Skip to content

Commit a4df238

Browse files
authored
Updated the importlib + nturl2path + pathlib libraries + associated tests - v3.13.10 (#6609)
* Updated the nturl2path library * Updated pathlib library + test * Updated urllib test * Added expectedFailure to failing tests * Updated importlib library
1 parent 1e706d9 commit a4df238

25 files changed

+6751
-5116
lines changed

Lib/importlib/__init__.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@
5454
# Fully bootstrapped at this point, import whatever you like, circular
5555
# dependencies and startup overhead minimisation permitting :)
5656

57-
import warnings
58-
5957

6058
# Public API #########################################################
6159

@@ -105,7 +103,7 @@ def reload(module):
105103
try:
106104
name = module.__name__
107105
except AttributeError:
108-
raise TypeError("reload() argument must be a module")
106+
raise TypeError("reload() argument must be a module") from None
109107

110108
if sys.modules.get(name) is not module:
111109
raise ImportError(f"module {name} not in sys.modules", name=name)

Lib/importlib/_bootstrap.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def _new_module(name):
5353

5454
# For a list that can have a weakref to it.
5555
class _List(list):
56-
pass
56+
__slots__ = ("__weakref__",)
5757

5858

5959
# Copied from weakref.py with some simplifications and modifications unique to
@@ -527,7 +527,7 @@ def _load_module_shim(self, fullname):
527527
528528
"""
529529
msg = ("the load_module() method is deprecated and slated for removal in "
530-
"Python 3.12; use exec_module() instead")
530+
"Python 3.15; use exec_module() instead")
531531
_warnings.warn(msg, DeprecationWarning)
532532
spec = spec_from_loader(fullname, self)
533533
if fullname in sys.modules:
@@ -825,10 +825,16 @@ def _module_repr_from_spec(spec):
825825
"""Return the repr to use for the module."""
826826
name = '?' if spec.name is None else spec.name
827827
if spec.origin is None:
828-
if spec.loader is None:
828+
loader = spec.loader
829+
if loader is None:
829830
return f'<module {name!r}>'
831+
elif (
832+
_bootstrap_external is not None
833+
and isinstance(loader, _bootstrap_external.NamespaceLoader)
834+
):
835+
return f'<module {name!r} (namespace) from {list(loader._path)}>'
830836
else:
831-
return f'<module {name!r} (namespace) from {list(spec.loader._path)}>'
837+
return f'<module {name!r} ({loader!r})>'
832838
else:
833839
if spec.has_location:
834840
return f'<module {name!r} from {spec.origin!r}>'
@@ -1129,7 +1135,7 @@ def find_spec(cls, fullname, path=None, target=None):
11291135
# part of the importer), instead of here (the finder part).
11301136
# The loader is the usual place to get the data that will
11311137
# be loaded into the module. (For example, see _LoaderBasics
1132-
# in _bootstra_external.py.) Most importantly, this importer
1138+
# in _bootstrap_external.py.) Most importantly, this importer
11331139
# is simpler if we wait to get the data.
11341140
# However, getting as much data in the finder as possible
11351141
# to later load the module is okay, and sometimes important.

Lib/importlib/_bootstrap_external.py

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252

5353
# Bootstrap-related code ######################################################
5454
_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
55-
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin'
55+
_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin', 'ios', 'tvos', 'watchos'
5656
_CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY
5757
+ _CASE_INSENSITIVE_PLATFORMS_STR_KEY)
5858

@@ -81,6 +81,11 @@ def _pack_uint32(x):
8181
return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little')
8282

8383

84+
def _unpack_uint64(data):
85+
"""Convert 8 bytes in little-endian to an integer."""
86+
assert len(data) == 8
87+
return int.from_bytes(data, 'little')
88+
8489
def _unpack_uint32(data):
8590
"""Convert 4 bytes in little-endian to an integer."""
8691
assert len(data) == 4
@@ -203,7 +208,7 @@ def _write_atomic(path, data, mode=0o666):
203208
try:
204209
# We first write data to a temporary file, and then use os.replace() to
205210
# perform an atomic rename.
206-
with _io.FileIO(fd, 'wb') as file:
211+
with _io.open(fd, 'wb') as file:
207212
file.write(data)
208213
_os.replace(path_tmp, path)
209214
except OSError:
@@ -413,6 +418,7 @@ def _write_atomic(path, data, mode=0o666):
413418
# Python 3.11a7 3492 (make POP_JUMP_IF_NONE/NOT_NONE/TRUE/FALSE relative)
414419
# Python 3.11a7 3493 (Make JUMP_IF_TRUE_OR_POP/JUMP_IF_FALSE_OR_POP relative)
415420
# Python 3.11a7 3494 (New location info table)
421+
# Python 3.11b4 3495 (Set line number of module's RESUME instr to 0 per PEP 626)
416422
# Python 3.12a1 3500 (Remove PRECALL opcode)
417423
# Python 3.12a1 3501 (YIELD_VALUE oparg == stack_depth)
418424
# Python 3.12a1 3502 (LOAD_FAST_CHECK, no NULL-check in LOAD_FAST)
@@ -445,8 +451,30 @@ def _write_atomic(path, data, mode=0o666):
445451
# Python 3.12b1 3529 (Inline list/dict/set comprehensions)
446452
# Python 3.12b1 3530 (Shrink the LOAD_SUPER_ATTR caches)
447453
# Python 3.12b1 3531 (Add PEP 695 changes)
448-
449-
# Python 3.13 will start with 3550
454+
# Python 3.13a1 3550 (Plugin optimizer support)
455+
# Python 3.13a1 3551 (Compact superinstructions)
456+
# Python 3.13a1 3552 (Remove LOAD_FAST__LOAD_CONST and LOAD_CONST__LOAD_FAST)
457+
# Python 3.13a1 3553 (Add SET_FUNCTION_ATTRIBUTE)
458+
# Python 3.13a1 3554 (more efficient bytecodes for f-strings)
459+
# Python 3.13a1 3555 (generate specialized opcodes metadata from bytecodes.c)
460+
# Python 3.13a1 3556 (Convert LOAD_CLOSURE to a pseudo-op)
461+
# Python 3.13a1 3557 (Make the conversion to boolean in jumps explicit)
462+
# Python 3.13a1 3558 (Reorder the stack items for CALL)
463+
# Python 3.13a1 3559 (Generate opcode IDs from bytecodes.c)
464+
# Python 3.13a1 3560 (Add RESUME_CHECK instruction)
465+
# Python 3.13a1 3561 (Add cache entry to branch instructions)
466+
# Python 3.13a1 3562 (Assign opcode IDs for internal ops in separate range)
467+
# Python 3.13a1 3563 (Add CALL_KW and remove KW_NAMES)
468+
# Python 3.13a1 3564 (Removed oparg from YIELD_VALUE, changed oparg values of RESUME)
469+
# Python 3.13a1 3565 (Oparg of YIELD_VALUE indicates whether it is in a yield-from)
470+
# Python 3.13a1 3566 (Emit JUMP_NO_INTERRUPT instead of JUMP for non-loop no-lineno cases)
471+
# Python 3.13a1 3567 (Reimplement line number propagation by the compiler)
472+
# Python 3.13a1 3568 (Change semantics of END_FOR)
473+
# Python 3.13a5 3569 (Specialize CONTAINS_OP)
474+
# Python 3.13a6 3570 (Add __firstlineno__ class attribute)
475+
# Python 3.13b1 3571 (Fix miscompilation of private names in generic classes)
476+
477+
# Python 3.14 will start with 3600
450478

451479
# Please don't copy-paste the same pre-release tag for new entries above!!!
452480
# You should always use the *upcoming* tag. For example, if 3.12a6 came out
@@ -461,7 +489,7 @@ def _write_atomic(path, data, mode=0o666):
461489
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
462490
# in PC/launcher.c must also be updated.
463491

464-
MAGIC_NUMBER = (3531).to_bytes(2, 'little') + b'\r\n'
492+
MAGIC_NUMBER = (3571).to_bytes(2, 'little') + b'\r\n'
465493

466494
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
467495

@@ -535,7 +563,8 @@ def cache_from_source(path, debug_override=None, *, optimization=None):
535563
# Strip initial drive from a Windows path. We know we have an absolute
536564
# path here, so the second part of the check rules out a POSIX path that
537565
# happens to contain a colon at the second character.
538-
if head[1] == ':' and head[0] not in path_separators:
566+
# Slicing avoids issues with an empty (or short) `head`.
567+
if head[1:2] == ':' and head[0:1] not in path_separators:
539568
head = head[2:]
540569

541570
# Strip initial path separator from `head` to complete the conversion
@@ -1437,7 +1466,7 @@ class PathFinder:
14371466
@staticmethod
14381467
def invalidate_caches():
14391468
"""Call the invalidate_caches() method on all path entry finders
1440-
stored in sys.path_importer_caches (where implemented)."""
1469+
stored in sys.path_importer_cache (where implemented)."""
14411470
for name, finder in list(sys.path_importer_cache.items()):
14421471
# Drop entry if finder name is a relative path. The current
14431472
# working directory may have changed.
@@ -1449,6 +1478,9 @@ def invalidate_caches():
14491478
# https://bugs.python.org/issue45703
14501479
_NamespacePath._epoch += 1
14511480

1481+
from importlib.metadata import MetadataPathFinder
1482+
MetadataPathFinder.invalidate_caches()
1483+
14521484
@staticmethod
14531485
def _path_hooks(path):
14541486
"""Search sys.path_hooks for a finder for 'path'."""
@@ -1690,6 +1722,52 @@ def __repr__(self):
16901722
return f'FileFinder({self.path!r})'
16911723

16921724

1725+
class AppleFrameworkLoader(ExtensionFileLoader):
1726+
"""A loader for modules that have been packaged as frameworks for
1727+
compatibility with Apple's iOS App Store policies.
1728+
"""
1729+
def create_module(self, spec):
1730+
# If the ModuleSpec has been created by the FileFinder, it will have
1731+
# been created with an origin pointing to the .fwork file. We need to
1732+
# redirect this to the location in the Frameworks folder, using the
1733+
# content of the .fwork file.
1734+
if spec.origin.endswith(".fwork"):
1735+
with _io.FileIO(spec.origin, 'r') as file:
1736+
framework_binary = file.read().decode().strip()
1737+
bundle_path = _path_split(sys.executable)[0]
1738+
spec.origin = _path_join(bundle_path, framework_binary)
1739+
1740+
# If the loader is created based on the spec for a loaded module, the
1741+
# path will be pointing at the Framework location. If this occurs,
1742+
# get the original .fwork location to use as the module's __file__.
1743+
if self.path.endswith(".fwork"):
1744+
path = self.path
1745+
else:
1746+
with _io.FileIO(self.path + ".origin", 'r') as file:
1747+
origin = file.read().decode().strip()
1748+
bundle_path = _path_split(sys.executable)[0]
1749+
path = _path_join(bundle_path, origin)
1750+
1751+
module = _bootstrap._call_with_frames_removed(_imp.create_dynamic, spec)
1752+
1753+
_bootstrap._verbose_message(
1754+
"Apple framework extension module {!r} loaded from {!r} (path {!r})",
1755+
spec.name,
1756+
spec.origin,
1757+
path,
1758+
)
1759+
1760+
# Ensure that the __file__ points at the .fwork location
1761+
try:
1762+
module.__file__ = path
1763+
except AttributeError:
1764+
# Not important enough to report.
1765+
# (The error is also ignored in _bootstrap._init_module_attrs or
1766+
# import_run_extension in import.c)
1767+
pass
1768+
1769+
return module
1770+
16931771
# Import setup ###############################################################
16941772

16951773
def _fix_up_module(ns, name, pathname, cpathname=None):
@@ -1722,10 +1800,17 @@ def _get_supported_file_loaders():
17221800
17231801
Each item is a tuple (loader, suffixes).
17241802
"""
1725-
extensions = ExtensionFileLoader, _imp.extension_suffixes()
1803+
extension_loaders = []
1804+
if hasattr(_imp, 'create_dynamic'):
1805+
if sys.platform in {"ios", "tvos", "watchos"}:
1806+
extension_loaders = [(AppleFrameworkLoader, [
1807+
suffix.replace(".so", ".fwork")
1808+
for suffix in _imp.extension_suffixes()
1809+
])]
1810+
extension_loaders.append((ExtensionFileLoader, _imp.extension_suffixes()))
17261811
source = SourceFileLoader, SOURCE_SUFFIXES
17271812
bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
1728-
return [extensions, source, bytecode]
1813+
return extension_loaders + [source, bytecode]
17291814

17301815

17311816
def _set_bootstrap_module(_bootstrap_module):

Lib/importlib/abc.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,11 @@ def get_code(self, fullname):
180180
else:
181181
return self.source_to_code(source, path)
182182

183-
_register(ExecutionLoader, machinery.ExtensionFileLoader)
183+
_register(
184+
ExecutionLoader,
185+
machinery.ExtensionFileLoader,
186+
machinery.AppleFrameworkLoader,
187+
)
184188

185189

186190
class FileLoader(_bootstrap_external.FileLoader, ResourceLoader, ExecutionLoader):

Lib/importlib/machinery.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from ._bootstrap_external import SourceFileLoader
1313
from ._bootstrap_external import SourcelessFileLoader
1414
from ._bootstrap_external import ExtensionFileLoader
15+
from ._bootstrap_external import AppleFrameworkLoader
1516
from ._bootstrap_external import NamespaceLoader
1617

1718

0 commit comments

Comments
 (0)