diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_zipimport.py | 8 | ||||
-rw-r--r-- | Lib/zipimport.py | 38 |
2 files changed, 24 insertions, 22 deletions
diff --git a/Lib/test/test_zipimport.py b/Lib/test/test_zipimport.py index 6dea2b1628..d59ef1ed6f 100644 --- a/Lib/test/test_zipimport.py +++ b/Lib/test/test_zipimport.py @@ -242,10 +242,10 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase): files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)} try: self.doTest(".py", files, TESTMOD) - except ImportError: - pass - else: - self.fail("expected ImportError; import from bad pyc") + self.fail("This should not be reached") + except zipimport.ZipImportError as exc: + self.assertIsInstance(exc.__cause__, ImportError) + self.assertIn("magic number", exc.__cause__.msg) def testBadMTime(self): badtime_pyc = bytearray(test_pyc) diff --git a/Lib/zipimport.py b/Lib/zipimport.py index 02e4fd38d0..ce3e00e24f 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) |