This commit is contained in:
ton
2024-10-07 10:13:40 +07:00
parent aa1631742f
commit 3a7d696db6
9729 changed files with 1832837 additions and 161742 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+8 -2
View File
@@ -824,10 +824,16 @@ def _module_repr_from_spec(spec):
"""Return the repr to use for the module."""
name = '?' if spec.name is None else spec.name
if spec.origin is None:
if spec.loader is None:
loader = spec.loader
if loader is None:
return f'<module {name!r}>'
elif (
_bootstrap_external is not None
and isinstance(loader, _bootstrap_external.NamespaceLoader)
):
return f'<module {name!r} (namespace) from {list(loader._path)}>'
else:
return f'<module {name!r} (namespace) from {list(spec.loader._path)}>'
return f'<module {name!r} ({loader!r})>'
else:
if spec.has_location:
return f'<module {name!r} from {spec.origin!r}>'
+4
View File
@@ -413,6 +413,7 @@ _code_type = type(_write_atomic.__code__)
# Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative)
# Python 3.11a7 3493 (Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative)
# Python 3.11a7 3494 (New location info table)
# Python 3.11b4 3495 (Set line number of module's RESUME instr to 0 per PEP 626)
# Python 3.12a1 3500 (Remove PRECALL opcode)
# Python 3.12a1 3501 (YIELD_VALUE oparg == stack_depth)
# Python 3.12a1 3502 (LOAD_FAST_CHECK, no NULL-check in LOAD_FAST)
@@ -1449,6 +1450,9 @@ class PathFinder:
# https://bugs.python.org/issue45703
_NamespacePath._epoch += 1
from importlib.metadata import MetadataPathFinder
MetadataPathFinder.invalidate_caches()
@staticmethod
def _path_hooks(path):
"""Search sys.path_hooks for a finder for 'path'."""
+2 -1
View File
@@ -534,7 +534,7 @@ class Distribution(DeprecatedNonAbstract):
paths = (
(subdir / name)
.resolve()
.relative_to(self.locate_file('').resolve())
.relative_to(self.locate_file('').resolve(), walk_up=True)
.as_posix()
for name in text.splitlines()
)
@@ -795,6 +795,7 @@ class MetadataPathFinder(DistributionFinder):
path.search(prepared) for path in map(FastPath, paths)
)
@classmethod
def invalidate_caches(cls):
FastPath.__new__.cache_clear()
+4 -2
View File
@@ -31,8 +31,10 @@ class FileReader(abc.TraversableResources):
class ZipReader(abc.TraversableResources):
def __init__(self, loader, module):
_, _, name = module.rpartition('.')
self.prefix = loader.prefix.replace('\\', '/') + name + '/'
self.prefix = loader.prefix.replace('\\', '/')
if loader.is_package(module):
_, _, name = module.rpartition('.')
self.prefix += name + '/'
self.archive = loader.archive
def open_resource(self, resource):
+1 -1
View File
@@ -88,7 +88,7 @@ class ResourceHandle(Traversable):
def open(self, mode='r', *args, **kwargs):
stream = self.parent.reader.open_binary(self.name)
if 'b' not in mode:
stream = io.TextIOWrapper(*args, **kwargs)
stream = io.TextIOWrapper(stream, *args, **kwargs)
return stream
def joinpath(self, name):
+53 -31
View File
@@ -145,7 +145,7 @@ class _incompatible_extension_module_restrictions:
You can get the same effect as this function by implementing the
basic interface of multi-phase init (PEP 489) and lying about
support for mulitple interpreters (or per-interpreter GIL).
support for multiple interpreters (or per-interpreter GIL).
"""
def __init__(self, *, disable_check):
@@ -171,36 +171,53 @@ class _LazyModule(types.ModuleType):
def __getattribute__(self, attr):
"""Trigger the load of the module and return the attribute."""
# All module metadata must be garnered from __spec__ in order to avoid
# using mutated values.
# Stop triggering this method.
self.__class__ = types.ModuleType
# Get the original name to make sure no object substitution occurred
# in sys.modules.
original_name = self.__spec__.name
# Figure out exactly what attributes were mutated between the creation
# of the module and now.
attrs_then = self.__spec__.loader_state['__dict__']
attrs_now = self.__dict__
attrs_updated = {}
for key, value in attrs_now.items():
# Code that set the attribute may have kept a reference to the
# assigned object, making identity more important than equality.
if key not in attrs_then:
attrs_updated[key] = value
elif id(attrs_now[key]) != id(attrs_then[key]):
attrs_updated[key] = value
self.__spec__.loader.exec_module(self)
# If exec_module() was used directly there is no guarantee the module
# object was put into sys.modules.
if original_name in sys.modules:
if id(self) != id(sys.modules[original_name]):
raise ValueError(f"module object for {original_name!r} "
"substituted in sys.modules during a lazy "
"load")
# Update after loading since that's what would happen in an eager
# loading situation.
self.__dict__.update(attrs_updated)
__spec__ = object.__getattribute__(self, '__spec__')
loader_state = __spec__.loader_state
with loader_state['lock']:
# Only the first thread to get the lock should trigger the load
# and reset the module's class. The rest can now getattr().
if object.__getattribute__(self, '__class__') is _LazyModule:
# Reentrant calls from the same thread must be allowed to proceed without
# triggering the load again.
# exec_module() and self-referential imports are the primary ways this can
# happen, but in any case we must return something to avoid deadlock.
if loader_state['is_loading']:
return object.__getattribute__(self, attr)
loader_state['is_loading'] = True
__dict__ = object.__getattribute__(self, '__dict__')
# All module metadata must be gathered from __spec__ in order to avoid
# using mutated values.
# Get the original name to make sure no object substitution occurred
# in sys.modules.
original_name = __spec__.name
# Figure out exactly what attributes were mutated between the creation
# of the module and now.
attrs_then = loader_state['__dict__']
attrs_now = __dict__
attrs_updated = {}
for key, value in attrs_now.items():
# Code that set an attribute may have kept a reference to the
# assigned object, making identity more important than equality.
if key not in attrs_then:
attrs_updated[key] = value
elif id(attrs_now[key]) != id(attrs_then[key]):
attrs_updated[key] = value
__spec__.loader.exec_module(self)
# If exec_module() was used directly there is no guarantee the module
# object was put into sys.modules.
if original_name in sys.modules:
if id(self) != id(sys.modules[original_name]):
raise ValueError(f"module object for {original_name!r} "
"substituted in sys.modules during a lazy "
"load")
# Update after loading since that's what would happen in an eager
# loading situation.
__dict__.update(attrs_updated)
# Finally, stop triggering this method.
self.__class__ = types.ModuleType
return getattr(self, attr)
def __delattr__(self, attr):
@@ -235,6 +252,9 @@ class LazyLoader(Loader):
def exec_module(self, module):
"""Make the module load lazily."""
# Threading is only needed for lazy loading, and importlib.util can
# be pulled in at interpreter startup, so defer until needed.
import threading
module.__spec__.loader = self.loader
module.__loader__ = self.loader
# Don't need to worry about deep-copying as trying to set an attribute
@@ -244,5 +264,7 @@ class LazyLoader(Loader):
loader_state = {}
loader_state['__dict__'] = module.__dict__.copy()
loader_state['__class__'] = module.__class__
loader_state['lock'] = threading.RLock()
loader_state['is_loading'] = False
module.__spec__.loader_state = loader_state
module.__class__ = _LazyModule