diff options
author | Irit Katriel <iritkatriel@yahoo.com> | 2020-12-19 00:09:54 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-18 16:09:54 -0800 |
commit | fb34096140bbb74c81500dd8bbc3c69c1d24d9ab (patch) | |
tree | 0b3dd85011b4d6f36068f0e69f38666178a10b48 /Lib/zipimport.py | |
parent | bpo-36769: Document that fnmatch.filter supports any kind of iterable (#13039) (diff) | |
download | cpython-fb34096140bbb74c81500dd8bbc3c69c1d24d9ab.tar.gz cpython-fb34096140bbb74c81500dd8bbc3c69c1d24d9ab.tar.bz2 cpython-fb34096140bbb74c81500dd8bbc3c69c1d24d9ab.zip |
bpo-24792: Fix zipimporter masking the cause of import errors (GH-22204)
zipimport's _unmarshal_code swallows import errors and then _get_module_code doesn't know the cause of the error, and returns the generic, and sometimes incorrect, 'could not find...'.
Automerge-Triggered-By: GH:brettcannon
Diffstat (limited to 'Lib/zipimport.py')
-rw-r--r-- | Lib/zipimport.py | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/Lib/zipimport.py b/Lib/zipimport.py index 02e4fd38d0e..ce3e00e24fa 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -185,7 +185,7 @@ class zipimporter(_bootstrap_external._LoaderBasics): """get_code(fullname) -> code object. Return the code object for the specified module. Raise ZipImportError - if the module couldn't be found. + if the module couldn't be imported. """ code, ispackage, modpath = _get_module_code(self, fullname) return code @@ -215,7 +215,8 @@ class zipimporter(_bootstrap_external._LoaderBasics): def get_filename(self, fullname): """get_filename(fullname) -> filename string. - Return the filename for the specified module. + Return the filename for the specified module or raise ZipImportError + if it couldn't be imported. """ # Deciding the filename requires working out where the code # would come from if the module was actually loaded @@ -267,7 +268,7 @@ class zipimporter(_bootstrap_external._LoaderBasics): Load the module specified by 'fullname'. 'fullname' must be the fully qualified (dotted) module name. It returns the imported - module, or raises ZipImportError if it wasn't found. + module, or raises ZipImportError if it could not be imported. Deprecated since Python 3.10. Use exec_module() instead. """ @@ -613,20 +614,15 @@ def _eq_mtime(t1, t2): # Given the contents of a .py[co] file, unmarshal the data -# and return the code object. Return None if it the magic word doesn't -# match, or if the recorded .py[co] metadata does not match the source, -# (we do this instead of raising an exception as we fall back -# to .py if available and we don't want to mask other errors). +# and return the code object. Raises ImportError it the magic word doesn't +# match, or if the recorded .py[co] metadata does not match the source. def _unmarshal_code(self, pathname, fullpath, fullname, data): exc_details = { 'name': fullname, 'path': fullpath, } - try: - flags = _bootstrap_external._classify_pyc(data, fullname, exc_details) - except ImportError: - return None + flags = _bootstrap_external._classify_pyc(data, fullname, exc_details) hash_based = flags & 0b1 != 0 if hash_based: @@ -640,11 +636,8 @@ def _unmarshal_code(self, pathname, fullpath, fullname, data): source_bytes, ) - try: - _bootstrap_external._validate_hash_pyc( - data, source_hash, fullname, exc_details) - except ImportError: - return None + _bootstrap_external._validate_hash_pyc( + data, source_hash, fullname, exc_details) else: source_mtime, source_size = \ _get_mtime_and_size_of_source(self, fullpath) @@ -730,6 +723,7 @@ def _get_pyc_source(self, path): # 'fullname'. def _get_module_code(self, fullname): path = _get_module_path(self, fullname) + import_error = None for suffix, isbytecode, ispackage in _zip_searchorder: fullpath = path + suffix _bootstrap._verbose_message('trying {}{}{}', self.archive, path_sep, fullpath, verbosity=2) @@ -740,8 +734,12 @@ def _get_module_code(self, fullname): else: modpath = toc_entry[0] data = _get_data(self.archive, toc_entry) + code = None if isbytecode: - code = _unmarshal_code(self, modpath, fullpath, fullname, data) + try: + code = _unmarshal_code(self, modpath, fullpath, fullname, data) + except ImportError as exc: + import_error = exc else: code = _compile_source(modpath, data) if code is None: @@ -751,4 +749,8 @@ def _get_module_code(self, fullname): modpath = toc_entry[0] return code, ispackage, modpath else: - raise ZipImportError(f"can't find module {fullname!r}", name=fullname) + if import_error: + msg = f"module load failed: {import_error}" + raise ZipImportError(msg, name=fullname) from import_error + else: + raise ZipImportError(f"can't find module {fullname!r}", name=fullname) |