mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Update zipimport from CPython 3.10.5
This commit is contained in:
1 parent
d7437e1975
commit
97e6542e93
2 files changed
+95
-115
No files matched your search
Vendored
+20
-20
@@ -463,15 +463,15 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
|
||||
# PEP 302
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
find_mod = zi.find_module('spam')
|
||||
self.assertIsNotNone(find_mod)
|
||||
self.assertIsInstance(find_mod, zipimport.zipimporter)
|
||||
self.assertFalse(find_mod.is_package('spam'))
|
||||
load_mod = find_mod.load_module('spam')
|
||||
self.assertEqual(find_mod.get_filename('spam'), load_mod.__file__)
|
||||
find_mod = zi.find_module('spam')
|
||||
self.assertIsNotNone(find_mod)
|
||||
self.assertIsInstance(find_mod, zipimport.zipimporter)
|
||||
self.assertFalse(find_mod.is_package('spam'))
|
||||
load_mod = find_mod.load_module('spam')
|
||||
self.assertEqual(find_mod.get_filename('spam'), load_mod.__file__)
|
||||
|
||||
mod = zi.load_module(TESTPACK)
|
||||
self.assertEqual(zi.get_filename(TESTPACK), mod.__file__)
|
||||
mod = zi.load_module(TESTPACK)
|
||||
self.assertEqual(zi.get_filename(TESTPACK), mod.__file__)
|
||||
|
||||
# PEP 451
|
||||
spec = zi.find_spec('spam')
|
||||
@@ -580,8 +580,8 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
|
||||
# PEP 302
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
mod = zi.load_module(TESTPACK2)
|
||||
self.assertEqual(zi.get_filename(TESTPACK2), mod.__file__)
|
||||
mod = zi.load_module(TESTPACK2)
|
||||
self.assertEqual(zi.get_filename(TESTPACK2), mod.__file__)
|
||||
# PEP 451
|
||||
spec = zi.find_spec(TESTPACK2)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
@@ -596,13 +596,13 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
|
||||
# PEP 302
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
find_mod_dotted = zi2.find_module(TESTMOD)
|
||||
self.assertIsNotNone(find_mod_dotted)
|
||||
self.assertIsInstance(find_mod_dotted, zipimport.zipimporter)
|
||||
self.assertFalse(zi2.is_package(TESTMOD))
|
||||
load_mod = find_mod_dotted.load_module(TESTMOD)
|
||||
self.assertEqual(
|
||||
find_mod_dotted.get_filename(TESTMOD), load_mod.__file__)
|
||||
find_mod_dotted = zi2.find_module(TESTMOD)
|
||||
self.assertIsNotNone(find_mod_dotted)
|
||||
self.assertIsInstance(find_mod_dotted, zipimport.zipimporter)
|
||||
self.assertFalse(zi2.is_package(TESTMOD))
|
||||
load_mod = find_mod_dotted.load_module(TESTMOD)
|
||||
self.assertEqual(
|
||||
find_mod_dotted.get_filename(TESTMOD), load_mod.__file__)
|
||||
|
||||
# PEP 451
|
||||
spec = zi2.find_spec(TESTMOD)
|
||||
@@ -842,7 +842,7 @@ class BadFileZipImportTestCase(unittest.TestCase):
|
||||
try:
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
self.assertRaises(TypeError, z.load_module, None)
|
||||
self.assertRaises(TypeError, z.load_module, None)
|
||||
self.assertRaises(TypeError, z.find_module, None)
|
||||
self.assertRaises(TypeError, z.find_spec, None)
|
||||
self.assertRaises(TypeError, z.exec_module, None)
|
||||
@@ -857,7 +857,7 @@ class BadFileZipImportTestCase(unittest.TestCase):
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore", DeprecationWarning)
|
||||
self.assertRaises(error, z.load_module, 'abc')
|
||||
self.assertRaises(error, z.load_module, 'abc')
|
||||
self.assertRaises(error, z.get_code, 'abc')
|
||||
self.assertRaises(OSError, z.get_data, 'abc')
|
||||
self.assertRaises(error, z.get_source, 'abc')
|
||||
@@ -867,7 +867,7 @@ class BadFileZipImportTestCase(unittest.TestCase):
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
os_helper.unlink(TESTMOD)
|
||||
os_helper.unlink(TESTMOD)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Vendored
+75
-95
@@ -22,6 +22,7 @@ import _io # for open
|
||||
import marshal # for loads
|
||||
import sys # for modules
|
||||
import time # for mktime
|
||||
import _warnings # For warn()
|
||||
|
||||
__all__ = ['ZipImportError', 'zipimporter']
|
||||
|
||||
@@ -42,7 +43,7 @@ END_CENTRAL_DIR_SIZE = 22
|
||||
STRING_END_ARCHIVE = b'PK\x05\x06'
|
||||
MAX_COMMENT_LEN = (1 << 16) - 1
|
||||
|
||||
class zipimporter:
|
||||
class zipimporter(_bootstrap_external._LoaderBasics):
|
||||
"""zipimporter(archivepath) -> zipimporter object
|
||||
|
||||
Create a new zipimporter instance. 'archivepath' must be a path to
|
||||
@@ -115,7 +116,12 @@ class zipimporter:
|
||||
full path name if it's possibly a portion of a namespace package,
|
||||
or None otherwise. The optional 'path' argument is ignored -- it's
|
||||
there for compatibility with the importer protocol.
|
||||
|
||||
Deprecated since Python 3.10. Use find_spec() instead.
|
||||
"""
|
||||
_warnings.warn("zipimporter.find_loader() is deprecated and slated for "
|
||||
"removal in Python 3.12; use find_spec() instead",
|
||||
DeprecationWarning)
|
||||
mi = _get_module_info(self, fullname)
|
||||
if mi is not None:
|
||||
# This is a module or package.
|
||||
@@ -146,15 +152,46 @@ class zipimporter:
|
||||
instance itself if the module was found, or None if it wasn't.
|
||||
The optional 'path' argument is ignored -- it's there for compatibility
|
||||
with the importer protocol.
|
||||
|
||||
Deprecated since Python 3.10. Use find_spec() instead.
|
||||
"""
|
||||
_warnings.warn("zipimporter.find_module() is deprecated and slated for "
|
||||
"removal in Python 3.12; use find_spec() instead",
|
||||
DeprecationWarning)
|
||||
return self.find_loader(fullname, path)[0]
|
||||
|
||||
def find_spec(self, fullname, target=None):
|
||||
"""Create a ModuleSpec for the specified module.
|
||||
|
||||
Returns None if the module cannot be found.
|
||||
"""
|
||||
module_info = _get_module_info(self, fullname)
|
||||
if module_info is not None:
|
||||
return _bootstrap.spec_from_loader(fullname, self, is_package=module_info)
|
||||
else:
|
||||
# Not a module or regular package. See if this is a directory, and
|
||||
# therefore possibly a portion of a namespace package.
|
||||
|
||||
# We're only interested in the last path component of fullname
|
||||
# earlier components are recorded in self.prefix.
|
||||
modpath = _get_module_path(self, fullname)
|
||||
if _is_dir(self, modpath):
|
||||
# This is possibly a portion of a namespace
|
||||
# package. Return the string representing its path,
|
||||
# without a trailing separator.
|
||||
path = f'{self.archive}{path_sep}{modpath}'
|
||||
spec = _bootstrap.ModuleSpec(name=fullname, loader=None,
|
||||
is_package=True)
|
||||
spec.submodule_search_locations.append(path)
|
||||
return spec
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_code(self, fullname):
|
||||
"""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
|
||||
@@ -184,7 +221,8 @@ class zipimporter:
|
||||
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
|
||||
@@ -236,8 +274,13 @@ class zipimporter:
|
||||
|
||||
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.
|
||||
"""
|
||||
msg = ("zipimport.zipimporter.load_module() is deprecated and slated for "
|
||||
"removal in Python 3.12; use exec_module() instead")
|
||||
_warnings.warn(msg, DeprecationWarning)
|
||||
code, ispackage, modpath = _get_module_code(self, fullname)
|
||||
mod = sys.modules.get(fullname)
|
||||
if mod is None or not isinstance(mod, _module_type):
|
||||
@@ -280,11 +323,18 @@ class zipimporter:
|
||||
return None
|
||||
except ZipImportError:
|
||||
return None
|
||||
if not _ZipImportResourceReader._registered:
|
||||
from importlib.abc import ResourceReader
|
||||
ResourceReader.register(_ZipImportResourceReader)
|
||||
_ZipImportResourceReader._registered = True
|
||||
return _ZipImportResourceReader(self, fullname)
|
||||
from importlib.readers import ZipReader
|
||||
return ZipReader(self, fullname)
|
||||
|
||||
|
||||
def invalidate_caches(self):
|
||||
"""Reload the file data of the archive path."""
|
||||
try:
|
||||
self._files = _read_directory(self.archive)
|
||||
_zip_directory_cache[self.archive] = self._files
|
||||
except ZipImportError:
|
||||
_zip_directory_cache.pop(self.archive, None)
|
||||
self._files = {}
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
@@ -580,20 +630,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:
|
||||
@@ -607,11 +652,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)
|
||||
@@ -697,6 +739,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)
|
||||
@@ -707,8 +750,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:
|
||||
@@ -718,75 +765,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)
|
||||
|
||||
|
||||
class _ZipImportResourceReader:
|
||||
"""Private class used to support ZipImport.get_resource_reader().
|
||||
|
||||
This class is allowed to reference all the innards and private parts of
|
||||
the zipimporter.
|
||||
"""
|
||||
_registered = False
|
||||
|
||||
def __init__(self, zipimporter, fullname):
|
||||
self.zipimporter = zipimporter
|
||||
self.fullname = fullname
|
||||
|
||||
def open_resource(self, resource):
|
||||
fullname_as_path = self.fullname.replace('.', '/')
|
||||
path = f'{fullname_as_path}/{resource}'
|
||||
from io import BytesIO
|
||||
try:
|
||||
return BytesIO(self.zipimporter.get_data(path))
|
||||
except OSError:
|
||||
raise FileNotFoundError(path)
|
||||
|
||||
def resource_path(self, resource):
|
||||
# All resources are in the zip file, so there is no path to the file.
|
||||
# Raising FileNotFoundError tells the higher level API to extract the
|
||||
# binary data and create a temporary file.
|
||||
raise FileNotFoundError
|
||||
|
||||
def is_resource(self, name):
|
||||
# Maybe we could do better, but if we can get the data, it's a
|
||||
# resource. Otherwise it isn't.
|
||||
fullname_as_path = self.fullname.replace('.', '/')
|
||||
path = f'{fullname_as_path}/{name}'
|
||||
try:
|
||||
self.zipimporter.get_data(path)
|
||||
except OSError:
|
||||
return False
|
||||
return True
|
||||
|
||||
def contents(self):
|
||||
# This is a bit convoluted, because fullname will be a module path,
|
||||
# but _files is a list of file names relative to the top of the
|
||||
# archive's namespace. We want to compare file paths to find all the
|
||||
# names of things inside the module represented by fullname. So we
|
||||
# turn the module path of fullname into a file path relative to the
|
||||
# top of the archive, and then we iterate through _files looking for
|
||||
# names inside that "directory".
|
||||
from pathlib import Path
|
||||
fullname_path = Path(self.zipimporter.get_filename(self.fullname))
|
||||
relative_path = fullname_path.relative_to(self.zipimporter.archive)
|
||||
# Don't forget that fullname names a package, so its path will include
|
||||
# __init__.py, which we want to ignore.
|
||||
assert relative_path.name == '__init__.py'
|
||||
package_path = relative_path.parent
|
||||
subdirs_seen = set()
|
||||
for filename in self.zipimporter._files:
|
||||
try:
|
||||
relative = Path(filename).relative_to(package_path)
|
||||
except ValueError:
|
||||
continue
|
||||
# If the path of the file (which is relative to the top of the zip
|
||||
# namespace), relative to the package given when the resource
|
||||
# reader was created, has a parent, then it's a name in a
|
||||
# subdirectory and thus we skip it.
|
||||
parent_name = relative.parent.name
|
||||
if len(parent_name) == 0:
|
||||
yield relative.name
|
||||
elif parent_name not in subdirs_seen:
|
||||
subdirs_seen.add(parent_name)
|
||||
yield parent_name
|
||||
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)
|
||||
Reference in new issue
Block a user