summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2012-07-31 11:14:18 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2012-07-31 11:14:18 (GMT)
commit42c0766a53d88756158cd0157faa7c8560c70c3b (patch)
tree8ae8a41fd61a3f24afa68d7331566b23f782f70e /Lib
parent73a74dad3fe4ff69cdb1ecce73484c1574f93256 (diff)
downloadcpython-42c0766a53d88756158cd0157faa7c8560c70c3b.zip
cpython-42c0766a53d88756158cd0157faa7c8560c70c3b.tar.gz
cpython-42c0766a53d88756158cd0157faa7c8560c70c3b.tar.bz2
Close #15486: Simplify the mechanism used to remove importlib frames from tracebacks when they just introduce irrelevant noise
Diffstat (limited to 'Lib')
-rw-r--r--Lib/importlib/_bootstrap.py65
-rw-r--r--Lib/test/test_import.py6
2 files changed, 27 insertions, 44 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
index 6a869f7..5980141 100644
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -297,8 +297,20 @@ def _lock_unlock_module(name):
else:
lock.release()
+# Frame stripping magic ###############################################
-# Finder/loader utility code ##################################################
+def _call_with_frames_removed(f, *args, **kwds):
+ """remove_importlib_frames in import.c will always remove sequences
+ of importlib frames that end with a call to this function
+
+ Use it instead of a normal call in places where including the importlib
+ frames introduces unwanted noise into the traceback (e.g. when executing
+ module code)
+ """
+ return f(*args, **kwds)
+
+
+# Finder/loader utility code ###############################################
"""Magic word to reject .pyc files generated by other Python versions.
It should change for each incompatible change to the bytecode.
@@ -629,20 +641,13 @@ class BuiltinImporter:
"""Load a built-in module."""
is_reload = fullname in sys.modules
try:
- return cls._exec_module(fullname)
+ return _call_with_frames_removed(_imp.init_builtin, fullname)
except:
if not is_reload and fullname in sys.modules:
del sys.modules[fullname]
raise
@classmethod
- def _exec_module(cls, fullname):
- """Helper for load_module, allowing to isolate easily (when
- looking at a traceback) whether an error comes from executing
- an imported module's code."""
- return _imp.init_builtin(fullname)
-
- @classmethod
@_requires_builtin
def get_code(cls, fullname):
"""Return None as built-in modules do not have code objects."""
@@ -687,7 +692,7 @@ class FrozenImporter:
"""Load a frozen module."""
is_reload = fullname in sys.modules
try:
- m = cls._exec_module(fullname)
+ m = _call_with_frames_removed(_imp.init_frozen, fullname)
# Let our own module_repr() method produce a suitable repr.
del m.__file__
return m
@@ -714,13 +719,6 @@ class FrozenImporter:
"""Return if the frozen module is a package."""
return _imp.is_frozen_package(fullname)
- @classmethod
- def _exec_module(cls, fullname):
- """Helper for load_module, allowing to isolate easily (when
- looking at a traceback) whether an error comes from executing
- an imported module's code."""
- return _imp.init_frozen(fullname)
-
class WindowsRegistryImporter:
@@ -850,15 +848,9 @@ class _LoaderBasics:
else:
module.__package__ = module.__package__.rpartition('.')[0]
module.__loader__ = self
- self._exec_module(code_object, module.__dict__)
+ _call_with_frames_removed(exec, code_object, module.__dict__)
return module
- def _exec_module(self, code_object, module_dict):
- """Helper for _load_module, allowing to isolate easily (when
- looking at a traceback) whether an error comes from executing
- an imported module's code."""
- exec(code_object, module_dict)
-
class SourceLoader(_LoaderBasics):
@@ -956,8 +948,9 @@ class SourceLoader(_LoaderBasics):
raise ImportError(msg.format(bytecode_path),
name=fullname, path=bytecode_path)
source_bytes = self.get_data(source_path)
- code_object = compile(source_bytes, source_path, 'exec',
- dont_inherit=True)
+ code_object = _call_with_frames_removed(compile,
+ source_bytes, source_path, 'exec',
+ dont_inherit=True)
_verbose_message('code object from {}', source_path)
if (not sys.dont_write_bytecode and bytecode_path is not None and
source_mtime is not None):
@@ -1093,7 +1086,8 @@ class ExtensionFileLoader:
"""Load an extension module."""
is_reload = fullname in sys.modules
try:
- module = self._exec_module(fullname, self.path)
+ module = _call_with_frames_removed(_imp.load_dynamic,
+ fullname, self.path)
_verbose_message('extension module loaded from {!r}', self.path)
return module
except:
@@ -1113,12 +1107,6 @@ class ExtensionFileLoader:
"""Return None as extension modules have no source code."""
return None
- def _exec_module(self, fullname, path):
- """Helper for load_module, allowing to isolate easily (when
- looking at a traceback) whether an error comes from executing
- an imported module's code."""
- return _imp.load_dynamic(fullname, path)
-
class _NamespacePath:
"""Represents a namespace package's path. It uses the module name
@@ -1472,7 +1460,7 @@ def _find_and_load_unlocked(name, import_):
parent = name.rpartition('.')[0]
if parent:
if parent not in sys.modules:
- _recursive_import(import_, parent)
+ _call_with_frames_removed(import_, parent)
# Crazy side-effects!
if name in sys.modules:
return sys.modules[name]
@@ -1550,13 +1538,6 @@ def _gcd_import(name, package=None, level=0):
_lock_unlock_module(name)
return module
-def _recursive_import(import_, name):
- """Common exit point for recursive calls to the import machinery
-
- This simplifies the process of stripping importlib from tracebacks
- """
- return import_(name)
-
def _handle_fromlist(module, fromlist, import_):
"""Figure out what __import__ should return.
@@ -1575,7 +1556,7 @@ def _handle_fromlist(module, fromlist, import_):
fromlist.extend(module.__all__)
for x in fromlist:
if not hasattr(module, x):
- _recursive_import(import_,
+ _call_with_frames_removed(import_,
'{}.{}'.format(module.__name__, x))
return module
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
index 3e61577..7089328 100644
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -785,11 +785,13 @@ class ImportTracebackTests(unittest.TestCase):
sys.path[:] = self.old_path
rmtree(TESTFN)
- def create_module(self, mod, contents):
- with open(os.path.join(TESTFN, mod + ".py"), "w") as f:
+ def create_module(self, mod, contents, ext=".py"):
+ fname = os.path.join(TESTFN, mod + ext)
+ with open(fname, "w") as f:
f.write(contents)
self.addCleanup(unload, mod)
importlib.invalidate_caches()
+ return fname
def assert_traceback(self, tb, files):
deduped_files = []