Removed the Requirement to Install Python and NodeJS (Now Bundled with Borealis)
This commit is contained in:
136
Dependencies/Python/Lib/importlib/__init__.py
vendored
Normal file
136
Dependencies/Python/Lib/importlib/__init__.py
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
"""A pure Python implementation of import."""
|
||||
__all__ = ['__import__', 'import_module', 'invalidate_caches', 'reload']
|
||||
|
||||
# Bootstrap help #####################################################
|
||||
|
||||
# Until bootstrapping is complete, DO NOT import any modules that attempt
|
||||
# to import importlib._bootstrap (directly or indirectly). Since this
|
||||
# partially initialised package would be present in sys.modules, those
|
||||
# modules would get an uninitialised copy of the source version, instead
|
||||
# of a fully initialised version (either the frozen one or the one
|
||||
# initialised below if the frozen one is not available).
|
||||
import _imp # Just the builtin component, NOT the full Python module
|
||||
import sys
|
||||
|
||||
try:
|
||||
import _frozen_importlib as _bootstrap
|
||||
except ImportError:
|
||||
from . import _bootstrap
|
||||
_bootstrap._setup(sys, _imp)
|
||||
else:
|
||||
# importlib._bootstrap is the built-in import, ensure we don't create
|
||||
# a second copy of the module.
|
||||
_bootstrap.__name__ = 'importlib._bootstrap'
|
||||
_bootstrap.__package__ = 'importlib'
|
||||
try:
|
||||
_bootstrap.__file__ = __file__.replace('__init__.py', '_bootstrap.py')
|
||||
except NameError:
|
||||
# __file__ is not guaranteed to be defined, e.g. if this code gets
|
||||
# frozen by a tool like cx_Freeze.
|
||||
pass
|
||||
sys.modules['importlib._bootstrap'] = _bootstrap
|
||||
|
||||
try:
|
||||
import _frozen_importlib_external as _bootstrap_external
|
||||
except ImportError:
|
||||
from . import _bootstrap_external
|
||||
_bootstrap_external._set_bootstrap_module(_bootstrap)
|
||||
_bootstrap._bootstrap_external = _bootstrap_external
|
||||
else:
|
||||
_bootstrap_external.__name__ = 'importlib._bootstrap_external'
|
||||
_bootstrap_external.__package__ = 'importlib'
|
||||
try:
|
||||
_bootstrap_external.__file__ = __file__.replace('__init__.py', '_bootstrap_external.py')
|
||||
except NameError:
|
||||
# __file__ is not guaranteed to be defined, e.g. if this code gets
|
||||
# frozen by a tool like cx_Freeze.
|
||||
pass
|
||||
sys.modules['importlib._bootstrap_external'] = _bootstrap_external
|
||||
|
||||
# To simplify imports in test code
|
||||
_pack_uint32 = _bootstrap_external._pack_uint32
|
||||
_unpack_uint32 = _bootstrap_external._unpack_uint32
|
||||
|
||||
# Fully bootstrapped at this point, import whatever you like, circular
|
||||
# dependencies and startup overhead minimisation permitting :)
|
||||
|
||||
|
||||
# Public API #########################################################
|
||||
|
||||
from ._bootstrap import __import__
|
||||
|
||||
|
||||
def invalidate_caches():
|
||||
"""Call the invalidate_caches() method on all meta path finders stored in
|
||||
sys.meta_path (where implemented)."""
|
||||
for finder in sys.meta_path:
|
||||
if hasattr(finder, 'invalidate_caches'):
|
||||
finder.invalidate_caches()
|
||||
|
||||
|
||||
def import_module(name, package=None):
|
||||
"""Import a module.
|
||||
|
||||
The 'package' argument is required when performing a relative import. It
|
||||
specifies the package to use as the anchor point from which to resolve the
|
||||
relative import to an absolute import.
|
||||
|
||||
"""
|
||||
level = 0
|
||||
if name.startswith('.'):
|
||||
if not package:
|
||||
raise TypeError("the 'package' argument is required to perform a "
|
||||
f"relative import for {name!r}")
|
||||
for character in name:
|
||||
if character != '.':
|
||||
break
|
||||
level += 1
|
||||
return _bootstrap._gcd_import(name[level:], package, level)
|
||||
|
||||
|
||||
_RELOADING = {}
|
||||
|
||||
|
||||
def reload(module):
|
||||
"""Reload the module and return it.
|
||||
|
||||
The module must have been successfully imported before.
|
||||
|
||||
"""
|
||||
try:
|
||||
name = module.__spec__.name
|
||||
except AttributeError:
|
||||
try:
|
||||
name = module.__name__
|
||||
except AttributeError:
|
||||
raise TypeError("reload() argument must be a module") from None
|
||||
|
||||
if sys.modules.get(name) is not module:
|
||||
raise ImportError(f"module {name} not in sys.modules", name=name)
|
||||
if name in _RELOADING:
|
||||
return _RELOADING[name]
|
||||
_RELOADING[name] = module
|
||||
try:
|
||||
parent_name = name.rpartition('.')[0]
|
||||
if parent_name:
|
||||
try:
|
||||
parent = sys.modules[parent_name]
|
||||
except KeyError:
|
||||
raise ImportError(f"parent {parent_name!r} not in sys.modules",
|
||||
name=parent_name) from None
|
||||
else:
|
||||
pkgpath = parent.__path__
|
||||
else:
|
||||
pkgpath = None
|
||||
target = module
|
||||
spec = module.__spec__ = _bootstrap._find_spec(name, pkgpath, target)
|
||||
if spec is None:
|
||||
raise ModuleNotFoundError(f"spec not found for the module {name!r}", name=name)
|
||||
_bootstrap._exec(spec, module)
|
||||
# The module may have replaced itself in sys.modules!
|
||||
return sys.modules[name]
|
||||
finally:
|
||||
try:
|
||||
del _RELOADING[name]
|
||||
except KeyError:
|
||||
pass
|
BIN
Dependencies/Python/Lib/importlib/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/__pycache__/_abc.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/__pycache__/_abc.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/__pycache__/abc.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/__pycache__/abc.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/__pycache__/readers.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/__pycache__/readers.cpython-313.pyc
vendored
Normal file
Binary file not shown.
39
Dependencies/Python/Lib/importlib/_abc.py
vendored
Normal file
39
Dependencies/Python/Lib/importlib/_abc.py
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
"""Subset of importlib.abc used to reduce importlib.util imports."""
|
||||
from . import _bootstrap
|
||||
import abc
|
||||
|
||||
|
||||
class Loader(metaclass=abc.ABCMeta):
|
||||
|
||||
"""Abstract base class for import loaders."""
|
||||
|
||||
def create_module(self, spec):
|
||||
"""Return a module to initialize and into which to load.
|
||||
|
||||
This method should raise ImportError if anything prevents it
|
||||
from creating a new module. It may return None to indicate
|
||||
that the spec should create the new module.
|
||||
"""
|
||||
# By default, defer to default semantics for the new module.
|
||||
return None
|
||||
|
||||
# We don't define exec_module() here since that would break
|
||||
# hasattr checks we do to support backward compatibility.
|
||||
|
||||
def load_module(self, fullname):
|
||||
"""Return the loaded module.
|
||||
|
||||
The module must be added to sys.modules and have import-related
|
||||
attributes set properly. The fullname is a str.
|
||||
|
||||
ImportError is raised on failure.
|
||||
|
||||
This method is deprecated in favor of loader.exec_module(). If
|
||||
exec_module() exists then it is used to provide a backwards-compatible
|
||||
functionality for this method.
|
||||
|
||||
"""
|
||||
if not hasattr(self, 'exec_module'):
|
||||
raise ImportError
|
||||
# Warning implemented in _load_module_shim().
|
||||
return _bootstrap._load_module_shim(self, fullname)
|
1551
Dependencies/Python/Lib/importlib/_bootstrap.py
vendored
Normal file
1551
Dependencies/Python/Lib/importlib/_bootstrap.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1823
Dependencies/Python/Lib/importlib/_bootstrap_external.py
vendored
Normal file
1823
Dependencies/Python/Lib/importlib/_bootstrap_external.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
243
Dependencies/Python/Lib/importlib/abc.py
vendored
Normal file
243
Dependencies/Python/Lib/importlib/abc.py
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
"""Abstract base classes related to import."""
|
||||
from . import _bootstrap_external
|
||||
from . import machinery
|
||||
try:
|
||||
import _frozen_importlib
|
||||
except ImportError as exc:
|
||||
if exc.name != '_frozen_importlib':
|
||||
raise
|
||||
_frozen_importlib = None
|
||||
try:
|
||||
import _frozen_importlib_external
|
||||
except ImportError:
|
||||
_frozen_importlib_external = _bootstrap_external
|
||||
from ._abc import Loader
|
||||
import abc
|
||||
import warnings
|
||||
|
||||
from .resources import abc as _resources_abc
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Loader', 'MetaPathFinder', 'PathEntryFinder',
|
||||
'ResourceLoader', 'InspectLoader', 'ExecutionLoader',
|
||||
'FileLoader', 'SourceLoader',
|
||||
]
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
"""
|
||||
For backwards compatibility, continue to make names
|
||||
from _resources_abc available through this module. #93963
|
||||
"""
|
||||
if name in _resources_abc.__all__:
|
||||
obj = getattr(_resources_abc, name)
|
||||
warnings._deprecated(f"{__name__}.{name}", remove=(3, 14))
|
||||
globals()[name] = obj
|
||||
return obj
|
||||
raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
|
||||
|
||||
|
||||
def _register(abstract_cls, *classes):
|
||||
for cls in classes:
|
||||
abstract_cls.register(cls)
|
||||
if _frozen_importlib is not None:
|
||||
try:
|
||||
frozen_cls = getattr(_frozen_importlib, cls.__name__)
|
||||
except AttributeError:
|
||||
frozen_cls = getattr(_frozen_importlib_external, cls.__name__)
|
||||
abstract_cls.register(frozen_cls)
|
||||
|
||||
|
||||
class MetaPathFinder(metaclass=abc.ABCMeta):
|
||||
|
||||
"""Abstract base class for import finders on sys.meta_path."""
|
||||
|
||||
# We don't define find_spec() here since that would break
|
||||
# hasattr checks we do to support backward compatibility.
|
||||
|
||||
def invalidate_caches(self):
|
||||
"""An optional method for clearing the finder's cache, if any.
|
||||
This method is used by importlib.invalidate_caches().
|
||||
"""
|
||||
|
||||
_register(MetaPathFinder, machinery.BuiltinImporter, machinery.FrozenImporter,
|
||||
machinery.PathFinder, machinery.WindowsRegistryFinder)
|
||||
|
||||
|
||||
class PathEntryFinder(metaclass=abc.ABCMeta):
|
||||
|
||||
"""Abstract base class for path entry finders used by PathFinder."""
|
||||
|
||||
def invalidate_caches(self):
|
||||
"""An optional method for clearing the finder's cache, if any.
|
||||
This method is used by PathFinder.invalidate_caches().
|
||||
"""
|
||||
|
||||
_register(PathEntryFinder, machinery.FileFinder)
|
||||
|
||||
|
||||
class ResourceLoader(Loader):
|
||||
|
||||
"""Abstract base class for loaders which can return data from their
|
||||
back-end storage.
|
||||
|
||||
This ABC represents one of the optional protocols specified by PEP 302.
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_data(self, path):
|
||||
"""Abstract method which when implemented should return the bytes for
|
||||
the specified path. The path must be a str."""
|
||||
raise OSError
|
||||
|
||||
|
||||
class InspectLoader(Loader):
|
||||
|
||||
"""Abstract base class for loaders which support inspection about the
|
||||
modules they can load.
|
||||
|
||||
This ABC represents one of the optional protocols specified by PEP 302.
|
||||
|
||||
"""
|
||||
|
||||
def is_package(self, fullname):
|
||||
"""Optional method which when implemented should return whether the
|
||||
module is a package. The fullname is a str. Returns a bool.
|
||||
|
||||
Raises ImportError if the module cannot be found.
|
||||
"""
|
||||
raise ImportError
|
||||
|
||||
def get_code(self, fullname):
|
||||
"""Method which returns the code object for the module.
|
||||
|
||||
The fullname is a str. Returns a types.CodeType if possible, else
|
||||
returns None if a code object does not make sense
|
||||
(e.g. built-in module). Raises ImportError if the module cannot be
|
||||
found.
|
||||
"""
|
||||
source = self.get_source(fullname)
|
||||
if source is None:
|
||||
return None
|
||||
return self.source_to_code(source)
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_source(self, fullname):
|
||||
"""Abstract method which should return the source code for the
|
||||
module. The fullname is a str. Returns a str.
|
||||
|
||||
Raises ImportError if the module cannot be found.
|
||||
"""
|
||||
raise ImportError
|
||||
|
||||
@staticmethod
|
||||
def source_to_code(data, path='<string>'):
|
||||
"""Compile 'data' into a code object.
|
||||
|
||||
The 'data' argument can be anything that compile() can handle. The'path'
|
||||
argument should be where the data was retrieved (when applicable)."""
|
||||
return compile(data, path, 'exec', dont_inherit=True)
|
||||
|
||||
exec_module = _bootstrap_external._LoaderBasics.exec_module
|
||||
load_module = _bootstrap_external._LoaderBasics.load_module
|
||||
|
||||
_register(InspectLoader, machinery.BuiltinImporter, machinery.FrozenImporter, machinery.NamespaceLoader)
|
||||
|
||||
|
||||
class ExecutionLoader(InspectLoader):
|
||||
|
||||
"""Abstract base class for loaders that wish to support the execution of
|
||||
modules as scripts.
|
||||
|
||||
This ABC represents one of the optional protocols specified in PEP 302.
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_filename(self, fullname):
|
||||
"""Abstract method which should return the value that __file__ is to be
|
||||
set to.
|
||||
|
||||
Raises ImportError if the module cannot be found.
|
||||
"""
|
||||
raise ImportError
|
||||
|
||||
def get_code(self, fullname):
|
||||
"""Method to return the code object for fullname.
|
||||
|
||||
Should return None if not applicable (e.g. built-in module).
|
||||
Raise ImportError if the module cannot be found.
|
||||
"""
|
||||
source = self.get_source(fullname)
|
||||
if source is None:
|
||||
return None
|
||||
try:
|
||||
path = self.get_filename(fullname)
|
||||
except ImportError:
|
||||
return self.source_to_code(source)
|
||||
else:
|
||||
return self.source_to_code(source, path)
|
||||
|
||||
_register(
|
||||
ExecutionLoader,
|
||||
machinery.ExtensionFileLoader,
|
||||
machinery.AppleFrameworkLoader,
|
||||
)
|
||||
|
||||
|
||||
class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader):
|
||||
|
||||
"""Abstract base class partially implementing the ResourceLoader and
|
||||
ExecutionLoader ABCs."""
|
||||
|
||||
_register(FileLoader, machinery.SourceFileLoader,
|
||||
machinery.SourcelessFileLoader)
|
||||
|
||||
|
||||
class SourceLoader(_bootstrap_external.SourceLoader, ResourceLoader, ExecutionLoader):
|
||||
|
||||
"""Abstract base class for loading source code (and optionally any
|
||||
corresponding bytecode).
|
||||
|
||||
To support loading from source code, the abstractmethods inherited from
|
||||
ResourceLoader and ExecutionLoader need to be implemented. To also support
|
||||
loading from bytecode, the optional methods specified directly by this ABC
|
||||
is required.
|
||||
|
||||
Inherited abstractmethods not implemented in this ABC:
|
||||
|
||||
* ResourceLoader.get_data
|
||||
* ExecutionLoader.get_filename
|
||||
|
||||
"""
|
||||
|
||||
def path_mtime(self, path):
|
||||
"""Return the (int) modification time for the path (str)."""
|
||||
if self.path_stats.__func__ is SourceLoader.path_stats:
|
||||
raise OSError
|
||||
return int(self.path_stats(path)['mtime'])
|
||||
|
||||
def path_stats(self, path):
|
||||
"""Return a metadata dict for the source pointed to by the path (str).
|
||||
Possible keys:
|
||||
- 'mtime' (mandatory) is the numeric timestamp of last source
|
||||
code modification;
|
||||
- 'size' (optional) is the size in bytes of the source code.
|
||||
"""
|
||||
if self.path_mtime.__func__ is SourceLoader.path_mtime:
|
||||
raise OSError
|
||||
return {'mtime': self.path_mtime(path)}
|
||||
|
||||
def set_data(self, path, data):
|
||||
"""Write the bytes to the path (if possible).
|
||||
|
||||
Accepts a str path and data as bytes.
|
||||
|
||||
Any needed intermediary directories are to be created. If for some
|
||||
reason the file cannot be written because of permissions, fail
|
||||
silently.
|
||||
"""
|
||||
|
||||
_register(SourceLoader, machinery.SourceFileLoader)
|
21
Dependencies/Python/Lib/importlib/machinery.py
vendored
Normal file
21
Dependencies/Python/Lib/importlib/machinery.py
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
"""The machinery of importlib: finders, loaders, hooks, etc."""
|
||||
|
||||
from ._bootstrap import ModuleSpec
|
||||
from ._bootstrap import BuiltinImporter
|
||||
from ._bootstrap import FrozenImporter
|
||||
from ._bootstrap_external import (SOURCE_SUFFIXES, DEBUG_BYTECODE_SUFFIXES,
|
||||
OPTIMIZED_BYTECODE_SUFFIXES, BYTECODE_SUFFIXES,
|
||||
EXTENSION_SUFFIXES)
|
||||
from ._bootstrap_external import WindowsRegistryFinder
|
||||
from ._bootstrap_external import PathFinder
|
||||
from ._bootstrap_external import FileFinder
|
||||
from ._bootstrap_external import SourceFileLoader
|
||||
from ._bootstrap_external import SourcelessFileLoader
|
||||
from ._bootstrap_external import ExtensionFileLoader
|
||||
from ._bootstrap_external import AppleFrameworkLoader
|
||||
from ._bootstrap_external import NamespaceLoader
|
||||
|
||||
|
||||
def all_suffixes():
|
||||
"""Returns a list of all recognized module suffixes for this process"""
|
||||
return SOURCE_SUFFIXES + BYTECODE_SUFFIXES + EXTENSION_SUFFIXES
|
1093
Dependencies/Python/Lib/importlib/metadata/__init__.py
vendored
Normal file
1093
Dependencies/Python/Lib/importlib/metadata/__init__.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_adapters.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_adapters.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_collections.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_collections.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_functools.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_functools.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_itertools.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_itertools.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_meta.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_meta.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_text.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/metadata/__pycache__/_text.cpython-313.pyc
vendored
Normal file
Binary file not shown.
89
Dependencies/Python/Lib/importlib/metadata/_adapters.py
vendored
Normal file
89
Dependencies/Python/Lib/importlib/metadata/_adapters.py
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
import functools
|
||||
import warnings
|
||||
import re
|
||||
import textwrap
|
||||
import email.message
|
||||
|
||||
from ._text import FoldedCase
|
||||
|
||||
|
||||
# Do not remove prior to 2024-01-01 or Python 3.14
|
||||
_warn = functools.partial(
|
||||
warnings.warn,
|
||||
"Implicit None on return values is deprecated and will raise KeyErrors.",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
|
||||
|
||||
class Message(email.message.Message):
|
||||
multiple_use_keys = set(
|
||||
map(
|
||||
FoldedCase,
|
||||
[
|
||||
'Classifier',
|
||||
'Obsoletes-Dist',
|
||||
'Platform',
|
||||
'Project-URL',
|
||||
'Provides-Dist',
|
||||
'Provides-Extra',
|
||||
'Requires-Dist',
|
||||
'Requires-External',
|
||||
'Supported-Platform',
|
||||
'Dynamic',
|
||||
],
|
||||
)
|
||||
)
|
||||
"""
|
||||
Keys that may be indicated multiple times per PEP 566.
|
||||
"""
|
||||
|
||||
def __new__(cls, orig: email.message.Message):
|
||||
res = super().__new__(cls)
|
||||
vars(res).update(vars(orig))
|
||||
return res
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self._headers = self._repair_headers()
|
||||
|
||||
# suppress spurious error from mypy
|
||||
def __iter__(self):
|
||||
return super().__iter__()
|
||||
|
||||
def __getitem__(self, item):
|
||||
"""
|
||||
Warn users that a ``KeyError`` can be expected when a
|
||||
missing key is supplied. Ref python/importlib_metadata#371.
|
||||
"""
|
||||
res = super().__getitem__(item)
|
||||
if res is None:
|
||||
_warn()
|
||||
return res
|
||||
|
||||
def _repair_headers(self):
|
||||
def redent(value):
|
||||
"Correct for RFC822 indentation"
|
||||
if not value or '\n' not in value:
|
||||
return value
|
||||
return textwrap.dedent(' ' * 8 + value)
|
||||
|
||||
headers = [(key, redent(value)) for key, value in vars(self)['_headers']]
|
||||
if self._payload:
|
||||
headers.append(('Description', self.get_payload()))
|
||||
return headers
|
||||
|
||||
@property
|
||||
def json(self):
|
||||
"""
|
||||
Convert PackageMetadata to a JSON-compatible format
|
||||
per PEP 0566.
|
||||
"""
|
||||
|
||||
def transform(key):
|
||||
value = self.get_all(key) if key in self.multiple_use_keys else self[key]
|
||||
if key == 'Keywords':
|
||||
value = re.split(r'\s+', value)
|
||||
tk = key.lower().replace('-', '_')
|
||||
return tk, value
|
||||
|
||||
return dict(map(transform, map(FoldedCase, self)))
|
30
Dependencies/Python/Lib/importlib/metadata/_collections.py
vendored
Normal file
30
Dependencies/Python/Lib/importlib/metadata/_collections.py
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
import collections
|
||||
|
||||
|
||||
# from jaraco.collections 3.3
|
||||
class FreezableDefaultDict(collections.defaultdict):
|
||||
"""
|
||||
Often it is desirable to prevent the mutation of
|
||||
a default dict after its initial construction, such
|
||||
as to prevent mutation during iteration.
|
||||
|
||||
>>> dd = FreezableDefaultDict(list)
|
||||
>>> dd[0].append('1')
|
||||
>>> dd.freeze()
|
||||
>>> dd[1]
|
||||
[]
|
||||
>>> len(dd)
|
||||
1
|
||||
"""
|
||||
|
||||
def __missing__(self, key):
|
||||
return getattr(self, '_frozen', super().__missing__)(key)
|
||||
|
||||
def freeze(self):
|
||||
self._frozen = lambda key: self.default_factory()
|
||||
|
||||
|
||||
class Pair(collections.namedtuple('Pair', 'name value')):
|
||||
@classmethod
|
||||
def parse(cls, text):
|
||||
return cls(*map(str.strip, text.split("=", 1)))
|
104
Dependencies/Python/Lib/importlib/metadata/_functools.py
vendored
Normal file
104
Dependencies/Python/Lib/importlib/metadata/_functools.py
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
import types
|
||||
import functools
|
||||
|
||||
|
||||
# from jaraco.functools 3.3
|
||||
def method_cache(method, cache_wrapper=None):
|
||||
"""
|
||||
Wrap lru_cache to support storing the cache data in the object instances.
|
||||
|
||||
Abstracts the common paradigm where the method explicitly saves an
|
||||
underscore-prefixed protected property on first call and returns that
|
||||
subsequently.
|
||||
|
||||
>>> class MyClass:
|
||||
... calls = 0
|
||||
...
|
||||
... @method_cache
|
||||
... def method(self, value):
|
||||
... self.calls += 1
|
||||
... return value
|
||||
|
||||
>>> a = MyClass()
|
||||
>>> a.method(3)
|
||||
3
|
||||
>>> for x in range(75):
|
||||
... res = a.method(x)
|
||||
>>> a.calls
|
||||
75
|
||||
|
||||
Note that the apparent behavior will be exactly like that of lru_cache
|
||||
except that the cache is stored on each instance, so values in one
|
||||
instance will not flush values from another, and when an instance is
|
||||
deleted, so are the cached values for that instance.
|
||||
|
||||
>>> b = MyClass()
|
||||
>>> for x in range(35):
|
||||
... res = b.method(x)
|
||||
>>> b.calls
|
||||
35
|
||||
>>> a.method(0)
|
||||
0
|
||||
>>> a.calls
|
||||
75
|
||||
|
||||
Note that if method had been decorated with ``functools.lru_cache()``,
|
||||
a.calls would have been 76 (due to the cached value of 0 having been
|
||||
flushed by the 'b' instance).
|
||||
|
||||
Clear the cache with ``.cache_clear()``
|
||||
|
||||
>>> a.method.cache_clear()
|
||||
|
||||
Same for a method that hasn't yet been called.
|
||||
|
||||
>>> c = MyClass()
|
||||
>>> c.method.cache_clear()
|
||||
|
||||
Another cache wrapper may be supplied:
|
||||
|
||||
>>> cache = functools.lru_cache(maxsize=2)
|
||||
>>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache)
|
||||
>>> a = MyClass()
|
||||
>>> a.method2()
|
||||
3
|
||||
|
||||
Caution - do not subsequently wrap the method with another decorator, such
|
||||
as ``@property``, which changes the semantics of the function.
|
||||
|
||||
See also
|
||||
http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/
|
||||
for another implementation and additional justification.
|
||||
"""
|
||||
cache_wrapper = cache_wrapper or functools.lru_cache()
|
||||
|
||||
def wrapper(self, *args, **kwargs):
|
||||
# it's the first call, replace the method with a cached, bound method
|
||||
bound_method = types.MethodType(method, self)
|
||||
cached_method = cache_wrapper(bound_method)
|
||||
setattr(self, method.__name__, cached_method)
|
||||
return cached_method(*args, **kwargs)
|
||||
|
||||
# Support cache clear even before cache has been created.
|
||||
wrapper.cache_clear = lambda: None
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
# From jaraco.functools 3.3
|
||||
def pass_none(func):
|
||||
"""
|
||||
Wrap func so it's not called if its first param is None
|
||||
|
||||
>>> print_text = pass_none(print)
|
||||
>>> print_text('text')
|
||||
text
|
||||
>>> print_text(None)
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(param, *args, **kwargs):
|
||||
if param is not None:
|
||||
return func(param, *args, **kwargs)
|
||||
|
||||
return wrapper
|
73
Dependencies/Python/Lib/importlib/metadata/_itertools.py
vendored
Normal file
73
Dependencies/Python/Lib/importlib/metadata/_itertools.py
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
from itertools import filterfalse
|
||||
|
||||
|
||||
def unique_everseen(iterable, key=None):
|
||||
"List unique elements, preserving order. Remember all elements ever seen."
|
||||
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
|
||||
# unique_everseen('ABBCcAD', str.lower) --> A B C D
|
||||
seen = set()
|
||||
seen_add = seen.add
|
||||
if key is None:
|
||||
for element in filterfalse(seen.__contains__, iterable):
|
||||
seen_add(element)
|
||||
yield element
|
||||
else:
|
||||
for element in iterable:
|
||||
k = key(element)
|
||||
if k not in seen:
|
||||
seen_add(k)
|
||||
yield element
|
||||
|
||||
|
||||
# copied from more_itertools 8.8
|
||||
def always_iterable(obj, base_type=(str, bytes)):
|
||||
"""If *obj* is iterable, return an iterator over its items::
|
||||
|
||||
>>> obj = (1, 2, 3)
|
||||
>>> list(always_iterable(obj))
|
||||
[1, 2, 3]
|
||||
|
||||
If *obj* is not iterable, return a one-item iterable containing *obj*::
|
||||
|
||||
>>> obj = 1
|
||||
>>> list(always_iterable(obj))
|
||||
[1]
|
||||
|
||||
If *obj* is ``None``, return an empty iterable:
|
||||
|
||||
>>> obj = None
|
||||
>>> list(always_iterable(None))
|
||||
[]
|
||||
|
||||
By default, binary and text strings are not considered iterable::
|
||||
|
||||
>>> obj = 'foo'
|
||||
>>> list(always_iterable(obj))
|
||||
['foo']
|
||||
|
||||
If *base_type* is set, objects for which ``isinstance(obj, base_type)``
|
||||
returns ``True`` won't be considered iterable.
|
||||
|
||||
>>> obj = {'a': 1}
|
||||
>>> list(always_iterable(obj)) # Iterate over the dict's keys
|
||||
['a']
|
||||
>>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit
|
||||
[{'a': 1}]
|
||||
|
||||
Set *base_type* to ``None`` to avoid any special handling and treat objects
|
||||
Python considers iterable as iterable:
|
||||
|
||||
>>> obj = 'foo'
|
||||
>>> list(always_iterable(obj, base_type=None))
|
||||
['f', 'o', 'o']
|
||||
"""
|
||||
if obj is None:
|
||||
return iter(())
|
||||
|
||||
if (base_type is not None) and isinstance(obj, base_type):
|
||||
return iter((obj,))
|
||||
|
||||
try:
|
||||
return iter(obj)
|
||||
except TypeError:
|
||||
return iter((obj,))
|
67
Dependencies/Python/Lib/importlib/metadata/_meta.py
vendored
Normal file
67
Dependencies/Python/Lib/importlib/metadata/_meta.py
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from typing import Protocol
|
||||
from typing import Any, Dict, Iterator, List, Optional, TypeVar, Union, overload
|
||||
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class PackageMetadata(Protocol):
|
||||
def __len__(self) -> int: ... # pragma: no cover
|
||||
|
||||
def __contains__(self, item: str) -> bool: ... # pragma: no cover
|
||||
|
||||
def __getitem__(self, key: str) -> str: ... # pragma: no cover
|
||||
|
||||
def __iter__(self) -> Iterator[str]: ... # pragma: no cover
|
||||
|
||||
@overload
|
||||
def get(
|
||||
self, name: str, failobj: None = None
|
||||
) -> Optional[str]: ... # pragma: no cover
|
||||
|
||||
@overload
|
||||
def get(self, name: str, failobj: _T) -> Union[str, _T]: ... # pragma: no cover
|
||||
|
||||
# overload per python/importlib_metadata#435
|
||||
@overload
|
||||
def get_all(
|
||||
self, name: str, failobj: None = None
|
||||
) -> Optional[List[Any]]: ... # pragma: no cover
|
||||
|
||||
@overload
|
||||
def get_all(self, name: str, failobj: _T) -> Union[List[Any], _T]:
|
||||
"""
|
||||
Return all values associated with a possibly multi-valued key.
|
||||
"""
|
||||
|
||||
@property
|
||||
def json(self) -> Dict[str, Union[str, List[str]]]:
|
||||
"""
|
||||
A JSON-compatible form of the metadata.
|
||||
"""
|
||||
|
||||
|
||||
class SimplePath(Protocol):
|
||||
"""
|
||||
A minimal subset of pathlib.Path required by Distribution.
|
||||
"""
|
||||
|
||||
def joinpath(
|
||||
self, other: Union[str, os.PathLike[str]]
|
||||
) -> SimplePath: ... # pragma: no cover
|
||||
|
||||
def __truediv__(
|
||||
self, other: Union[str, os.PathLike[str]]
|
||||
) -> SimplePath: ... # pragma: no cover
|
||||
|
||||
@property
|
||||
def parent(self) -> SimplePath: ... # pragma: no cover
|
||||
|
||||
def read_text(self, encoding=None) -> str: ... # pragma: no cover
|
||||
|
||||
def read_bytes(self) -> bytes: ... # pragma: no cover
|
||||
|
||||
def exists(self) -> bool: ... # pragma: no cover
|
99
Dependencies/Python/Lib/importlib/metadata/_text.py
vendored
Normal file
99
Dependencies/Python/Lib/importlib/metadata/_text.py
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
import re
|
||||
|
||||
from ._functools import method_cache
|
||||
|
||||
|
||||
# from jaraco.text 3.5
|
||||
class FoldedCase(str):
|
||||
"""
|
||||
A case insensitive string class; behaves just like str
|
||||
except compares equal when the only variation is case.
|
||||
|
||||
>>> s = FoldedCase('hello world')
|
||||
|
||||
>>> s == 'Hello World'
|
||||
True
|
||||
|
||||
>>> 'Hello World' == s
|
||||
True
|
||||
|
||||
>>> s != 'Hello World'
|
||||
False
|
||||
|
||||
>>> s.index('O')
|
||||
4
|
||||
|
||||
>>> s.split('O')
|
||||
['hell', ' w', 'rld']
|
||||
|
||||
>>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta']))
|
||||
['alpha', 'Beta', 'GAMMA']
|
||||
|
||||
Sequence membership is straightforward.
|
||||
|
||||
>>> "Hello World" in [s]
|
||||
True
|
||||
>>> s in ["Hello World"]
|
||||
True
|
||||
|
||||
You may test for set inclusion, but candidate and elements
|
||||
must both be folded.
|
||||
|
||||
>>> FoldedCase("Hello World") in {s}
|
||||
True
|
||||
>>> s in {FoldedCase("Hello World")}
|
||||
True
|
||||
|
||||
String inclusion works as long as the FoldedCase object
|
||||
is on the right.
|
||||
|
||||
>>> "hello" in FoldedCase("Hello World")
|
||||
True
|
||||
|
||||
But not if the FoldedCase object is on the left:
|
||||
|
||||
>>> FoldedCase('hello') in 'Hello World'
|
||||
False
|
||||
|
||||
In that case, use in_:
|
||||
|
||||
>>> FoldedCase('hello').in_('Hello World')
|
||||
True
|
||||
|
||||
>>> FoldedCase('hello') > FoldedCase('Hello')
|
||||
False
|
||||
"""
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.lower() < other.lower()
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.lower() > other.lower()
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.lower() == other.lower()
|
||||
|
||||
def __ne__(self, other):
|
||||
return self.lower() != other.lower()
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.lower())
|
||||
|
||||
def __contains__(self, other):
|
||||
return super().lower().__contains__(other.lower())
|
||||
|
||||
def in_(self, other):
|
||||
"Does self appear in other?"
|
||||
return self in FoldedCase(other)
|
||||
|
||||
# cache lower since it's likely to be called frequently.
|
||||
@method_cache
|
||||
def lower(self):
|
||||
return super().lower()
|
||||
|
||||
def index(self, sub):
|
||||
return self.lower().index(sub.lower())
|
||||
|
||||
def split(self, splitter=' ', maxsplit=0):
|
||||
pattern = re.compile(re.escape(splitter), re.I)
|
||||
return pattern.split(self, maxsplit)
|
21
Dependencies/Python/Lib/importlib/metadata/diagnose.py
vendored
Normal file
21
Dependencies/Python/Lib/importlib/metadata/diagnose.py
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
import sys
|
||||
|
||||
from . import Distribution
|
||||
|
||||
|
||||
def inspect(path):
|
||||
print("Inspecting", path)
|
||||
dists = list(Distribution.discover(path=[path]))
|
||||
if not dists:
|
||||
return
|
||||
print("Found", len(dists), "packages:", end=' ')
|
||||
print(', '.join(dist.name for dist in dists))
|
||||
|
||||
|
||||
def run():
|
||||
for path in sys.path:
|
||||
inspect(path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
12
Dependencies/Python/Lib/importlib/readers.py
vendored
Normal file
12
Dependencies/Python/Lib/importlib/readers.py
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
"""
|
||||
Compatibility shim for .resources.readers as found on Python 3.10.
|
||||
|
||||
Consumers that can rely on Python 3.11 should use the other
|
||||
module directly.
|
||||
"""
|
||||
|
||||
from .resources.readers import (
|
||||
FileReader, ZipReader, MultiplexedPath, NamespaceReader,
|
||||
)
|
||||
|
||||
__all__ = ['FileReader', 'ZipReader', 'MultiplexedPath', 'NamespaceReader']
|
43
Dependencies/Python/Lib/importlib/resources/__init__.py
vendored
Normal file
43
Dependencies/Python/Lib/importlib/resources/__init__.py
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
"""
|
||||
Read resources contained within a package.
|
||||
|
||||
This codebase is shared between importlib.resources in the stdlib
|
||||
and importlib_resources in PyPI. See
|
||||
https://github.com/python/importlib_metadata/wiki/Development-Methodology
|
||||
for more detail.
|
||||
"""
|
||||
|
||||
from ._common import (
|
||||
as_file,
|
||||
files,
|
||||
Package,
|
||||
Anchor,
|
||||
)
|
||||
|
||||
from ._functional import (
|
||||
contents,
|
||||
is_resource,
|
||||
open_binary,
|
||||
open_text,
|
||||
path,
|
||||
read_binary,
|
||||
read_text,
|
||||
)
|
||||
|
||||
from .abc import ResourceReader
|
||||
|
||||
|
||||
__all__ = [
|
||||
'Package',
|
||||
'Anchor',
|
||||
'ResourceReader',
|
||||
'as_file',
|
||||
'files',
|
||||
'contents',
|
||||
'is_resource',
|
||||
'open_binary',
|
||||
'open_text',
|
||||
'path',
|
||||
'read_binary',
|
||||
'read_text',
|
||||
]
|
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_adapters.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_adapters.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_common.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_common.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_functional.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_functional.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_itertools.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/_itertools.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/abc.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/abc.cpython-313.pyc
vendored
Normal file
Binary file not shown.
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/readers.cpython-313.pyc
vendored
Normal file
BIN
Dependencies/Python/Lib/importlib/resources/__pycache__/readers.cpython-313.pyc
vendored
Normal file
Binary file not shown.
168
Dependencies/Python/Lib/importlib/resources/_adapters.py
vendored
Normal file
168
Dependencies/Python/Lib/importlib/resources/_adapters.py
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
from contextlib import suppress
|
||||
from io import TextIOWrapper
|
||||
|
||||
from . import abc
|
||||
|
||||
|
||||
class SpecLoaderAdapter:
|
||||
"""
|
||||
Adapt a package spec to adapt the underlying loader.
|
||||
"""
|
||||
|
||||
def __init__(self, spec, adapter=lambda spec: spec.loader):
|
||||
self.spec = spec
|
||||
self.loader = adapter(spec)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.spec, name)
|
||||
|
||||
|
||||
class TraversableResourcesLoader:
|
||||
"""
|
||||
Adapt a loader to provide TraversableResources.
|
||||
"""
|
||||
|
||||
def __init__(self, spec):
|
||||
self.spec = spec
|
||||
|
||||
def get_resource_reader(self, name):
|
||||
return CompatibilityFiles(self.spec)._native()
|
||||
|
||||
|
||||
def _io_wrapper(file, mode='r', *args, **kwargs):
|
||||
if mode == 'r':
|
||||
return TextIOWrapper(file, *args, **kwargs)
|
||||
elif mode == 'rb':
|
||||
return file
|
||||
raise ValueError(f"Invalid mode value '{mode}', only 'r' and 'rb' are supported")
|
||||
|
||||
|
||||
class CompatibilityFiles:
|
||||
"""
|
||||
Adapter for an existing or non-existent resource reader
|
||||
to provide a compatibility .files().
|
||||
"""
|
||||
|
||||
class SpecPath(abc.Traversable):
|
||||
"""
|
||||
Path tied to a module spec.
|
||||
Can be read and exposes the resource reader children.
|
||||
"""
|
||||
|
||||
def __init__(self, spec, reader):
|
||||
self._spec = spec
|
||||
self._reader = reader
|
||||
|
||||
def iterdir(self):
|
||||
if not self._reader:
|
||||
return iter(())
|
||||
return iter(
|
||||
CompatibilityFiles.ChildPath(self._reader, path)
|
||||
for path in self._reader.contents()
|
||||
)
|
||||
|
||||
def is_file(self):
|
||||
return False
|
||||
|
||||
is_dir = is_file
|
||||
|
||||
def joinpath(self, other):
|
||||
if not self._reader:
|
||||
return CompatibilityFiles.OrphanPath(other)
|
||||
return CompatibilityFiles.ChildPath(self._reader, other)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._spec.name
|
||||
|
||||
def open(self, mode='r', *args, **kwargs):
|
||||
return _io_wrapper(self._reader.open_resource(None), mode, *args, **kwargs)
|
||||
|
||||
class ChildPath(abc.Traversable):
|
||||
"""
|
||||
Path tied to a resource reader child.
|
||||
Can be read but doesn't expose any meaningful children.
|
||||
"""
|
||||
|
||||
def __init__(self, reader, name):
|
||||
self._reader = reader
|
||||
self._name = name
|
||||
|
||||
def iterdir(self):
|
||||
return iter(())
|
||||
|
||||
def is_file(self):
|
||||
return self._reader.is_resource(self.name)
|
||||
|
||||
def is_dir(self):
|
||||
return not self.is_file()
|
||||
|
||||
def joinpath(self, other):
|
||||
return CompatibilityFiles.OrphanPath(self.name, other)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
def open(self, mode='r', *args, **kwargs):
|
||||
return _io_wrapper(
|
||||
self._reader.open_resource(self.name), mode, *args, **kwargs
|
||||
)
|
||||
|
||||
class OrphanPath(abc.Traversable):
|
||||
"""
|
||||
Orphan path, not tied to a module spec or resource reader.
|
||||
Can't be read and doesn't expose any meaningful children.
|
||||
"""
|
||||
|
||||
def __init__(self, *path_parts):
|
||||
if len(path_parts) < 1:
|
||||
raise ValueError('Need at least one path part to construct a path')
|
||||
self._path = path_parts
|
||||
|
||||
def iterdir(self):
|
||||
return iter(())
|
||||
|
||||
def is_file(self):
|
||||
return False
|
||||
|
||||
is_dir = is_file
|
||||
|
||||
def joinpath(self, other):
|
||||
return CompatibilityFiles.OrphanPath(*self._path, other)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._path[-1]
|
||||
|
||||
def open(self, mode='r', *args, **kwargs):
|
||||
raise FileNotFoundError("Can't open orphan path")
|
||||
|
||||
def __init__(self, spec):
|
||||
self.spec = spec
|
||||
|
||||
@property
|
||||
def _reader(self):
|
||||
with suppress(AttributeError):
|
||||
return self.spec.loader.get_resource_reader(self.spec.name)
|
||||
|
||||
def _native(self):
|
||||
"""
|
||||
Return the native reader if it supports files().
|
||||
"""
|
||||
reader = self._reader
|
||||
return reader if hasattr(reader, 'files') else self
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self._reader, attr)
|
||||
|
||||
def files(self):
|
||||
return CompatibilityFiles.SpecPath(self.spec, self._reader)
|
||||
|
||||
|
||||
def wrap_spec(package):
|
||||
"""
|
||||
Construct a package spec with traversable compatibility
|
||||
on the spec/loader/reader.
|
||||
"""
|
||||
return SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader)
|
210
Dependencies/Python/Lib/importlib/resources/_common.py
vendored
Normal file
210
Dependencies/Python/Lib/importlib/resources/_common.py
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
import os
|
||||
import pathlib
|
||||
import tempfile
|
||||
import functools
|
||||
import contextlib
|
||||
import types
|
||||
import importlib
|
||||
import inspect
|
||||
import warnings
|
||||
import itertools
|
||||
|
||||
from typing import Union, Optional, cast
|
||||
from .abc import ResourceReader, Traversable
|
||||
|
||||
Package = Union[types.ModuleType, str]
|
||||
Anchor = Package
|
||||
|
||||
|
||||
def package_to_anchor(func):
|
||||
"""
|
||||
Replace 'package' parameter as 'anchor' and warn about the change.
|
||||
|
||||
Other errors should fall through.
|
||||
|
||||
>>> files('a', 'b')
|
||||
Traceback (most recent call last):
|
||||
TypeError: files() takes from 0 to 1 positional arguments but 2 were given
|
||||
|
||||
Remove this compatibility in Python 3.14.
|
||||
"""
|
||||
undefined = object()
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(anchor=undefined, package=undefined):
|
||||
if package is not undefined:
|
||||
if anchor is not undefined:
|
||||
return func(anchor, package)
|
||||
warnings.warn(
|
||||
"First parameter to files is renamed to 'anchor'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return func(package)
|
||||
elif anchor is undefined:
|
||||
return func()
|
||||
return func(anchor)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@package_to_anchor
|
||||
def files(anchor: Optional[Anchor] = None) -> Traversable:
|
||||
"""
|
||||
Get a Traversable resource for an anchor.
|
||||
"""
|
||||
return from_package(resolve(anchor))
|
||||
|
||||
|
||||
def get_resource_reader(package: types.ModuleType) -> Optional[ResourceReader]:
|
||||
"""
|
||||
Return the package's loader if it's a ResourceReader.
|
||||
"""
|
||||
# We can't use
|
||||
# a issubclass() check here because apparently abc.'s __subclasscheck__()
|
||||
# hook wants to create a weak reference to the object, but
|
||||
# zipimport.zipimporter does not support weak references, resulting in a
|
||||
# TypeError. That seems terrible.
|
||||
spec = package.__spec__
|
||||
reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore[union-attr]
|
||||
if reader is None:
|
||||
return None
|
||||
return reader(spec.name) # type: ignore[union-attr]
|
||||
|
||||
|
||||
@functools.singledispatch
|
||||
def resolve(cand: Optional[Anchor]) -> types.ModuleType:
|
||||
return cast(types.ModuleType, cand)
|
||||
|
||||
|
||||
@resolve.register
|
||||
def _(cand: str) -> types.ModuleType:
|
||||
return importlib.import_module(cand)
|
||||
|
||||
|
||||
@resolve.register
|
||||
def _(cand: None) -> types.ModuleType:
|
||||
return resolve(_infer_caller().f_globals['__name__'])
|
||||
|
||||
|
||||
def _infer_caller():
|
||||
"""
|
||||
Walk the stack and find the frame of the first caller not in this module.
|
||||
"""
|
||||
|
||||
def is_this_file(frame_info):
|
||||
return frame_info.filename == __file__
|
||||
|
||||
def is_wrapper(frame_info):
|
||||
return frame_info.function == 'wrapper'
|
||||
|
||||
not_this_file = itertools.filterfalse(is_this_file, inspect.stack())
|
||||
# also exclude 'wrapper' due to singledispatch in the call stack
|
||||
callers = itertools.filterfalse(is_wrapper, not_this_file)
|
||||
return next(callers).frame
|
||||
|
||||
|
||||
def from_package(package: types.ModuleType):
|
||||
"""
|
||||
Return a Traversable object for the given package.
|
||||
|
||||
"""
|
||||
# deferred for performance (python/cpython#109829)
|
||||
from ._adapters import wrap_spec
|
||||
|
||||
spec = wrap_spec(package)
|
||||
reader = spec.loader.get_resource_reader(spec.name)
|
||||
return reader.files()
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _tempfile(
|
||||
reader,
|
||||
suffix='',
|
||||
# gh-93353: Keep a reference to call os.remove() in late Python
|
||||
# finalization.
|
||||
*,
|
||||
_os_remove=os.remove,
|
||||
):
|
||||
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'
|
||||
# blocks due to the need to close the temporary file to work on Windows
|
||||
# properly.
|
||||
fd, raw_path = tempfile.mkstemp(suffix=suffix)
|
||||
try:
|
||||
try:
|
||||
os.write(fd, reader())
|
||||
finally:
|
||||
os.close(fd)
|
||||
del reader
|
||||
yield pathlib.Path(raw_path)
|
||||
finally:
|
||||
try:
|
||||
_os_remove(raw_path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
|
||||
def _temp_file(path):
|
||||
return _tempfile(path.read_bytes, suffix=path.name)
|
||||
|
||||
|
||||
def _is_present_dir(path: Traversable) -> bool:
|
||||
"""
|
||||
Some Traversables implement ``is_dir()`` to raise an
|
||||
exception (i.e. ``FileNotFoundError``) when the
|
||||
directory doesn't exist. This function wraps that call
|
||||
to always return a boolean and only return True
|
||||
if there's a dir and it exists.
|
||||
"""
|
||||
with contextlib.suppress(FileNotFoundError):
|
||||
return path.is_dir()
|
||||
return False
|
||||
|
||||
|
||||
@functools.singledispatch
|
||||
def as_file(path):
|
||||
"""
|
||||
Given a Traversable object, return that object as a
|
||||
path on the local file system in a context manager.
|
||||
"""
|
||||
return _temp_dir(path) if _is_present_dir(path) else _temp_file(path)
|
||||
|
||||
|
||||
@as_file.register(pathlib.Path)
|
||||
@contextlib.contextmanager
|
||||
def _(path):
|
||||
"""
|
||||
Degenerate behavior for pathlib.Path objects.
|
||||
"""
|
||||
yield path
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _temp_path(dir: tempfile.TemporaryDirectory):
|
||||
"""
|
||||
Wrap tempfile.TemporyDirectory to return a pathlib object.
|
||||
"""
|
||||
with dir as result:
|
||||
yield pathlib.Path(result)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _temp_dir(path):
|
||||
"""
|
||||
Given a traversable dir, recursively replicate the whole tree
|
||||
to the file system in a context manager.
|
||||
"""
|
||||
assert path.is_dir()
|
||||
with _temp_path(tempfile.TemporaryDirectory()) as temp_dir:
|
||||
yield _write_contents(temp_dir, path)
|
||||
|
||||
|
||||
def _write_contents(target, source):
|
||||
child = target.joinpath(source.name)
|
||||
if source.is_dir():
|
||||
child.mkdir()
|
||||
for item in source.iterdir():
|
||||
_write_contents(child, item)
|
||||
else:
|
||||
child.write_bytes(source.read_bytes())
|
||||
return child
|
81
Dependencies/Python/Lib/importlib/resources/_functional.py
vendored
Normal file
81
Dependencies/Python/Lib/importlib/resources/_functional.py
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
"""Simplified function-based API for importlib.resources"""
|
||||
|
||||
import warnings
|
||||
|
||||
from ._common import files, as_file
|
||||
|
||||
|
||||
_MISSING = object()
|
||||
|
||||
|
||||
def open_binary(anchor, *path_names):
|
||||
"""Open for binary reading the *resource* within *package*."""
|
||||
return _get_resource(anchor, path_names).open('rb')
|
||||
|
||||
|
||||
def open_text(anchor, *path_names, encoding=_MISSING, errors='strict'):
|
||||
"""Open for text reading the *resource* within *package*."""
|
||||
encoding = _get_encoding_arg(path_names, encoding)
|
||||
resource = _get_resource(anchor, path_names)
|
||||
return resource.open('r', encoding=encoding, errors=errors)
|
||||
|
||||
|
||||
def read_binary(anchor, *path_names):
|
||||
"""Read and return contents of *resource* within *package* as bytes."""
|
||||
return _get_resource(anchor, path_names).read_bytes()
|
||||
|
||||
|
||||
def read_text(anchor, *path_names, encoding=_MISSING, errors='strict'):
|
||||
"""Read and return contents of *resource* within *package* as str."""
|
||||
encoding = _get_encoding_arg(path_names, encoding)
|
||||
resource = _get_resource(anchor, path_names)
|
||||
return resource.read_text(encoding=encoding, errors=errors)
|
||||
|
||||
|
||||
def path(anchor, *path_names):
|
||||
"""Return the path to the *resource* as an actual file system path."""
|
||||
return as_file(_get_resource(anchor, path_names))
|
||||
|
||||
|
||||
def is_resource(anchor, *path_names):
|
||||
"""Return ``True`` if there is a resource named *name* in the package,
|
||||
|
||||
Otherwise returns ``False``.
|
||||
"""
|
||||
return _get_resource(anchor, path_names).is_file()
|
||||
|
||||
|
||||
def contents(anchor, *path_names):
|
||||
"""Return an iterable over the named resources within the package.
|
||||
|
||||
The iterable returns :class:`str` resources (e.g. files).
|
||||
The iterable does not recurse into subdirectories.
|
||||
"""
|
||||
warnings.warn(
|
||||
"importlib.resources.contents is deprecated. "
|
||||
"Use files(anchor).iterdir() instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=1,
|
||||
)
|
||||
return (resource.name for resource in _get_resource(anchor, path_names).iterdir())
|
||||
|
||||
|
||||
def _get_encoding_arg(path_names, encoding):
|
||||
# For compatibility with versions where *encoding* was a positional
|
||||
# argument, it needs to be given explicitly when there are multiple
|
||||
# *path_names*.
|
||||
# This limitation can be removed in Python 3.15.
|
||||
if encoding is _MISSING:
|
||||
if len(path_names) > 1:
|
||||
raise TypeError(
|
||||
"'encoding' argument required with multiple path names",
|
||||
)
|
||||
else:
|
||||
return 'utf-8'
|
||||
return encoding
|
||||
|
||||
|
||||
def _get_resource(anchor, path_names):
|
||||
if anchor is None:
|
||||
raise TypeError("anchor must be module or string, got None")
|
||||
return files(anchor).joinpath(*path_names)
|
38
Dependencies/Python/Lib/importlib/resources/_itertools.py
vendored
Normal file
38
Dependencies/Python/Lib/importlib/resources/_itertools.py
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# from more_itertools 9.0
|
||||
def only(iterable, default=None, too_long=None):
|
||||
"""If *iterable* has only one item, return it.
|
||||
If it has zero items, return *default*.
|
||||
If it has more than one item, raise the exception given by *too_long*,
|
||||
which is ``ValueError`` by default.
|
||||
>>> only([], default='missing')
|
||||
'missing'
|
||||
>>> only([1])
|
||||
1
|
||||
>>> only([1, 2]) # doctest: +IGNORE_EXCEPTION_DETAIL
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Expected exactly one item in iterable, but got 1, 2,
|
||||
and perhaps more.'
|
||||
>>> only([1, 2], too_long=TypeError) # doctest: +IGNORE_EXCEPTION_DETAIL
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError
|
||||
Note that :func:`only` attempts to advance *iterable* twice to ensure there
|
||||
is only one item. See :func:`spy` or :func:`peekable` to check
|
||||
iterable contents less destructively.
|
||||
"""
|
||||
it = iter(iterable)
|
||||
first_value = next(it, default)
|
||||
|
||||
try:
|
||||
second_value = next(it)
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
msg = (
|
||||
'Expected exactly one item in iterable, but got {!r}, {!r}, '
|
||||
'and perhaps more.'.format(first_value, second_value)
|
||||
)
|
||||
raise too_long or ValueError(msg)
|
||||
|
||||
return first_value
|
173
Dependencies/Python/Lib/importlib/resources/abc.py
vendored
Normal file
173
Dependencies/Python/Lib/importlib/resources/abc.py
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
import abc
|
||||
import io
|
||||
import itertools
|
||||
import os
|
||||
import pathlib
|
||||
from typing import Any, BinaryIO, Iterable, Iterator, NoReturn, Text, Optional
|
||||
from typing import runtime_checkable, Protocol
|
||||
from typing import Union
|
||||
|
||||
|
||||
StrPath = Union[str, os.PathLike[str]]
|
||||
|
||||
__all__ = ["ResourceReader", "Traversable", "TraversableResources"]
|
||||
|
||||
|
||||
class ResourceReader(metaclass=abc.ABCMeta):
|
||||
"""Abstract base class for loaders to provide resource reading support."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def open_resource(self, resource: Text) -> BinaryIO:
|
||||
"""Return an opened, file-like object for binary reading.
|
||||
|
||||
The 'resource' argument is expected to represent only a file name.
|
||||
If the resource cannot be found, FileNotFoundError is raised.
|
||||
"""
|
||||
# This deliberately raises FileNotFoundError instead of
|
||||
# NotImplementedError so that if this method is accidentally called,
|
||||
# it'll still do the right thing.
|
||||
raise FileNotFoundError
|
||||
|
||||
@abc.abstractmethod
|
||||
def resource_path(self, resource: Text) -> Text:
|
||||
"""Return the file system path to the specified resource.
|
||||
|
||||
The 'resource' argument is expected to represent only a file name.
|
||||
If the resource does not exist on the file system, raise
|
||||
FileNotFoundError.
|
||||
"""
|
||||
# This deliberately raises FileNotFoundError instead of
|
||||
# NotImplementedError so that if this method is accidentally called,
|
||||
# it'll still do the right thing.
|
||||
raise FileNotFoundError
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_resource(self, path: Text) -> bool:
|
||||
"""Return True if the named 'path' is a resource.
|
||||
|
||||
Files are resources, directories are not.
|
||||
"""
|
||||
raise FileNotFoundError
|
||||
|
||||
@abc.abstractmethod
|
||||
def contents(self) -> Iterable[str]:
|
||||
"""Return an iterable of entries in `package`."""
|
||||
raise FileNotFoundError
|
||||
|
||||
|
||||
class TraversalError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class Traversable(Protocol):
|
||||
"""
|
||||
An object with a subset of pathlib.Path methods suitable for
|
||||
traversing directories and opening files.
|
||||
|
||||
Any exceptions that occur when accessing the backing resource
|
||||
may propagate unaltered.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def iterdir(self) -> Iterator["Traversable"]:
|
||||
"""
|
||||
Yield Traversable objects in self
|
||||
"""
|
||||
|
||||
def read_bytes(self) -> bytes:
|
||||
"""
|
||||
Read contents of self as bytes
|
||||
"""
|
||||
with self.open('rb') as strm:
|
||||
return strm.read()
|
||||
|
||||
def read_text(self, encoding: Optional[str] = None) -> str:
|
||||
"""
|
||||
Read contents of self as text
|
||||
"""
|
||||
with self.open(encoding=encoding) as strm:
|
||||
return strm.read()
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_dir(self) -> bool:
|
||||
"""
|
||||
Return True if self is a directory
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_file(self) -> bool:
|
||||
"""
|
||||
Return True if self is a file
|
||||
"""
|
||||
|
||||
def joinpath(self, *descendants: StrPath) -> "Traversable":
|
||||
"""
|
||||
Return Traversable resolved with any descendants applied.
|
||||
|
||||
Each descendant should be a path segment relative to self
|
||||
and each may contain multiple levels separated by
|
||||
``posixpath.sep`` (``/``).
|
||||
"""
|
||||
if not descendants:
|
||||
return self
|
||||
names = itertools.chain.from_iterable(
|
||||
path.parts for path in map(pathlib.PurePosixPath, descendants)
|
||||
)
|
||||
target = next(names)
|
||||
matches = (
|
||||
traversable for traversable in self.iterdir() if traversable.name == target
|
||||
)
|
||||
try:
|
||||
match = next(matches)
|
||||
except StopIteration:
|
||||
raise TraversalError(
|
||||
"Target not found during traversal.", target, list(names)
|
||||
)
|
||||
return match.joinpath(*names)
|
||||
|
||||
def __truediv__(self, child: StrPath) -> "Traversable":
|
||||
"""
|
||||
Return Traversable child in self
|
||||
"""
|
||||
return self.joinpath(child)
|
||||
|
||||
@abc.abstractmethod
|
||||
def open(self, mode='r', *args, **kwargs):
|
||||
"""
|
||||
mode may be 'r' or 'rb' to open as text or binary. Return a handle
|
||||
suitable for reading (same as pathlib.Path.open).
|
||||
|
||||
When opening as text, accepts encoding parameters such as those
|
||||
accepted by io.TextIOWrapper.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def name(self) -> str:
|
||||
"""
|
||||
The base name of this object without any parent references.
|
||||
"""
|
||||
|
||||
|
||||
class TraversableResources(ResourceReader):
|
||||
"""
|
||||
The required interface for providing traversable
|
||||
resources.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def files(self) -> "Traversable":
|
||||
"""Return a Traversable object for the loaded package."""
|
||||
|
||||
def open_resource(self, resource: StrPath) -> io.BufferedReader:
|
||||
return self.files().joinpath(resource).open('rb')
|
||||
|
||||
def resource_path(self, resource: Any) -> NoReturn:
|
||||
raise FileNotFoundError(resource)
|
||||
|
||||
def is_resource(self, path: StrPath) -> bool:
|
||||
return self.files().joinpath(path).is_file()
|
||||
|
||||
def contents(self) -> Iterator[str]:
|
||||
return (item.name for item in self.files().iterdir())
|
203
Dependencies/Python/Lib/importlib/resources/readers.py
vendored
Normal file
203
Dependencies/Python/Lib/importlib/resources/readers.py
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import collections
|
||||
import contextlib
|
||||
import itertools
|
||||
import pathlib
|
||||
import operator
|
||||
import re
|
||||
import warnings
|
||||
import zipfile
|
||||
from collections.abc import Iterator
|
||||
|
||||
from . import abc
|
||||
|
||||
from ._itertools import only
|
||||
|
||||
|
||||
def remove_duplicates(items):
|
||||
return iter(collections.OrderedDict.fromkeys(items))
|
||||
|
||||
|
||||
class FileReader(abc.TraversableResources):
|
||||
def __init__(self, loader):
|
||||
self.path = pathlib.Path(loader.path).parent
|
||||
|
||||
def resource_path(self, resource):
|
||||
"""
|
||||
Return the file system path to prevent
|
||||
`resources.path()` from creating a temporary
|
||||
copy.
|
||||
"""
|
||||
return str(self.path.joinpath(resource))
|
||||
|
||||
def files(self):
|
||||
return self.path
|
||||
|
||||
|
||||
class ZipReader(abc.TraversableResources):
|
||||
def __init__(self, loader, module):
|
||||
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):
|
||||
try:
|
||||
return super().open_resource(resource)
|
||||
except KeyError as exc:
|
||||
raise FileNotFoundError(exc.args[0])
|
||||
|
||||
def is_resource(self, path):
|
||||
"""
|
||||
Workaround for `zipfile.Path.is_file` returning true
|
||||
for non-existent paths.
|
||||
"""
|
||||
target = self.files().joinpath(path)
|
||||
return target.is_file() and target.exists()
|
||||
|
||||
def files(self):
|
||||
return zipfile.Path(self.archive, self.prefix)
|
||||
|
||||
|
||||
class MultiplexedPath(abc.Traversable):
|
||||
"""
|
||||
Given a series of Traversable objects, implement a merged
|
||||
version of the interface across all objects. Useful for
|
||||
namespace packages which may be multihomed at a single
|
||||
name.
|
||||
"""
|
||||
|
||||
def __init__(self, *paths):
|
||||
self._paths = list(map(_ensure_traversable, remove_duplicates(paths)))
|
||||
if not self._paths:
|
||||
message = 'MultiplexedPath must contain at least one path'
|
||||
raise FileNotFoundError(message)
|
||||
if not all(path.is_dir() for path in self._paths):
|
||||
raise NotADirectoryError('MultiplexedPath only supports directories')
|
||||
|
||||
def iterdir(self):
|
||||
children = (child for path in self._paths for child in path.iterdir())
|
||||
by_name = operator.attrgetter('name')
|
||||
groups = itertools.groupby(sorted(children, key=by_name), key=by_name)
|
||||
return map(self._follow, (locs for name, locs in groups))
|
||||
|
||||
def read_bytes(self):
|
||||
raise FileNotFoundError(f'{self} is not a file')
|
||||
|
||||
def read_text(self, *args, **kwargs):
|
||||
raise FileNotFoundError(f'{self} is not a file')
|
||||
|
||||
def is_dir(self):
|
||||
return True
|
||||
|
||||
def is_file(self):
|
||||
return False
|
||||
|
||||
def joinpath(self, *descendants):
|
||||
try:
|
||||
return super().joinpath(*descendants)
|
||||
except abc.TraversalError:
|
||||
# One of the paths did not resolve (a directory does not exist).
|
||||
# Just return something that will not exist.
|
||||
return self._paths[0].joinpath(*descendants)
|
||||
|
||||
@classmethod
|
||||
def _follow(cls, children):
|
||||
"""
|
||||
Construct a MultiplexedPath if needed.
|
||||
|
||||
If children contains a sole element, return it.
|
||||
Otherwise, return a MultiplexedPath of the items.
|
||||
Unless one of the items is not a Directory, then return the first.
|
||||
"""
|
||||
subdirs, one_dir, one_file = itertools.tee(children, 3)
|
||||
|
||||
try:
|
||||
return only(one_dir)
|
||||
except ValueError:
|
||||
try:
|
||||
return cls(*subdirs)
|
||||
except NotADirectoryError:
|
||||
return next(one_file)
|
||||
|
||||
def open(self, *args, **kwargs):
|
||||
raise FileNotFoundError(f'{self} is not a file')
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._paths[0].name
|
||||
|
||||
def __repr__(self):
|
||||
paths = ', '.join(f"'{path}'" for path in self._paths)
|
||||
return f'MultiplexedPath({paths})'
|
||||
|
||||
|
||||
class NamespaceReader(abc.TraversableResources):
|
||||
def __init__(self, namespace_path):
|
||||
if 'NamespacePath' not in str(namespace_path):
|
||||
raise ValueError('Invalid path')
|
||||
self.path = MultiplexedPath(*filter(bool, map(self._resolve, namespace_path)))
|
||||
|
||||
@classmethod
|
||||
def _resolve(cls, path_str) -> abc.Traversable | None:
|
||||
r"""
|
||||
Given an item from a namespace path, resolve it to a Traversable.
|
||||
|
||||
path_str might be a directory on the filesystem or a path to a
|
||||
zipfile plus the path within the zipfile, e.g. ``/foo/bar`` or
|
||||
``/foo/baz.zip/inner_dir`` or ``foo\baz.zip\inner_dir\sub``.
|
||||
|
||||
path_str might also be a sentinel used by editable packages to
|
||||
trigger other behaviors (see python/importlib_resources#311).
|
||||
In that case, return None.
|
||||
"""
|
||||
dirs = (cand for cand in cls._candidate_paths(path_str) if cand.is_dir())
|
||||
return next(dirs, None)
|
||||
|
||||
@classmethod
|
||||
def _candidate_paths(cls, path_str: str) -> Iterator[abc.Traversable]:
|
||||
yield pathlib.Path(path_str)
|
||||
yield from cls._resolve_zip_path(path_str)
|
||||
|
||||
@staticmethod
|
||||
def _resolve_zip_path(path_str: str):
|
||||
for match in reversed(list(re.finditer(r'[\\/]', path_str))):
|
||||
with contextlib.suppress(
|
||||
FileNotFoundError,
|
||||
IsADirectoryError,
|
||||
NotADirectoryError,
|
||||
PermissionError,
|
||||
):
|
||||
inner = path_str[match.end() :].replace('\\', '/') + '/'
|
||||
yield zipfile.Path(path_str[: match.start()], inner.lstrip('/'))
|
||||
|
||||
def resource_path(self, resource):
|
||||
"""
|
||||
Return the file system path to prevent
|
||||
`resources.path()` from creating a temporary
|
||||
copy.
|
||||
"""
|
||||
return str(self.path.joinpath(resource))
|
||||
|
||||
def files(self):
|
||||
return self.path
|
||||
|
||||
|
||||
def _ensure_traversable(path):
|
||||
"""
|
||||
Convert deprecated string arguments to traversables (pathlib.Path).
|
||||
|
||||
Remove with Python 3.15.
|
||||
"""
|
||||
if not isinstance(path, str):
|
||||
return path
|
||||
|
||||
warnings.warn(
|
||||
"String arguments are deprecated. Pass a Traversable instead.",
|
||||
DeprecationWarning,
|
||||
stacklevel=3,
|
||||
)
|
||||
|
||||
return pathlib.Path(path)
|
106
Dependencies/Python/Lib/importlib/resources/simple.py
vendored
Normal file
106
Dependencies/Python/Lib/importlib/resources/simple.py
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
"""
|
||||
Interface adapters for low-level readers.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import io
|
||||
import itertools
|
||||
from typing import BinaryIO, List
|
||||
|
||||
from .abc import Traversable, TraversableResources
|
||||
|
||||
|
||||
class SimpleReader(abc.ABC):
|
||||
"""
|
||||
The minimum, low-level interface required from a resource
|
||||
provider.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def package(self) -> str:
|
||||
"""
|
||||
The name of the package for which this reader loads resources.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def children(self) -> List['SimpleReader']:
|
||||
"""
|
||||
Obtain an iterable of SimpleReader for available
|
||||
child containers (e.g. directories).
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def resources(self) -> List[str]:
|
||||
"""
|
||||
Obtain available named resources for this virtual package.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def open_binary(self, resource: str) -> BinaryIO:
|
||||
"""
|
||||
Obtain a File-like for a named resource.
|
||||
"""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.package.split('.')[-1]
|
||||
|
||||
|
||||
class ResourceContainer(Traversable):
|
||||
"""
|
||||
Traversable container for a package's resources via its reader.
|
||||
"""
|
||||
|
||||
def __init__(self, reader: SimpleReader):
|
||||
self.reader = reader
|
||||
|
||||
def is_dir(self):
|
||||
return True
|
||||
|
||||
def is_file(self):
|
||||
return False
|
||||
|
||||
def iterdir(self):
|
||||
files = (ResourceHandle(self, name) for name in self.reader.resources)
|
||||
dirs = map(ResourceContainer, self.reader.children())
|
||||
return itertools.chain(files, dirs)
|
||||
|
||||
def open(self, *args, **kwargs):
|
||||
raise IsADirectoryError()
|
||||
|
||||
|
||||
class ResourceHandle(Traversable):
|
||||
"""
|
||||
Handle to a named resource in a ResourceReader.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: ResourceContainer, name: str):
|
||||
self.parent = parent
|
||||
self.name = name # type: ignore[misc]
|
||||
|
||||
def is_file(self):
|
||||
return True
|
||||
|
||||
def is_dir(self):
|
||||
return False
|
||||
|
||||
def open(self, mode='r', *args, **kwargs):
|
||||
stream = self.parent.reader.open_binary(self.name)
|
||||
if 'b' not in mode:
|
||||
stream = io.TextIOWrapper(stream, *args, **kwargs)
|
||||
return stream
|
||||
|
||||
def joinpath(self, name):
|
||||
raise RuntimeError("Cannot traverse into a resource")
|
||||
|
||||
|
||||
class TraversableReader(TraversableResources, SimpleReader):
|
||||
"""
|
||||
A TraversableResources based on SimpleReader. Resource providers
|
||||
may derive from this class to provide the TraversableResources
|
||||
interface by supplying the SimpleReader interface.
|
||||
"""
|
||||
|
||||
def files(self):
|
||||
return ResourceContainer(self)
|
14
Dependencies/Python/Lib/importlib/simple.py
vendored
Normal file
14
Dependencies/Python/Lib/importlib/simple.py
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
"""
|
||||
Compatibility shim for .resources.simple as found on Python 3.10.
|
||||
|
||||
Consumers that can rely on Python 3.11 should use the other
|
||||
module directly.
|
||||
"""
|
||||
|
||||
from .resources.simple import (
|
||||
SimpleReader, ResourceHandle, ResourceContainer, TraversableReader,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'SimpleReader', 'ResourceHandle', 'ResourceContainer', 'TraversableReader',
|
||||
]
|
274
Dependencies/Python/Lib/importlib/util.py
vendored
Normal file
274
Dependencies/Python/Lib/importlib/util.py
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
"""Utility code for constructing importers, etc."""
|
||||
from ._abc import Loader
|
||||
from ._bootstrap import module_from_spec
|
||||
from ._bootstrap import _resolve_name
|
||||
from ._bootstrap import spec_from_loader
|
||||
from ._bootstrap import _find_spec
|
||||
from ._bootstrap_external import MAGIC_NUMBER
|
||||
from ._bootstrap_external import _RAW_MAGIC_NUMBER
|
||||
from ._bootstrap_external import cache_from_source
|
||||
from ._bootstrap_external import decode_source
|
||||
from ._bootstrap_external import source_from_cache
|
||||
from ._bootstrap_external import spec_from_file_location
|
||||
|
||||
import _imp
|
||||
import sys
|
||||
import types
|
||||
|
||||
|
||||
def source_hash(source_bytes):
|
||||
"Return the hash of *source_bytes* as used in hash-based pyc files."
|
||||
return _imp.source_hash(_RAW_MAGIC_NUMBER, source_bytes)
|
||||
|
||||
|
||||
def resolve_name(name, package):
|
||||
"""Resolve a relative module name to an absolute one."""
|
||||
if not name.startswith('.'):
|
||||
return name
|
||||
elif not package:
|
||||
raise ImportError(f'no package specified for {repr(name)} '
|
||||
'(required for relative module names)')
|
||||
level = 0
|
||||
for character in name:
|
||||
if character != '.':
|
||||
break
|
||||
level += 1
|
||||
return _resolve_name(name[level:], package, level)
|
||||
|
||||
|
||||
def _find_spec_from_path(name, path=None):
|
||||
"""Return the spec for the specified module.
|
||||
|
||||
First, sys.modules is checked to see if the module was already imported. If
|
||||
so, then sys.modules[name].__spec__ is returned. If that happens to be
|
||||
set to None, then ValueError is raised. If the module is not in
|
||||
sys.modules, then sys.meta_path is searched for a suitable spec with the
|
||||
value of 'path' given to the finders. None is returned if no spec could
|
||||
be found.
|
||||
|
||||
Dotted names do not have their parent packages implicitly imported. You will
|
||||
most likely need to explicitly import all parent packages in the proper
|
||||
order for a submodule to get the correct spec.
|
||||
|
||||
"""
|
||||
if name not in sys.modules:
|
||||
return _find_spec(name, path)
|
||||
else:
|
||||
module = sys.modules[name]
|
||||
if module is None:
|
||||
return None
|
||||
try:
|
||||
spec = module.__spec__
|
||||
except AttributeError:
|
||||
raise ValueError(f'{name}.__spec__ is not set') from None
|
||||
else:
|
||||
if spec is None:
|
||||
raise ValueError(f'{name}.__spec__ is None')
|
||||
return spec
|
||||
|
||||
|
||||
def find_spec(name, package=None):
|
||||
"""Return the spec for the specified module.
|
||||
|
||||
First, sys.modules is checked to see if the module was already imported. If
|
||||
so, then sys.modules[name].__spec__ is returned. If that happens to be
|
||||
set to None, then ValueError is raised. If the module is not in
|
||||
sys.modules, then sys.meta_path is searched for a suitable spec with the
|
||||
value of 'path' given to the finders. None is returned if no spec could
|
||||
be found.
|
||||
|
||||
If the name is for submodule (contains a dot), the parent module is
|
||||
automatically imported.
|
||||
|
||||
The name and package arguments work the same as importlib.import_module().
|
||||
In other words, relative module names (with leading dots) work.
|
||||
|
||||
"""
|
||||
fullname = resolve_name(name, package) if name.startswith('.') else name
|
||||
if fullname not in sys.modules:
|
||||
parent_name = fullname.rpartition('.')[0]
|
||||
if parent_name:
|
||||
parent = __import__(parent_name, fromlist=['__path__'])
|
||||
try:
|
||||
parent_path = parent.__path__
|
||||
except AttributeError as e:
|
||||
raise ModuleNotFoundError(
|
||||
f"__path__ attribute not found on {parent_name!r} "
|
||||
f"while trying to find {fullname!r}", name=fullname) from e
|
||||
else:
|
||||
parent_path = None
|
||||
return _find_spec(fullname, parent_path)
|
||||
else:
|
||||
module = sys.modules[fullname]
|
||||
if module is None:
|
||||
return None
|
||||
try:
|
||||
spec = module.__spec__
|
||||
except AttributeError:
|
||||
raise ValueError(f'{name}.__spec__ is not set') from None
|
||||
else:
|
||||
if spec is None:
|
||||
raise ValueError(f'{name}.__spec__ is None')
|
||||
return spec
|
||||
|
||||
|
||||
# Normally we would use contextlib.contextmanager. However, this module
|
||||
# is imported by runpy, which means we want to avoid any unnecessary
|
||||
# dependencies. Thus we use a class.
|
||||
|
||||
class _incompatible_extension_module_restrictions:
|
||||
"""A context manager that can temporarily skip the compatibility check.
|
||||
|
||||
NOTE: This function is meant to accommodate an unusual case; one
|
||||
which is likely to eventually go away. There's is a pretty good
|
||||
chance this is not what you were looking for.
|
||||
|
||||
WARNING: Using this function to disable the check can lead to
|
||||
unexpected behavior and even crashes. It should only be used during
|
||||
extension module development.
|
||||
|
||||
If "disable_check" is True then the compatibility check will not
|
||||
happen while the context manager is active. Otherwise the check
|
||||
*will* happen.
|
||||
|
||||
Normally, extensions that do not support multiple interpreters
|
||||
may not be imported in a subinterpreter. That implies modules
|
||||
that do not implement multi-phase init or that explicitly of out.
|
||||
|
||||
Likewise for modules import in a subinterpreter with its own GIL
|
||||
when the extension does not support a per-interpreter GIL. This
|
||||
implies the module does not have a Py_mod_multiple_interpreters slot
|
||||
set to Py_MOD_PER_INTERPRETER_GIL_SUPPORTED.
|
||||
|
||||
In both cases, this context manager may be used to temporarily
|
||||
disable the check for compatible extension modules.
|
||||
|
||||
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 multiple interpreters (or per-interpreter GIL).
|
||||
"""
|
||||
|
||||
def __init__(self, *, disable_check):
|
||||
self.disable_check = bool(disable_check)
|
||||
|
||||
def __enter__(self):
|
||||
self.old = _imp._override_multi_interp_extensions_check(self.override)
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
old = self.old
|
||||
del self.old
|
||||
_imp._override_multi_interp_extensions_check(old)
|
||||
|
||||
@property
|
||||
def override(self):
|
||||
return -1 if self.disable_check else 1
|
||||
|
||||
|
||||
class _LazyModule(types.ModuleType):
|
||||
|
||||
"""A subclass of the module type which triggers loading upon attribute access."""
|
||||
|
||||
def __getattribute__(self, attr):
|
||||
"""Trigger the load of the module and return the attribute."""
|
||||
__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:
|
||||
__class__ = loader_state['__class__']
|
||||
|
||||
# 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 __class__.__getattribute__(self, attr)
|
||||
loader_state['is_loading'] = True
|
||||
|
||||
__dict__ = __class__.__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, if the module did not
|
||||
# already update its own __class__.
|
||||
if isinstance(self, _LazyModule):
|
||||
object.__setattr__(self, '__class__', __class__)
|
||||
|
||||
return getattr(self, attr)
|
||||
|
||||
def __delattr__(self, attr):
|
||||
"""Trigger the load and then perform the deletion."""
|
||||
# To trigger the load and raise an exception if the attribute
|
||||
# doesn't exist.
|
||||
self.__getattribute__(attr)
|
||||
delattr(self, attr)
|
||||
|
||||
|
||||
class LazyLoader(Loader):
|
||||
|
||||
"""A loader that creates a module which defers loading until attribute access."""
|
||||
|
||||
@staticmethod
|
||||
def __check_eager_loader(loader):
|
||||
if not hasattr(loader, 'exec_module'):
|
||||
raise TypeError('loader must define exec_module()')
|
||||
|
||||
@classmethod
|
||||
def factory(cls, loader):
|
||||
"""Construct a callable which returns the eager loader made lazy."""
|
||||
cls.__check_eager_loader(loader)
|
||||
return lambda *args, **kwargs: cls(loader(*args, **kwargs))
|
||||
|
||||
def __init__(self, loader):
|
||||
self.__check_eager_loader(loader)
|
||||
self.loader = loader
|
||||
|
||||
def create_module(self, spec):
|
||||
return self.loader.create_module(spec)
|
||||
|
||||
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
|
||||
# on an object would have triggered the load,
|
||||
# e.g. ``module.__spec__.loader = None`` would trigger a load from
|
||||
# trying to access module.__spec__.
|
||||
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
|
Reference in New Issue
Block a user