summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Lib/importlib/_bootstrap_external.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Lib/importlib/_bootstrap_external.py')
-rw-r--r--contrib/tools/python3/Lib/importlib/_bootstrap_external.py105
1 files changed, 91 insertions, 14 deletions
diff --git a/contrib/tools/python3/Lib/importlib/_bootstrap_external.py b/contrib/tools/python3/Lib/importlib/_bootstrap_external.py
index 9b8a8dfc5aa..0741f62ee83 100644
--- a/contrib/tools/python3/Lib/importlib/_bootstrap_external.py
+++ b/contrib/tools/python3/Lib/importlib/_bootstrap_external.py
@@ -52,7 +52,7 @@ _pathseps_with_colon = {f':{s}' for s in path_separators}
# Bootstrap-related code ######################################################
_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
-_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin'
+_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin', 'ios', 'tvos', 'watchos'
_CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY
+ _CASE_INSENSITIVE_PLATFORMS_STR_KEY)
@@ -81,6 +81,11 @@ def _pack_uint32(x):
return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little')
+def _unpack_uint64(data):
+ """Convert 8 bytes in little-endian to an integer."""
+ assert len(data) == 8
+ return int.from_bytes(data, 'little')
+
def _unpack_uint32(data):
"""Convert 4 bytes in little-endian to an integer."""
assert len(data) == 4
@@ -203,12 +208,8 @@ def _write_atomic(path, data, mode=0o666):
try:
# We first write data to a temporary file, and then use os.replace() to
# perform an atomic rename.
- with _io.FileIO(fd, 'wb') as file:
- bytes_written = file.write(data)
- if bytes_written != len(data):
- # Raise an OSError so the 'except' below cleans up the partially
- # written file.
- raise OSError("os.write() didn't write the full pyc file")
+ with _io.open(fd, 'wb') as file:
+ file.write(data)
_os.replace(path_tmp, path)
except OSError:
try:
@@ -450,8 +451,30 @@ _code_type = type(_write_atomic.__code__)
# Python 3.12b1 3529 (Inline list/dict/set comprehensions)
# Python 3.12b1 3530 (Shrink the LOAD_SUPER_ATTR caches)
# Python 3.12b1 3531 (Add PEP 695 changes)
+# Python 3.13a1 3550 (Plugin optimizer support)
+# Python 3.13a1 3551 (Compact superinstructions)
+# Python 3.13a1 3552 (Remove LOAD_FAST__LOAD_CONST and LOAD_CONST__LOAD_FAST)
+# Python 3.13a1 3553 (Add SET_FUNCTION_ATTRIBUTE)
+# Python 3.13a1 3554 (more efficient bytecodes for f-strings)
+# Python 3.13a1 3555 (generate specialized opcodes metadata from bytecodes.c)
+# Python 3.13a1 3556 (Convert LOAD_CLOSURE to a pseudo-op)
+# Python 3.13a1 3557 (Make the conversion to boolean in jumps explicit)
+# Python 3.13a1 3558 (Reorder the stack items for CALL)
+# Python 3.13a1 3559 (Generate opcode IDs from bytecodes.c)
+# Python 3.13a1 3560 (Add RESUME_CHECK instruction)
+# Python 3.13a1 3561 (Add cache entry to branch instructions)
+# Python 3.13a1 3562 (Assign opcode IDs for internal ops in separate range)
+# Python 3.13a1 3563 (Add CALL_KW and remove KW_NAMES)
+# Python 3.13a1 3564 (Removed oparg from YIELD_VALUE, changed oparg values of RESUME)
+# Python 3.13a1 3565 (Oparg of YIELD_VALUE indicates whether it is in a yield-from)
+# Python 3.13a1 3566 (Emit JUMP_NO_INTERRUPT instead of JUMP for non-loop no-lineno cases)
+# Python 3.13a1 3567 (Reimplement line number propagation by the compiler)
+# Python 3.13a1 3568 (Change semantics of END_FOR)
+# Python 3.13a5 3569 (Specialize CONTAINS_OP)
+# Python 3.13a6 3570 (Add __firstlineno__ class attribute)
+# Python 3.13b1 3571 (Fix miscompilation of private names in generic classes)
-# Python 3.13 will start with 3550
+# Python 3.14 will start with 3600
# Please don't copy-paste the same pre-release tag for new entries above!!!
# You should always use the *upcoming* tag. For example, if 3.12a6 came out
@@ -466,7 +489,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
-MAGIC_NUMBER = (3531).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3571).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
@@ -540,7 +563,8 @@ def cache_from_source(path, debug_override=None, *, optimization=None):
# Strip initial drive from a Windows path. We know we have an absolute
# path here, so the second part of the check rules out a POSIX path that
# happens to contain a colon at the second character.
- if head[1] == ':' and head[0] not in path_separators:
+ # Slicing avoids issues with an empty (or short) `head`.
+ if head[1:2] == ':' and head[0:1] not in path_separators:
head = head[2:]
# Strip initial path separator from `head` to complete the conversion
@@ -1186,7 +1210,7 @@ class FileLoader:
def get_data(self, path):
"""Return the data from path as raw bytes."""
- if isinstance(self, (SourceLoader, ExtensionFileLoader)):
+ if isinstance(self, (SourceLoader, SourcelessFileLoader, ExtensionFileLoader)):
with _io.open_code(str(path)) as file:
return file.read()
else:
@@ -1442,7 +1466,7 @@ class PathFinder:
@staticmethod
def invalidate_caches():
"""Call the invalidate_caches() method on all path entry finders
- stored in sys.path_importer_caches (where implemented)."""
+ stored in sys.path_importer_cache (where implemented)."""
for name, finder in list(sys.path_importer_cache.items()):
# Drop entry if finder name is a relative path. The current
# working directory may have changed.
@@ -1698,6 +1722,52 @@ class FileFinder:
return f'FileFinder({self.path!r})'
+class AppleFrameworkLoader(ExtensionFileLoader):
+ """A loader for modules that have been packaged as frameworks for
+ compatibility with Apple's iOS App Store policies.
+ """
+ def create_module(self, spec):
+ # If the ModuleSpec has been created by the FileFinder, it will have
+ # been created with an origin pointing to the .fwork file. We need to
+ # redirect this to the location in the Frameworks folder, using the
+ # content of the .fwork file.
+ if spec.origin.endswith(".fwork"):
+ with _io.FileIO(spec.origin, 'r') as file:
+ framework_binary = file.read().decode().strip()
+ bundle_path = _path_split(sys.executable)[0]
+ spec.origin = _path_join(bundle_path, framework_binary)
+
+ # If the loader is created based on the spec for a loaded module, the
+ # path will be pointing at the Framework location. If this occurs,
+ # get the original .fwork location to use as the module's __file__.
+ if self.path.endswith(".fwork"):
+ path = self.path
+ else:
+ with _io.FileIO(self.path + ".origin", 'r') as file:
+ origin = file.read().decode().strip()
+ bundle_path = _path_split(sys.executable)[0]
+ path = _path_join(bundle_path, origin)
+
+ module = _bootstrap._call_with_frames_removed(_imp.create_dynamic, spec)
+
+ _bootstrap._verbose_message(
+ "Apple framework extension module {!r} loaded from {!r} (path {!r})",
+ spec.name,
+ spec.origin,
+ path,
+ )
+
+ # Ensure that the __file__ points at the .fwork location
+ try:
+ module.__file__ = path
+ except AttributeError:
+ # Not important enough to report.
+ # (The error is also ignored in _bootstrap._init_module_attrs or
+ # import_run_extension in import.c)
+ pass
+
+ return module
+
# Import setup ###############################################################
def _fix_up_module(ns, name, pathname, cpathname=None):
@@ -1730,10 +1800,17 @@ def _get_supported_file_loaders():
Each item is a tuple (loader, suffixes).
"""
- extensions = ExtensionFileLoader, _imp.extension_suffixes()
+ extension_loaders = []
+ if hasattr(_imp, 'create_dynamic'):
+ if sys.platform in {"ios", "tvos", "watchos"}:
+ extension_loaders = [(AppleFrameworkLoader, [
+ suffix.replace(".so", ".fwork")
+ for suffix in _imp.extension_suffixes()
+ ])]
+ extension_loaders.append((ExtensionFileLoader, _imp.extension_suffixes()))
source = SourceFileLoader, SOURCE_SUFFIXES
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
- return [extensions, source, bytecode]
+ return extension_loaders + [source, bytecode]
def _set_bootstrap_module(_bootstrap_module):