aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIrit Katriel <iritkatriel@yahoo.com>2020-12-19 00:09:54 +0000
committerGitHub <noreply@github.com>2020-12-18 16:09:54 -0800
commitfb34096140bbb74c81500dd8bbc3c69c1d24d9ab (patch)
tree0b3dd85011b4d6f36068f0e69f38666178a10b48 /Lib/zipimport.py
parentbpo-36769: Document that fnmatch.filter supports any kind of iterable (#13039) (diff)
downloadcpython-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.py38
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)