• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Core implementation of path-based import.
2
3This module is NOT meant to be directly imported! It has been designed such
4that it can be bootstrapped into Python as the implementation of import. As
5such it requires the injection of specific modules and attributes in order to
6work. One should use importlib as the public-facing version of this module.
7
8"""
9# IMPORTANT: Whenever making changes to this module, be sure to run a top-level
10# `make regen-importlib` followed by `make` in order to get the frozen version
11# of the module updated. Not doing so will result in the Makefile to fail for
12# all others who don't have a ./python around to freeze the module in the early
13# stages of compilation.
14#
15
16# See importlib._setup() for what is injected into the global namespace.
17
18# When editing this code be aware that code executed at import time CANNOT
19# reference any injected objects! This includes not only global code but also
20# anything specified at the class level.
21
22# Bootstrap-related code ######################################################
23_CASE_INSENSITIVE_PLATFORMS_STR_KEY = 'win',
24_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY = 'cygwin', 'darwin'
25_CASE_INSENSITIVE_PLATFORMS =  (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY
26                                + _CASE_INSENSITIVE_PLATFORMS_STR_KEY)
27
28
29def _make_relax_case():
30    if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS):
31        if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS_STR_KEY):
32            key = 'PYTHONCASEOK'
33        else:
34            key = b'PYTHONCASEOK'
35
36        def _relax_case():
37            """True if filenames must be checked case-insensitively."""
38            return key in _os.environ
39    else:
40        def _relax_case():
41            """True if filenames must be checked case-insensitively."""
42            return False
43    return _relax_case
44
45
46def _pack_uint32(x):
47    """Convert a 32-bit integer to little-endian."""
48    return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little')
49
50
51def _unpack_uint32(data):
52    """Convert 4 bytes in little-endian to an integer."""
53    assert len(data) == 4
54    return int.from_bytes(data, 'little')
55
56def _unpack_uint16(data):
57    """Convert 2 bytes in little-endian to an integer."""
58    assert len(data) == 2
59    return int.from_bytes(data, 'little')
60
61
62def _path_join(*path_parts):
63    """Replacement for os.path.join()."""
64    return path_sep.join([part.rstrip(path_separators)
65                          for part in path_parts if part])
66
67
68def _path_split(path):
69    """Replacement for os.path.split()."""
70    if len(path_separators) == 1:
71        front, _, tail = path.rpartition(path_sep)
72        return front, tail
73    for x in reversed(path):
74        if x in path_separators:
75            front, tail = path.rsplit(x, maxsplit=1)
76            return front, tail
77    return '', path
78
79
80def _path_stat(path):
81    """Stat the path.
82
83    Made a separate function to make it easier to override in experiments
84    (e.g. cache stat results).
85
86    """
87    return _os.stat(path)
88
89
90def _path_is_mode_type(path, mode):
91    """Test whether the path is the specified mode type."""
92    try:
93        stat_info = _path_stat(path)
94    except OSError:
95        return False
96    return (stat_info.st_mode & 0o170000) == mode
97
98
99def _path_isfile(path):
100    """Replacement for os.path.isfile."""
101    return _path_is_mode_type(path, 0o100000)
102
103
104def _path_isdir(path):
105    """Replacement for os.path.isdir."""
106    if not path:
107        path = _os.getcwd()
108    return _path_is_mode_type(path, 0o040000)
109
110
111def _path_isabs(path):
112    """Replacement for os.path.isabs.
113
114    Considers a Windows drive-relative path (no drive, but starts with slash) to
115    still be "absolute".
116    """
117    return path.startswith(path_separators) or path[1:3] in _pathseps_with_colon
118
119
120def _write_atomic(path, data, mode=0o666):
121    """Best-effort function to write data to a path atomically.
122    Be prepared to handle a FileExistsError if concurrent writing of the
123    temporary file is attempted."""
124    # id() is used to generate a pseudo-random filename.
125    path_tmp = '{}.{}'.format(path, id(path))
126    fd = _os.open(path_tmp,
127                  _os.O_EXCL | _os.O_CREAT | _os.O_WRONLY, mode & 0o666)
128    try:
129        # We first write data to a temporary file, and then use os.replace() to
130        # perform an atomic rename.
131        with _io.FileIO(fd, 'wb') as file:
132            file.write(data)
133        _os.replace(path_tmp, path)
134    except OSError:
135        try:
136            _os.unlink(path_tmp)
137        except OSError:
138            pass
139        raise
140
141
142_code_type = type(_write_atomic.__code__)
143
144
145# Finder/loader utility code ###############################################
146
147# Magic word to reject .pyc files generated by other Python versions.
148# It should change for each incompatible change to the bytecode.
149#
150# The value of CR and LF is incorporated so if you ever read or write
151# a .pyc file in text mode the magic number will be wrong; also, the
152# Apple MPW compiler swaps their values, botching string constants.
153#
154# There were a variety of old schemes for setting the magic number.
155# The current working scheme is to increment the previous value by
156# 10.
157#
158# Starting with the adoption of PEP 3147 in Python 3.2, every bump in magic
159# number also includes a new "magic tag", i.e. a human readable string used
160# to represent the magic number in __pycache__ directories.  When you change
161# the magic number, you must also set a new unique magic tag.  Generally this
162# can be named after the Python major version of the magic number bump, but
163# it can really be anything, as long as it's different than anything else
164# that's come before.  The tags are included in the following table, starting
165# with Python 3.2a0.
166#
167# Known values:
168#  Python 1.5:   20121
169#  Python 1.5.1: 20121
170#     Python 1.5.2: 20121
171#     Python 1.6:   50428
172#     Python 2.0:   50823
173#     Python 2.0.1: 50823
174#     Python 2.1:   60202
175#     Python 2.1.1: 60202
176#     Python 2.1.2: 60202
177#     Python 2.2:   60717
178#     Python 2.3a0: 62011
179#     Python 2.3a0: 62021
180#     Python 2.3a0: 62011 (!)
181#     Python 2.4a0: 62041
182#     Python 2.4a3: 62051
183#     Python 2.4b1: 62061
184#     Python 2.5a0: 62071
185#     Python 2.5a0: 62081 (ast-branch)
186#     Python 2.5a0: 62091 (with)
187#     Python 2.5a0: 62092 (changed WITH_CLEANUP opcode)
188#     Python 2.5b3: 62101 (fix wrong code: for x, in ...)
189#     Python 2.5b3: 62111 (fix wrong code: x += yield)
190#     Python 2.5c1: 62121 (fix wrong lnotab with for loops and
191#                          storing constants that should have been removed)
192#     Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp)
193#     Python 2.6a0: 62151 (peephole optimizations and STORE_MAP opcode)
194#     Python 2.6a1: 62161 (WITH_CLEANUP optimization)
195#     Python 2.7a0: 62171 (optimize list comprehensions/change LIST_APPEND)
196#     Python 2.7a0: 62181 (optimize conditional branches:
197#                          introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE)
198#     Python 2.7a0  62191 (introduce SETUP_WITH)
199#     Python 2.7a0  62201 (introduce BUILD_SET)
200#     Python 2.7a0  62211 (introduce MAP_ADD and SET_ADD)
201#     Python 3000:   3000
202#                    3010 (removed UNARY_CONVERT)
203#                    3020 (added BUILD_SET)
204#                    3030 (added keyword-only parameters)
205#                    3040 (added signature annotations)
206#                    3050 (print becomes a function)
207#                    3060 (PEP 3115 metaclass syntax)
208#                    3061 (string literals become unicode)
209#                    3071 (PEP 3109 raise changes)
210#                    3081 (PEP 3137 make __file__ and __name__ unicode)
211#                    3091 (kill str8 interning)
212#                    3101 (merge from 2.6a0, see 62151)
213#                    3103 (__file__ points to source file)
214#     Python 3.0a4: 3111 (WITH_CLEANUP optimization).
215#     Python 3.0b1: 3131 (lexical exception stacking, including POP_EXCEPT
216                          #3021)
217#     Python 3.1a1: 3141 (optimize list, set and dict comprehensions:
218#                         change LIST_APPEND and SET_ADD, add MAP_ADD #2183)
219#     Python 3.1a1: 3151 (optimize conditional branches:
220#                         introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE
221                          #4715)
222#     Python 3.2a1: 3160 (add SETUP_WITH #6101)
223#                   tag: cpython-32
224#     Python 3.2a2: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR #9225)
225#                   tag: cpython-32
226#     Python 3.2a3  3180 (add DELETE_DEREF #4617)
227#     Python 3.3a1  3190 (__class__ super closure changed)
228#     Python 3.3a1  3200 (PEP 3155 __qualname__ added #13448)
229#     Python 3.3a1  3210 (added size modulo 2**32 to the pyc header #13645)
230#     Python 3.3a2  3220 (changed PEP 380 implementation #14230)
231#     Python 3.3a4  3230 (revert changes to implicit __class__ closure #14857)
232#     Python 3.4a1  3250 (evaluate positional default arguments before
233#                        keyword-only defaults #16967)
234#     Python 3.4a1  3260 (add LOAD_CLASSDEREF; allow locals of class to override
235#                        free vars #17853)
236#     Python 3.4a1  3270 (various tweaks to the __class__ closure #12370)
237#     Python 3.4a1  3280 (remove implicit class argument)
238#     Python 3.4a4  3290 (changes to __qualname__ computation #19301)
239#     Python 3.4a4  3300 (more changes to __qualname__ computation #19301)
240#     Python 3.4rc2 3310 (alter __qualname__ computation #20625)
241#     Python 3.5a1  3320 (PEP 465: Matrix multiplication operator #21176)
242#     Python 3.5b1  3330 (PEP 448: Additional Unpacking Generalizations #2292)
243#     Python 3.5b2  3340 (fix dictionary display evaluation order #11205)
244#     Python 3.5b3  3350 (add GET_YIELD_FROM_ITER opcode #24400)
245#     Python 3.5.2  3351 (fix BUILD_MAP_UNPACK_WITH_CALL opcode #27286)
246#     Python 3.6a0  3360 (add FORMAT_VALUE opcode #25483)
247#     Python 3.6a1  3361 (lineno delta of code.co_lnotab becomes signed #26107)
248#     Python 3.6a2  3370 (16 bit wordcode #26647)
249#     Python 3.6a2  3371 (add BUILD_CONST_KEY_MAP opcode #27140)
250#     Python 3.6a2  3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE
251#                         #27095)
252#     Python 3.6b1  3373 (add BUILD_STRING opcode #27078)
253#     Python 3.6b1  3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes
254#                         #27985)
255#     Python 3.6b1  3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL
256                          #27213)
257#     Python 3.6b1  3377 (set __class__ cell from type.__new__ #23722)
258#     Python 3.6b2  3378 (add BUILD_TUPLE_UNPACK_WITH_CALL #28257)
259#     Python 3.6rc1 3379 (more thorough __class__ validation #23722)
260#     Python 3.7a1  3390 (add LOAD_METHOD and CALL_METHOD opcodes #26110)
261#     Python 3.7a2  3391 (update GET_AITER #31709)
262#     Python 3.7a4  3392 (PEP 552: Deterministic pycs #31650)
263#     Python 3.7b1  3393 (remove STORE_ANNOTATION opcode #32550)
264#     Python 3.7b5  3394 (restored docstring as the first stmt in the body;
265#                         this might affected the first line number #32911)
266#     Python 3.8a1  3400 (move frame block handling to compiler #17611)
267#     Python 3.8a1  3401 (add END_ASYNC_FOR #33041)
268#     Python 3.8a1  3410 (PEP570 Python Positional-Only Parameters #36540)
269#     Python 3.8b2  3411 (Reverse evaluation order of key: value in dict
270#                         comprehensions #35224)
271#     Python 3.8b2  3412 (Swap the position of positional args and positional
272#                         only args in ast.arguments #37593)
273#     Python 3.8b4  3413 (Fix "break" and "continue" in "finally" #37830)
274#
275# MAGIC must change whenever the bytecode emitted by the compiler may no
276# longer be understood by older implementations of the eval loop (usually
277# due to the addition of new opcodes).
278#
279# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
280# in PC/launcher.c must also be updated.
281
282MAGIC_NUMBER = (3413).to_bytes(2, 'little') + b'\r\n'
283_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
284
285_PYCACHE = '__pycache__'
286_OPT = 'opt-'
287
288SOURCE_SUFFIXES = ['.py']  # _setup() adds .pyw as needed.
289
290BYTECODE_SUFFIXES = ['.pyc']
291# Deprecated.
292DEBUG_BYTECODE_SUFFIXES = OPTIMIZED_BYTECODE_SUFFIXES = BYTECODE_SUFFIXES
293
294def cache_from_source(path, debug_override=None, *, optimization=None):
295    """Given the path to a .py file, return the path to its .pyc file.
296
297    The .py file does not need to exist; this simply returns the path to the
298    .pyc file calculated as if the .py file were imported.
299
300    The 'optimization' parameter controls the presumed optimization level of
301    the bytecode file. If 'optimization' is not None, the string representation
302    of the argument is taken and verified to be alphanumeric (else ValueError
303    is raised).
304
305    The debug_override parameter is deprecated. If debug_override is not None,
306    a True value is the same as setting 'optimization' to the empty string
307    while a False value is equivalent to setting 'optimization' to '1'.
308
309    If sys.implementation.cache_tag is None then NotImplementedError is raised.
310
311    """
312    if debug_override is not None:
313        _warnings.warn('the debug_override parameter is deprecated; use '
314                       "'optimization' instead", DeprecationWarning)
315        if optimization is not None:
316            message = 'debug_override or optimization must be set to None'
317            raise TypeError(message)
318        optimization = '' if debug_override else 1
319    path = _os.fspath(path)
320    head, tail = _path_split(path)
321    base, sep, rest = tail.rpartition('.')
322    tag = sys.implementation.cache_tag
323    if tag is None:
324        raise NotImplementedError('sys.implementation.cache_tag is None')
325    almost_filename = ''.join([(base if base else rest), sep, tag])
326    if optimization is None:
327        if sys.flags.optimize == 0:
328            optimization = ''
329        else:
330            optimization = sys.flags.optimize
331    optimization = str(optimization)
332    if optimization != '':
333        if not optimization.isalnum():
334            raise ValueError('{!r} is not alphanumeric'.format(optimization))
335        almost_filename = '{}.{}{}'.format(almost_filename, _OPT, optimization)
336    filename = almost_filename + BYTECODE_SUFFIXES[0]
337    if sys.pycache_prefix is not None:
338        # We need an absolute path to the py file to avoid the possibility of
339        # collisions within sys.pycache_prefix, if someone has two different
340        # `foo/bar.py` on their system and they import both of them using the
341        # same sys.pycache_prefix. Let's say sys.pycache_prefix is
342        # `C:\Bytecode`; the idea here is that if we get `Foo\Bar`, we first
343        # make it absolute (`C:\Somewhere\Foo\Bar`), then make it root-relative
344        # (`Somewhere\Foo\Bar`), so we end up placing the bytecode file in an
345        # unambiguous `C:\Bytecode\Somewhere\Foo\Bar\`.
346        if not _path_isabs(head):
347            head = _path_join(_os.getcwd(), head)
348
349        # Strip initial drive from a Windows path. We know we have an absolute
350        # path here, so the second part of the check rules out a POSIX path that
351        # happens to contain a colon at the second character.
352        if head[1] == ':' and head[0] not in path_separators:
353            head = head[2:]
354
355        # Strip initial path separator from `head` to complete the conversion
356        # back to a root-relative path before joining.
357        return _path_join(
358            sys.pycache_prefix,
359            head.lstrip(path_separators),
360            filename,
361        )
362    return _path_join(head, _PYCACHE, filename)
363
364
365def source_from_cache(path):
366    """Given the path to a .pyc. file, return the path to its .py file.
367
368    The .pyc file does not need to exist; this simply returns the path to
369    the .py file calculated to correspond to the .pyc file.  If path does
370    not conform to PEP 3147/488 format, ValueError will be raised. If
371    sys.implementation.cache_tag is None then NotImplementedError is raised.
372
373    """
374    if sys.implementation.cache_tag is None:
375        raise NotImplementedError('sys.implementation.cache_tag is None')
376    path = _os.fspath(path)
377    head, pycache_filename = _path_split(path)
378    found_in_pycache_prefix = False
379    if sys.pycache_prefix is not None:
380        stripped_path = sys.pycache_prefix.rstrip(path_separators)
381        if head.startswith(stripped_path + path_sep):
382            head = head[len(stripped_path):]
383            found_in_pycache_prefix = True
384    if not found_in_pycache_prefix:
385        head, pycache = _path_split(head)
386        if pycache != _PYCACHE:
387            raise ValueError(f'{_PYCACHE} not bottom-level directory in '
388                             f'{path!r}')
389    dot_count = pycache_filename.count('.')
390    if dot_count not in {2, 3}:
391        raise ValueError(f'expected only 2 or 3 dots in {pycache_filename!r}')
392    elif dot_count == 3:
393        optimization = pycache_filename.rsplit('.', 2)[-2]
394        if not optimization.startswith(_OPT):
395            raise ValueError("optimization portion of filename does not start "
396                             f"with {_OPT!r}")
397        opt_level = optimization[len(_OPT):]
398        if not opt_level.isalnum():
399            raise ValueError(f"optimization level {optimization!r} is not an "
400                             "alphanumeric value")
401    base_filename = pycache_filename.partition('.')[0]
402    return _path_join(head, base_filename + SOURCE_SUFFIXES[0])
403
404
405def _get_sourcefile(bytecode_path):
406    """Convert a bytecode file path to a source path (if possible).
407
408    This function exists purely for backwards-compatibility for
409    PyImport_ExecCodeModuleWithFilenames() in the C API.
410
411    """
412    if len(bytecode_path) == 0:
413        return None
414    rest, _, extension = bytecode_path.rpartition('.')
415    if not rest or extension.lower()[-3:-1] != 'py':
416        return bytecode_path
417    try:
418        source_path = source_from_cache(bytecode_path)
419    except (NotImplementedError, ValueError):
420        source_path = bytecode_path[:-1]
421    return source_path if _path_isfile(source_path) else bytecode_path
422
423
424def _get_cached(filename):
425    if filename.endswith(tuple(SOURCE_SUFFIXES)):
426        try:
427            return cache_from_source(filename)
428        except NotImplementedError:
429            pass
430    elif filename.endswith(tuple(BYTECODE_SUFFIXES)):
431        return filename
432    else:
433        return None
434
435
436def _calc_mode(path):
437    """Calculate the mode permissions for a bytecode file."""
438    try:
439        mode = _path_stat(path).st_mode
440    except OSError:
441        mode = 0o666
442    # We always ensure write access so we can update cached files
443    # later even when the source files are read-only on Windows (#6074)
444    mode |= 0o200
445    return mode
446
447
448def _check_name(method):
449    """Decorator to verify that the module being requested matches the one the
450    loader can handle.
451
452    The first argument (self) must define _name which the second argument is
453    compared against. If the comparison fails then ImportError is raised.
454
455    """
456    def _check_name_wrapper(self, name=None, *args, **kwargs):
457        if name is None:
458            name = self.name
459        elif self.name != name:
460            raise ImportError('loader for %s cannot handle %s' %
461                                (self.name, name), name=name)
462        return method(self, name, *args, **kwargs)
463    try:
464        _wrap = _bootstrap._wrap
465    except NameError:
466        # XXX yuck
467        def _wrap(new, old):
468            for replace in ['__module__', '__name__', '__qualname__', '__doc__']:
469                if hasattr(old, replace):
470                    setattr(new, replace, getattr(old, replace))
471            new.__dict__.update(old.__dict__)
472    _wrap(_check_name_wrapper, method)
473    return _check_name_wrapper
474
475
476def _find_module_shim(self, fullname):
477    """Try to find a loader for the specified module by delegating to
478    self.find_loader().
479
480    This method is deprecated in favor of finder.find_spec().
481
482    """
483    # Call find_loader(). If it returns a string (indicating this
484    # is a namespace package portion), generate a warning and
485    # return None.
486    loader, portions = self.find_loader(fullname)
487    if loader is None and len(portions):
488        msg = 'Not importing directory {}: missing __init__'
489        _warnings.warn(msg.format(portions[0]), ImportWarning)
490    return loader
491
492
493def _classify_pyc(data, name, exc_details):
494    """Perform basic validity checking of a pyc header and return the flags field,
495    which determines how the pyc should be further validated against the source.
496
497    *data* is the contents of the pyc file. (Only the first 16 bytes are
498    required, though.)
499
500    *name* is the name of the module being imported. It is used for logging.
501
502    *exc_details* is a dictionary passed to ImportError if it raised for
503    improved debugging.
504
505    ImportError is raised when the magic number is incorrect or when the flags
506    field is invalid. EOFError is raised when the data is found to be truncated.
507
508    """
509    magic = data[:4]
510    if magic != MAGIC_NUMBER:
511        message = f'bad magic number in {name!r}: {magic!r}'
512        _bootstrap._verbose_message('{}', message)
513        raise ImportError(message, **exc_details)
514    if len(data) < 16:
515        message = f'reached EOF while reading pyc header of {name!r}'
516        _bootstrap._verbose_message('{}', message)
517        raise EOFError(message)
518    flags = _unpack_uint32(data[4:8])
519    # Only the first two flags are defined.
520    if flags & ~0b11:
521        message = f'invalid flags {flags!r} in {name!r}'
522        raise ImportError(message, **exc_details)
523    return flags
524
525
526def _validate_timestamp_pyc(data, source_mtime, source_size, name,
527                            exc_details):
528    """Validate a pyc against the source last-modified time.
529
530    *data* is the contents of the pyc file. (Only the first 16 bytes are
531    required.)
532
533    *source_mtime* is the last modified timestamp of the source file.
534
535    *source_size* is None or the size of the source file in bytes.
536
537    *name* is the name of the module being imported. It is used for logging.
538
539    *exc_details* is a dictionary passed to ImportError if it raised for
540    improved debugging.
541
542    An ImportError is raised if the bytecode is stale.
543
544    """
545    if _unpack_uint32(data[8:12]) != (source_mtime & 0xFFFFFFFF):
546        message = f'bytecode is stale for {name!r}'
547        _bootstrap._verbose_message('{}', message)
548        raise ImportError(message, **exc_details)
549    if (source_size is not None and
550        _unpack_uint32(data[12:16]) != (source_size & 0xFFFFFFFF)):
551        raise ImportError(f'bytecode is stale for {name!r}', **exc_details)
552
553
554def _validate_hash_pyc(data, source_hash, name, exc_details):
555    """Validate a hash-based pyc by checking the real source hash against the one in
556    the pyc header.
557
558    *data* is the contents of the pyc file. (Only the first 16 bytes are
559    required.)
560
561    *source_hash* is the importlib.util.source_hash() of the source file.
562
563    *name* is the name of the module being imported. It is used for logging.
564
565    *exc_details* is a dictionary passed to ImportError if it raised for
566    improved debugging.
567
568    An ImportError is raised if the bytecode is stale.
569
570    """
571    if data[8:16] != source_hash:
572        raise ImportError(
573            f'hash in bytecode doesn\'t match hash of source {name!r}',
574            **exc_details,
575        )
576
577
578def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None):
579    """Compile bytecode as found in a pyc."""
580    code = marshal.loads(data)
581    if isinstance(code, _code_type):
582        _bootstrap._verbose_message('code object from {!r}', bytecode_path)
583        if source_path is not None:
584            _imp._fix_co_filename(code, source_path)
585        return code
586    else:
587        raise ImportError('Non-code object in {!r}'.format(bytecode_path),
588                          name=name, path=bytecode_path)
589
590
591def _code_to_timestamp_pyc(code, mtime=0, source_size=0):
592    "Produce the data for a timestamp-based pyc."
593    data = bytearray(MAGIC_NUMBER)
594    data.extend(_pack_uint32(0))
595    data.extend(_pack_uint32(mtime))
596    data.extend(_pack_uint32(source_size))
597    data.extend(marshal.dumps(code))
598    return data
599
600
601def _code_to_hash_pyc(code, source_hash, checked=True):
602    "Produce the data for a hash-based pyc."
603    data = bytearray(MAGIC_NUMBER)
604    flags = 0b1 | checked << 1
605    data.extend(_pack_uint32(flags))
606    assert len(source_hash) == 8
607    data.extend(source_hash)
608    data.extend(marshal.dumps(code))
609    return data
610
611
612def decode_source(source_bytes):
613    """Decode bytes representing source code and return the string.
614
615    Universal newline support is used in the decoding.
616    """
617    import tokenize  # To avoid bootstrap issues.
618    source_bytes_readline = _io.BytesIO(source_bytes).readline
619    encoding = tokenize.detect_encoding(source_bytes_readline)
620    newline_decoder = _io.IncrementalNewlineDecoder(None, True)
621    return newline_decoder.decode(source_bytes.decode(encoding[0]))
622
623
624# Module specifications #######################################################
625
626_POPULATE = object()
627
628
629def spec_from_file_location(name, location=None, *, loader=None,
630                            submodule_search_locations=_POPULATE):
631    """Return a module spec based on a file location.
632
633    To indicate that the module is a package, set
634    submodule_search_locations to a list of directory paths.  An
635    empty list is sufficient, though its not otherwise useful to the
636    import system.
637
638    The loader must take a spec as its only __init__() arg.
639
640    """
641    if location is None:
642        # The caller may simply want a partially populated location-
643        # oriented spec.  So we set the location to a bogus value and
644        # fill in as much as we can.
645        location = '<unknown>'
646        if hasattr(loader, 'get_filename'):
647            # ExecutionLoader
648            try:
649                location = loader.get_filename(name)
650            except ImportError:
651                pass
652    else:
653        location = _os.fspath(location)
654
655    # If the location is on the filesystem, but doesn't actually exist,
656    # we could return None here, indicating that the location is not
657    # valid.  However, we don't have a good way of testing since an
658    # indirect location (e.g. a zip file or URL) will look like a
659    # non-existent file relative to the filesystem.
660
661    spec = _bootstrap.ModuleSpec(name, loader, origin=location)
662    spec._set_fileattr = True
663
664    # Pick a loader if one wasn't provided.
665    if loader is None:
666        for loader_class, suffixes in _get_supported_file_loaders():
667            if location.endswith(tuple(suffixes)):
668                loader = loader_class(name, location)
669                spec.loader = loader
670                break
671        else:
672            return None
673
674    # Set submodule_search_paths appropriately.
675    if submodule_search_locations is _POPULATE:
676        # Check the loader.
677        if hasattr(loader, 'is_package'):
678            try:
679                is_package = loader.is_package(name)
680            except ImportError:
681                pass
682            else:
683                if is_package:
684                    spec.submodule_search_locations = []
685    else:
686        spec.submodule_search_locations = submodule_search_locations
687    if spec.submodule_search_locations == []:
688        if location:
689            dirname = _path_split(location)[0]
690            spec.submodule_search_locations.append(dirname)
691
692    return spec
693
694
695# Loaders #####################################################################
696
697class WindowsRegistryFinder:
698
699    """Meta path finder for modules declared in the Windows registry."""
700
701    REGISTRY_KEY = (
702        'Software\\Python\\PythonCore\\{sys_version}'
703        '\\Modules\\{fullname}')
704    REGISTRY_KEY_DEBUG = (
705        'Software\\Python\\PythonCore\\{sys_version}'
706        '\\Modules\\{fullname}\\Debug')
707    DEBUG_BUILD = False  # Changed in _setup()
708
709    @classmethod
710    def _open_registry(cls, key):
711        try:
712            return _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, key)
713        except OSError:
714            return _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key)
715
716    @classmethod
717    def _search_registry(cls, fullname):
718        if cls.DEBUG_BUILD:
719            registry_key = cls.REGISTRY_KEY_DEBUG
720        else:
721            registry_key = cls.REGISTRY_KEY
722        key = registry_key.format(fullname=fullname,
723                                  sys_version='%d.%d' % sys.version_info[:2])
724        try:
725            with cls._open_registry(key) as hkey:
726                filepath = _winreg.QueryValue(hkey, '')
727        except OSError:
728            return None
729        return filepath
730
731    @classmethod
732    def find_spec(cls, fullname, path=None, target=None):
733        filepath = cls._search_registry(fullname)
734        if filepath is None:
735            return None
736        try:
737            _path_stat(filepath)
738        except OSError:
739            return None
740        for loader, suffixes in _get_supported_file_loaders():
741            if filepath.endswith(tuple(suffixes)):
742                spec = _bootstrap.spec_from_loader(fullname,
743                                                   loader(fullname, filepath),
744                                                   origin=filepath)
745                return spec
746
747    @classmethod
748    def find_module(cls, fullname, path=None):
749        """Find module named in the registry.
750
751        This method is deprecated.  Use exec_module() instead.
752
753        """
754        spec = cls.find_spec(fullname, path)
755        if spec is not None:
756            return spec.loader
757        else:
758            return None
759
760
761class _LoaderBasics:
762
763    """Base class of common code needed by both SourceLoader and
764    SourcelessFileLoader."""
765
766    def is_package(self, fullname):
767        """Concrete implementation of InspectLoader.is_package by checking if
768        the path returned by get_filename has a filename of '__init__.py'."""
769        filename = _path_split(self.get_filename(fullname))[1]
770        filename_base = filename.rsplit('.', 1)[0]
771        tail_name = fullname.rpartition('.')[2]
772        return filename_base == '__init__' and tail_name != '__init__'
773
774    def create_module(self, spec):
775        """Use default semantics for module creation."""
776
777    def exec_module(self, module):
778        """Execute the module."""
779        code = self.get_code(module.__name__)
780        if code is None:
781            raise ImportError('cannot load module {!r} when get_code() '
782                              'returns None'.format(module.__name__))
783        _bootstrap._call_with_frames_removed(exec, code, module.__dict__)
784
785    def load_module(self, fullname):
786        """This module is deprecated."""
787        return _bootstrap._load_module_shim(self, fullname)
788
789
790class SourceLoader(_LoaderBasics):
791
792    def path_mtime(self, path):
793        """Optional method that returns the modification time (an int) for the
794        specified path (a str).
795
796        Raises OSError when the path cannot be handled.
797        """
798        raise OSError
799
800    def path_stats(self, path):
801        """Optional method returning a metadata dict for the specified
802        path (a str).
803
804        Possible keys:
805        - 'mtime' (mandatory) is the numeric timestamp of last source
806          code modification;
807        - 'size' (optional) is the size in bytes of the source code.
808
809        Implementing this method allows the loader to read bytecode files.
810        Raises OSError when the path cannot be handled.
811        """
812        return {'mtime': self.path_mtime(path)}
813
814    def _cache_bytecode(self, source_path, cache_path, data):
815        """Optional method which writes data (bytes) to a file path (a str).
816
817        Implementing this method allows for the writing of bytecode files.
818
819        The source path is needed in order to correctly transfer permissions
820        """
821        # For backwards compatibility, we delegate to set_data()
822        return self.set_data(cache_path, data)
823
824    def set_data(self, path, data):
825        """Optional method which writes data (bytes) to a file path (a str).
826
827        Implementing this method allows for the writing of bytecode files.
828        """
829
830
831    def get_source(self, fullname):
832        """Concrete implementation of InspectLoader.get_source."""
833        path = self.get_filename(fullname)
834        try:
835            source_bytes = self.get_data(path)
836        except OSError as exc:
837            raise ImportError('source not available through get_data()',
838                              name=fullname) from exc
839        return decode_source(source_bytes)
840
841    def source_to_code(self, data, path, *, _optimize=-1):
842        """Return the code object compiled from source.
843
844        The 'data' argument can be any object type that compile() supports.
845        """
846        return _bootstrap._call_with_frames_removed(compile, data, path, 'exec',
847                                        dont_inherit=True, optimize=_optimize)
848
849    def get_code(self, fullname):
850        """Concrete implementation of InspectLoader.get_code.
851
852        Reading of bytecode requires path_stats to be implemented. To write
853        bytecode, set_data must also be implemented.
854
855        """
856        source_path = self.get_filename(fullname)
857        source_mtime = None
858        source_bytes = None
859        source_hash = None
860        hash_based = False
861        check_source = True
862        try:
863            bytecode_path = cache_from_source(source_path)
864        except NotImplementedError:
865            bytecode_path = None
866        else:
867            try:
868                st = self.path_stats(source_path)
869            except OSError:
870                pass
871            else:
872                source_mtime = int(st['mtime'])
873                try:
874                    data = self.get_data(bytecode_path)
875                except OSError:
876                    pass
877                else:
878                    exc_details = {
879                        'name': fullname,
880                        'path': bytecode_path,
881                    }
882                    try:
883                        flags = _classify_pyc(data, fullname, exc_details)
884                        bytes_data = memoryview(data)[16:]
885                        hash_based = flags & 0b1 != 0
886                        if hash_based:
887                            check_source = flags & 0b10 != 0
888                            if (_imp.check_hash_based_pycs != 'never' and
889                                (check_source or
890                                 _imp.check_hash_based_pycs == 'always')):
891                                source_bytes = self.get_data(source_path)
892                                source_hash = _imp.source_hash(
893                                    _RAW_MAGIC_NUMBER,
894                                    source_bytes,
895                                )
896                                _validate_hash_pyc(data, source_hash, fullname,
897                                                   exc_details)
898                        else:
899                            _validate_timestamp_pyc(
900                                data,
901                                source_mtime,
902                                st['size'],
903                                fullname,
904                                exc_details,
905                            )
906                    except (ImportError, EOFError):
907                        pass
908                    else:
909                        _bootstrap._verbose_message('{} matches {}', bytecode_path,
910                                                    source_path)
911                        return _compile_bytecode(bytes_data, name=fullname,
912                                                 bytecode_path=bytecode_path,
913                                                 source_path=source_path)
914        if source_bytes is None:
915            source_bytes = self.get_data(source_path)
916        code_object = self.source_to_code(source_bytes, source_path)
917        _bootstrap._verbose_message('code object from {}', source_path)
918        if (not sys.dont_write_bytecode and bytecode_path is not None and
919                source_mtime is not None):
920            if hash_based:
921                if source_hash is None:
922                    source_hash = _imp.source_hash(source_bytes)
923                data = _code_to_hash_pyc(code_object, source_hash, check_source)
924            else:
925                data = _code_to_timestamp_pyc(code_object, source_mtime,
926                                              len(source_bytes))
927            try:
928                self._cache_bytecode(source_path, bytecode_path, data)
929            except NotImplementedError:
930                pass
931        return code_object
932
933
934class FileLoader:
935
936    """Base file loader class which implements the loader protocol methods that
937    require file system usage."""
938
939    def __init__(self, fullname, path):
940        """Cache the module name and the path to the file found by the
941        finder."""
942        self.name = fullname
943        self.path = path
944
945    def __eq__(self, other):
946        return (self.__class__ == other.__class__ and
947                self.__dict__ == other.__dict__)
948
949    def __hash__(self):
950        return hash(self.name) ^ hash(self.path)
951
952    @_check_name
953    def load_module(self, fullname):
954        """Load a module from a file.
955
956        This method is deprecated.  Use exec_module() instead.
957
958        """
959        # The only reason for this method is for the name check.
960        # Issue #14857: Avoid the zero-argument form of super so the implementation
961        # of that form can be updated without breaking the frozen module
962        return super(FileLoader, self).load_module(fullname)
963
964    @_check_name
965    def get_filename(self, fullname):
966        """Return the path to the source file as found by the finder."""
967        return self.path
968
969    def get_data(self, path):
970        """Return the data from path as raw bytes."""
971        if isinstance(self, (SourceLoader, ExtensionFileLoader)):
972            with _io.open_code(str(path)) as file:
973                return file.read()
974        else:
975            with _io.FileIO(path, 'r') as file:
976                return file.read()
977
978    # ResourceReader ABC API.
979
980    @_check_name
981    def get_resource_reader(self, module):
982        if self.is_package(module):
983            return self
984        return None
985
986    def open_resource(self, resource):
987        path = _path_join(_path_split(self.path)[0], resource)
988        return _io.FileIO(path, 'r')
989
990    def resource_path(self, resource):
991        if not self.is_resource(resource):
992            raise FileNotFoundError
993        path = _path_join(_path_split(self.path)[0], resource)
994        return path
995
996    def is_resource(self, name):
997        if path_sep in name:
998            return False
999        path = _path_join(_path_split(self.path)[0], name)
1000        return _path_isfile(path)
1001
1002    def contents(self):
1003        return iter(_os.listdir(_path_split(self.path)[0]))
1004
1005
1006class SourceFileLoader(FileLoader, SourceLoader):
1007
1008    """Concrete implementation of SourceLoader using the file system."""
1009
1010    def path_stats(self, path):
1011        """Return the metadata for the path."""
1012        st = _path_stat(path)
1013        return {'mtime': st.st_mtime, 'size': st.st_size}
1014
1015    def _cache_bytecode(self, source_path, bytecode_path, data):
1016        # Adapt between the two APIs
1017        mode = _calc_mode(source_path)
1018        return self.set_data(bytecode_path, data, _mode=mode)
1019
1020    def set_data(self, path, data, *, _mode=0o666):
1021        """Write bytes data to a file."""
1022        parent, filename = _path_split(path)
1023        path_parts = []
1024        # Figure out what directories are missing.
1025        while parent and not _path_isdir(parent):
1026            parent, part = _path_split(parent)
1027            path_parts.append(part)
1028        # Create needed directories.
1029        for part in reversed(path_parts):
1030            parent = _path_join(parent, part)
1031            try:
1032                _os.mkdir(parent)
1033            except FileExistsError:
1034                # Probably another Python process already created the dir.
1035                continue
1036            except OSError as exc:
1037                # Could be a permission error, read-only filesystem: just forget
1038                # about writing the data.
1039                _bootstrap._verbose_message('could not create {!r}: {!r}',
1040                                            parent, exc)
1041                return
1042        try:
1043            _write_atomic(path, data, _mode)
1044            _bootstrap._verbose_message('created {!r}', path)
1045        except OSError as exc:
1046            # Same as above: just don't write the bytecode.
1047            _bootstrap._verbose_message('could not create {!r}: {!r}', path,
1048                                        exc)
1049
1050
1051class SourcelessFileLoader(FileLoader, _LoaderBasics):
1052
1053    """Loader which handles sourceless file imports."""
1054
1055    def get_code(self, fullname):
1056        path = self.get_filename(fullname)
1057        data = self.get_data(path)
1058        # Call _classify_pyc to do basic validation of the pyc but ignore the
1059        # result. There's no source to check against.
1060        exc_details = {
1061            'name': fullname,
1062            'path': path,
1063        }
1064        _classify_pyc(data, fullname, exc_details)
1065        return _compile_bytecode(
1066            memoryview(data)[16:],
1067            name=fullname,
1068            bytecode_path=path,
1069        )
1070
1071    def get_source(self, fullname):
1072        """Return None as there is no source code."""
1073        return None
1074
1075
1076# Filled in by _setup().
1077EXTENSION_SUFFIXES = []
1078
1079
1080class ExtensionFileLoader(FileLoader, _LoaderBasics):
1081
1082    """Loader for extension modules.
1083
1084    The constructor is designed to work with FileFinder.
1085
1086    """
1087
1088    def __init__(self, name, path):
1089        self.name = name
1090        self.path = path
1091
1092    def __eq__(self, other):
1093        return (self.__class__ == other.__class__ and
1094                self.__dict__ == other.__dict__)
1095
1096    def __hash__(self):
1097        return hash(self.name) ^ hash(self.path)
1098
1099    def create_module(self, spec):
1100        """Create an unitialized extension module"""
1101        module = _bootstrap._call_with_frames_removed(
1102            _imp.create_dynamic, spec)
1103        _bootstrap._verbose_message('extension module {!r} loaded from {!r}',
1104                         spec.name, self.path)
1105        return module
1106
1107    def exec_module(self, module):
1108        """Initialize an extension module"""
1109        _bootstrap._call_with_frames_removed(_imp.exec_dynamic, module)
1110        _bootstrap._verbose_message('extension module {!r} executed from {!r}',
1111                         self.name, self.path)
1112
1113    def is_package(self, fullname):
1114        """Return True if the extension module is a package."""
1115        file_name = _path_split(self.path)[1]
1116        return any(file_name == '__init__' + suffix
1117                   for suffix in EXTENSION_SUFFIXES)
1118
1119    def get_code(self, fullname):
1120        """Return None as an extension module cannot create a code object."""
1121        return None
1122
1123    def get_source(self, fullname):
1124        """Return None as extension modules have no source code."""
1125        return None
1126
1127    @_check_name
1128    def get_filename(self, fullname):
1129        """Return the path to the source file as found by the finder."""
1130        return self.path
1131
1132
1133class _NamespacePath:
1134    """Represents a namespace package's path.  It uses the module name
1135    to find its parent module, and from there it looks up the parent's
1136    __path__.  When this changes, the module's own path is recomputed,
1137    using path_finder.  For top-level modules, the parent module's path
1138    is sys.path."""
1139
1140    def __init__(self, name, path, path_finder):
1141        self._name = name
1142        self._path = path
1143        self._last_parent_path = tuple(self._get_parent_path())
1144        self._path_finder = path_finder
1145
1146    def _find_parent_path_names(self):
1147        """Returns a tuple of (parent-module-name, parent-path-attr-name)"""
1148        parent, dot, me = self._name.rpartition('.')
1149        if dot == '':
1150            # This is a top-level module. sys.path contains the parent path.
1151            return 'sys', 'path'
1152        # Not a top-level module. parent-module.__path__ contains the
1153        #  parent path.
1154        return parent, '__path__'
1155
1156    def _get_parent_path(self):
1157        parent_module_name, path_attr_name = self._find_parent_path_names()
1158        return getattr(sys.modules[parent_module_name], path_attr_name)
1159
1160    def _recalculate(self):
1161        # If the parent's path has changed, recalculate _path
1162        parent_path = tuple(self._get_parent_path()) # Make a copy
1163        if parent_path != self._last_parent_path:
1164            spec = self._path_finder(self._name, parent_path)
1165            # Note that no changes are made if a loader is returned, but we
1166            #  do remember the new parent path
1167            if spec is not None and spec.loader is None:
1168                if spec.submodule_search_locations:
1169                    self._path = spec.submodule_search_locations
1170            self._last_parent_path = parent_path     # Save the copy
1171        return self._path
1172
1173    def __iter__(self):
1174        return iter(self._recalculate())
1175
1176    def __getitem__(self, index):
1177        return self._recalculate()[index]
1178
1179    def __setitem__(self, index, path):
1180        self._path[index] = path
1181
1182    def __len__(self):
1183        return len(self._recalculate())
1184
1185    def __repr__(self):
1186        return '_NamespacePath({!r})'.format(self._path)
1187
1188    def __contains__(self, item):
1189        return item in self._recalculate()
1190
1191    def append(self, item):
1192        self._path.append(item)
1193
1194
1195# We use this exclusively in module_from_spec() for backward-compatibility.
1196class _NamespaceLoader:
1197    def __init__(self, name, path, path_finder):
1198        self._path = _NamespacePath(name, path, path_finder)
1199
1200    @classmethod
1201    def module_repr(cls, module):
1202        """Return repr for the module.
1203
1204        The method is deprecated.  The import machinery does the job itself.
1205
1206        """
1207        return '<module {!r} (namespace)>'.format(module.__name__)
1208
1209    def is_package(self, fullname):
1210        return True
1211
1212    def get_source(self, fullname):
1213        return ''
1214
1215    def get_code(self, fullname):
1216        return compile('', '<string>', 'exec', dont_inherit=True)
1217
1218    def create_module(self, spec):
1219        """Use default semantics for module creation."""
1220
1221    def exec_module(self, module):
1222        pass
1223
1224    def load_module(self, fullname):
1225        """Load a namespace module.
1226
1227        This method is deprecated.  Use exec_module() instead.
1228
1229        """
1230        # The import system never calls this method.
1231        _bootstrap._verbose_message('namespace module loaded with path {!r}',
1232                                    self._path)
1233        return _bootstrap._load_module_shim(self, fullname)
1234
1235
1236# Finders #####################################################################
1237
1238class PathFinder:
1239
1240    """Meta path finder for sys.path and package __path__ attributes."""
1241
1242    @classmethod
1243    def invalidate_caches(cls):
1244        """Call the invalidate_caches() method on all path entry finders
1245        stored in sys.path_importer_caches (where implemented)."""
1246        for name, finder in list(sys.path_importer_cache.items()):
1247            if finder is None:
1248                del sys.path_importer_cache[name]
1249            elif hasattr(finder, 'invalidate_caches'):
1250                finder.invalidate_caches()
1251
1252    @classmethod
1253    def _path_hooks(cls, path):
1254        """Search sys.path_hooks for a finder for 'path'."""
1255        if sys.path_hooks is not None and not sys.path_hooks:
1256            _warnings.warn('sys.path_hooks is empty', ImportWarning)
1257        for hook in sys.path_hooks:
1258            try:
1259                return hook(path)
1260            except ImportError:
1261                continue
1262        else:
1263            return None
1264
1265    @classmethod
1266    def _path_importer_cache(cls, path):
1267        """Get the finder for the path entry from sys.path_importer_cache.
1268
1269        If the path entry is not in the cache, find the appropriate finder
1270        and cache it. If no finder is available, store None.
1271
1272        """
1273        if path == '':
1274            try:
1275                path = _os.getcwd()
1276            except FileNotFoundError:
1277                # Don't cache the failure as the cwd can easily change to
1278                # a valid directory later on.
1279                return None
1280        try:
1281            finder = sys.path_importer_cache[path]
1282        except KeyError:
1283            finder = cls._path_hooks(path)
1284            sys.path_importer_cache[path] = finder
1285        return finder
1286
1287    @classmethod
1288    def _legacy_get_spec(cls, fullname, finder):
1289        # This would be a good place for a DeprecationWarning if
1290        # we ended up going that route.
1291        if hasattr(finder, 'find_loader'):
1292            loader, portions = finder.find_loader(fullname)
1293        else:
1294            loader = finder.find_module(fullname)
1295            portions = []
1296        if loader is not None:
1297            return _bootstrap.spec_from_loader(fullname, loader)
1298        spec = _bootstrap.ModuleSpec(fullname, None)
1299        spec.submodule_search_locations = portions
1300        return spec
1301
1302    @classmethod
1303    def _get_spec(cls, fullname, path, target=None):
1304        """Find the loader or namespace_path for this module/package name."""
1305        # If this ends up being a namespace package, namespace_path is
1306        #  the list of paths that will become its __path__
1307        namespace_path = []
1308        for entry in path:
1309            if not isinstance(entry, (str, bytes)):
1310                continue
1311            finder = cls._path_importer_cache(entry)
1312            if finder is not None:
1313                if hasattr(finder, 'find_spec'):
1314                    spec = finder.find_spec(fullname, target)
1315                else:
1316                    spec = cls._legacy_get_spec(fullname, finder)
1317                if spec is None:
1318                    continue
1319                if spec.loader is not None:
1320                    return spec
1321                portions = spec.submodule_search_locations
1322                if portions is None:
1323                    raise ImportError('spec missing loader')
1324                # This is possibly part of a namespace package.
1325                #  Remember these path entries (if any) for when we
1326                #  create a namespace package, and continue iterating
1327                #  on path.
1328                namespace_path.extend(portions)
1329        else:
1330            spec = _bootstrap.ModuleSpec(fullname, None)
1331            spec.submodule_search_locations = namespace_path
1332            return spec
1333
1334    @classmethod
1335    def find_spec(cls, fullname, path=None, target=None):
1336        """Try to find a spec for 'fullname' on sys.path or 'path'.
1337
1338        The search is based on sys.path_hooks and sys.path_importer_cache.
1339        """
1340        if path is None:
1341            path = sys.path
1342        spec = cls._get_spec(fullname, path, target)
1343        if spec is None:
1344            return None
1345        elif spec.loader is None:
1346            namespace_path = spec.submodule_search_locations
1347            if namespace_path:
1348                # We found at least one namespace path.  Return a spec which
1349                # can create the namespace package.
1350                spec.origin = None
1351                spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec)
1352                return spec
1353            else:
1354                return None
1355        else:
1356            return spec
1357
1358    @classmethod
1359    def find_module(cls, fullname, path=None):
1360        """find the module on sys.path or 'path' based on sys.path_hooks and
1361        sys.path_importer_cache.
1362
1363        This method is deprecated.  Use find_spec() instead.
1364
1365        """
1366        spec = cls.find_spec(fullname, path)
1367        if spec is None:
1368            return None
1369        return spec.loader
1370
1371    @classmethod
1372    def find_distributions(cls, *args, **kwargs):
1373        """
1374        Find distributions.
1375
1376        Return an iterable of all Distribution instances capable of
1377        loading the metadata for packages matching ``context.name``
1378        (or all names if ``None`` indicated) along the paths in the list
1379        of directories ``context.path``.
1380        """
1381        from importlib.metadata import MetadataPathFinder
1382        return MetadataPathFinder.find_distributions(*args, **kwargs)
1383
1384
1385class FileFinder:
1386
1387    """File-based finder.
1388
1389    Interactions with the file system are cached for performance, being
1390    refreshed when the directory the finder is handling has been modified.
1391
1392    """
1393
1394    def __init__(self, path, *loader_details):
1395        """Initialize with the path to search on and a variable number of
1396        2-tuples containing the loader and the file suffixes the loader
1397        recognizes."""
1398        loaders = []
1399        for loader, suffixes in loader_details:
1400            loaders.extend((suffix, loader) for suffix in suffixes)
1401        self._loaders = loaders
1402        # Base (directory) path
1403        self.path = path or '.'
1404        self._path_mtime = -1
1405        self._path_cache = set()
1406        self._relaxed_path_cache = set()
1407
1408    def invalidate_caches(self):
1409        """Invalidate the directory mtime."""
1410        self._path_mtime = -1
1411
1412    find_module = _find_module_shim
1413
1414    def find_loader(self, fullname):
1415        """Try to find a loader for the specified module, or the namespace
1416        package portions. Returns (loader, list-of-portions).
1417
1418        This method is deprecated.  Use find_spec() instead.
1419
1420        """
1421        spec = self.find_spec(fullname)
1422        if spec is None:
1423            return None, []
1424        return spec.loader, spec.submodule_search_locations or []
1425
1426    def _get_spec(self, loader_class, fullname, path, smsl, target):
1427        loader = loader_class(fullname, path)
1428        return spec_from_file_location(fullname, path, loader=loader,
1429                                       submodule_search_locations=smsl)
1430
1431    def find_spec(self, fullname, target=None):
1432        """Try to find a spec for the specified module.
1433
1434        Returns the matching spec, or None if not found.
1435        """
1436        is_namespace = False
1437        tail_module = fullname.rpartition('.')[2]
1438        try:
1439            mtime = _path_stat(self.path or _os.getcwd()).st_mtime
1440        except OSError:
1441            mtime = -1
1442        if mtime != self._path_mtime:
1443            self._fill_cache()
1444            self._path_mtime = mtime
1445        # tail_module keeps the original casing, for __file__ and friends
1446        if _relax_case():
1447            cache = self._relaxed_path_cache
1448            cache_module = tail_module.lower()
1449        else:
1450            cache = self._path_cache
1451            cache_module = tail_module
1452        # Check if the module is the name of a directory (and thus a package).
1453        if cache_module in cache:
1454            base_path = _path_join(self.path, tail_module)
1455            for suffix, loader_class in self._loaders:
1456                init_filename = '__init__' + suffix
1457                full_path = _path_join(base_path, init_filename)
1458                if _path_isfile(full_path):
1459                    return self._get_spec(loader_class, fullname, full_path, [base_path], target)
1460            else:
1461                # If a namespace package, return the path if we don't
1462                #  find a module in the next section.
1463                is_namespace = _path_isdir(base_path)
1464        # Check for a file w/ a proper suffix exists.
1465        for suffix, loader_class in self._loaders:
1466            full_path = _path_join(self.path, tail_module + suffix)
1467            _bootstrap._verbose_message('trying {}', full_path, verbosity=2)
1468            if cache_module + suffix in cache:
1469                if _path_isfile(full_path):
1470                    return self._get_spec(loader_class, fullname, full_path,
1471                                          None, target)
1472        if is_namespace:
1473            _bootstrap._verbose_message('possible namespace for {}', base_path)
1474            spec = _bootstrap.ModuleSpec(fullname, None)
1475            spec.submodule_search_locations = [base_path]
1476            return spec
1477        return None
1478
1479    def _fill_cache(self):
1480        """Fill the cache of potential modules and packages for this directory."""
1481        path = self.path
1482        try:
1483            contents = _os.listdir(path or _os.getcwd())
1484        except (FileNotFoundError, PermissionError, NotADirectoryError):
1485            # Directory has either been removed, turned into a file, or made
1486            # unreadable.
1487            contents = []
1488        # We store two cached versions, to handle runtime changes of the
1489        # PYTHONCASEOK environment variable.
1490        if not sys.platform.startswith('win'):
1491            self._path_cache = set(contents)
1492        else:
1493            # Windows users can import modules with case-insensitive file
1494            # suffixes (for legacy reasons). Make the suffix lowercase here
1495            # so it's done once instead of for every import. This is safe as
1496            # the specified suffixes to check against are always specified in a
1497            # case-sensitive manner.
1498            lower_suffix_contents = set()
1499            for item in contents:
1500                name, dot, suffix = item.partition('.')
1501                if dot:
1502                    new_name = '{}.{}'.format(name, suffix.lower())
1503                else:
1504                    new_name = name
1505                lower_suffix_contents.add(new_name)
1506            self._path_cache = lower_suffix_contents
1507        if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS):
1508            self._relaxed_path_cache = {fn.lower() for fn in contents}
1509
1510    @classmethod
1511    def path_hook(cls, *loader_details):
1512        """A class method which returns a closure to use on sys.path_hook
1513        which will return an instance using the specified loaders and the path
1514        called on the closure.
1515
1516        If the path called on the closure is not a directory, ImportError is
1517        raised.
1518
1519        """
1520        def path_hook_for_FileFinder(path):
1521            """Path hook for importlib.machinery.FileFinder."""
1522            if not _path_isdir(path):
1523                raise ImportError('only directories are supported', path=path)
1524            return cls(path, *loader_details)
1525
1526        return path_hook_for_FileFinder
1527
1528    def __repr__(self):
1529        return 'FileFinder({!r})'.format(self.path)
1530
1531
1532# Import setup ###############################################################
1533
1534def _fix_up_module(ns, name, pathname, cpathname=None):
1535    # This function is used by PyImport_ExecCodeModuleObject().
1536    loader = ns.get('__loader__')
1537    spec = ns.get('__spec__')
1538    if not loader:
1539        if spec:
1540            loader = spec.loader
1541        elif pathname == cpathname:
1542            loader = SourcelessFileLoader(name, pathname)
1543        else:
1544            loader = SourceFileLoader(name, pathname)
1545    if not spec:
1546        spec = spec_from_file_location(name, pathname, loader=loader)
1547    try:
1548        ns['__spec__'] = spec
1549        ns['__loader__'] = loader
1550        ns['__file__'] = pathname
1551        ns['__cached__'] = cpathname
1552    except Exception:
1553        # Not important enough to report.
1554        pass
1555
1556
1557def _get_supported_file_loaders():
1558    """Returns a list of file-based module loaders.
1559
1560    Each item is a tuple (loader, suffixes).
1561    """
1562    extensions = ExtensionFileLoader, _imp.extension_suffixes()
1563    source = SourceFileLoader, SOURCE_SUFFIXES
1564    bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
1565    return [extensions, source, bytecode]
1566
1567
1568def _setup(_bootstrap_module):
1569    """Setup the path-based importers for importlib by importing needed
1570    built-in modules and injecting them into the global namespace.
1571
1572    Other components are extracted from the core bootstrap module.
1573
1574    """
1575    global sys, _imp, _bootstrap
1576    _bootstrap = _bootstrap_module
1577    sys = _bootstrap.sys
1578    _imp = _bootstrap._imp
1579
1580    # Directly load built-in modules needed during bootstrap.
1581    self_module = sys.modules[__name__]
1582    for builtin_name in ('_io', '_warnings', 'builtins', 'marshal'):
1583        if builtin_name not in sys.modules:
1584            builtin_module = _bootstrap._builtin_from_name(builtin_name)
1585        else:
1586            builtin_module = sys.modules[builtin_name]
1587        setattr(self_module, builtin_name, builtin_module)
1588
1589    # Directly load the os module (needed during bootstrap).
1590    os_details = ('posix', ['/']), ('nt', ['\\', '/'])
1591    for builtin_os, path_separators in os_details:
1592        # Assumption made in _path_join()
1593        assert all(len(sep) == 1 for sep in path_separators)
1594        path_sep = path_separators[0]
1595        if builtin_os in sys.modules:
1596            os_module = sys.modules[builtin_os]
1597            break
1598        else:
1599            try:
1600                os_module = _bootstrap._builtin_from_name(builtin_os)
1601                break
1602            except ImportError:
1603                continue
1604    else:
1605        raise ImportError('importlib requires posix or nt')
1606    setattr(self_module, '_os', os_module)
1607    setattr(self_module, 'path_sep', path_sep)
1608    setattr(self_module, 'path_separators', ''.join(path_separators))
1609    setattr(self_module, '_pathseps_with_colon', {f':{s}' for s in path_separators})
1610
1611    # Directly load the _thread module (needed during bootstrap).
1612    thread_module = _bootstrap._builtin_from_name('_thread')
1613    setattr(self_module, '_thread', thread_module)
1614
1615    # Directly load the _weakref module (needed during bootstrap).
1616    weakref_module = _bootstrap._builtin_from_name('_weakref')
1617    setattr(self_module, '_weakref', weakref_module)
1618
1619    # Directly load the winreg module (needed during bootstrap).
1620    if builtin_os == 'nt':
1621        winreg_module = _bootstrap._builtin_from_name('winreg')
1622        setattr(self_module, '_winreg', winreg_module)
1623
1624    # Constants
1625    setattr(self_module, '_relax_case', _make_relax_case())
1626    EXTENSION_SUFFIXES.extend(_imp.extension_suffixes())
1627    if builtin_os == 'nt':
1628        SOURCE_SUFFIXES.append('.pyw')
1629        if '_d.pyd' in EXTENSION_SUFFIXES:
1630            WindowsRegistryFinder.DEBUG_BUILD = True
1631
1632
1633def _install(_bootstrap_module):
1634    """Install the path-based import components."""
1635    _setup(_bootstrap_module)
1636    supported_loaders = _get_supported_file_loaders()
1637    sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
1638    sys.meta_path.append(PathFinder)
1639