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 and ignore environment flags are not set."""
38            return not sys.flags.ignore_environment and 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#     Python 3.9a0  3420 (add LOAD_ASSERTION_ERROR #34880)
275#     Python 3.9a0  3421 (simplified bytecode for with blocks #32949)
276#     Python 3.9a0  3422 (remove BEGIN_FINALLY, END_FINALLY, CALL_FINALLY, POP_FINALLY bytecodes #33387)
277#     Python 3.9a2  3423 (add IS_OP, CONTAINS_OP and JUMP_IF_NOT_EXC_MATCH bytecodes #39156)
278#     Python 3.9a2  3424 (simplify bytecodes for *value unpacking)
279#     Python 3.9a2  3425 (simplify bytecodes for **value unpacking)
280
281#
282# MAGIC must change whenever the bytecode emitted by the compiler may no
283# longer be understood by older implementations of the eval loop (usually
284# due to the addition of new opcodes).
285#
286# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
287# in PC/launcher.c must also be updated.
288
289MAGIC_NUMBER = (3425).to_bytes(2, 'little') + b'\r\n'
290_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
291
292_PYCACHE = '__pycache__'
293_OPT = 'opt-'
294
295SOURCE_SUFFIXES = ['.py']  # _setup() adds .pyw as needed.
296
297BYTECODE_SUFFIXES = ['.pyc']
298# Deprecated.
299DEBUG_BYTECODE_SUFFIXES = OPTIMIZED_BYTECODE_SUFFIXES = BYTECODE_SUFFIXES
300
301def cache_from_source(path, debug_override=None, *, optimization=None):
302    """Given the path to a .py file, return the path to its .pyc file.
303
304    The .py file does not need to exist; this simply returns the path to the
305    .pyc file calculated as if the .py file were imported.
306
307    The 'optimization' parameter controls the presumed optimization level of
308    the bytecode file. If 'optimization' is not None, the string representation
309    of the argument is taken and verified to be alphanumeric (else ValueError
310    is raised).
311
312    The debug_override parameter is deprecated. If debug_override is not None,
313    a True value is the same as setting 'optimization' to the empty string
314    while a False value is equivalent to setting 'optimization' to '1'.
315
316    If sys.implementation.cache_tag is None then NotImplementedError is raised.
317
318    """
319    if debug_override is not None:
320        _warnings.warn('the debug_override parameter is deprecated; use '
321                       "'optimization' instead", DeprecationWarning)
322        if optimization is not None:
323            message = 'debug_override or optimization must be set to None'
324            raise TypeError(message)
325        optimization = '' if debug_override else 1
326    path = _os.fspath(path)
327    head, tail = _path_split(path)
328    base, sep, rest = tail.rpartition('.')
329    tag = sys.implementation.cache_tag
330    if tag is None:
331        raise NotImplementedError('sys.implementation.cache_tag is None')
332    almost_filename = ''.join([(base if base else rest), sep, tag])
333    if optimization is None:
334        if sys.flags.optimize == 0:
335            optimization = ''
336        else:
337            optimization = sys.flags.optimize
338    optimization = str(optimization)
339    if optimization != '':
340        if not optimization.isalnum():
341            raise ValueError('{!r} is not alphanumeric'.format(optimization))
342        almost_filename = '{}.{}{}'.format(almost_filename, _OPT, optimization)
343    filename = almost_filename + BYTECODE_SUFFIXES[0]
344    if sys.pycache_prefix is not None:
345        # We need an absolute path to the py file to avoid the possibility of
346        # collisions within sys.pycache_prefix, if someone has two different
347        # `foo/bar.py` on their system and they import both of them using the
348        # same sys.pycache_prefix. Let's say sys.pycache_prefix is
349        # `C:\Bytecode`; the idea here is that if we get `Foo\Bar`, we first
350        # make it absolute (`C:\Somewhere\Foo\Bar`), then make it root-relative
351        # (`Somewhere\Foo\Bar`), so we end up placing the bytecode file in an
352        # unambiguous `C:\Bytecode\Somewhere\Foo\Bar\`.
353        if not _path_isabs(head):
354            head = _path_join(_os.getcwd(), head)
355
356        # Strip initial drive from a Windows path. We know we have an absolute
357        # path here, so the second part of the check rules out a POSIX path that
358        # happens to contain a colon at the second character.
359        if head[1] == ':' and head[0] not in path_separators:
360            head = head[2:]
361
362        # Strip initial path separator from `head` to complete the conversion
363        # back to a root-relative path before joining.
364        return _path_join(
365            sys.pycache_prefix,
366            head.lstrip(path_separators),
367            filename,
368        )
369    return _path_join(head, _PYCACHE, filename)
370
371
372def source_from_cache(path):
373    """Given the path to a .pyc. file, return the path to its .py file.
374
375    The .pyc file does not need to exist; this simply returns the path to
376    the .py file calculated to correspond to the .pyc file.  If path does
377    not conform to PEP 3147/488 format, ValueError will be raised. If
378    sys.implementation.cache_tag is None then NotImplementedError is raised.
379
380    """
381    if sys.implementation.cache_tag is None:
382        raise NotImplementedError('sys.implementation.cache_tag is None')
383    path = _os.fspath(path)
384    head, pycache_filename = _path_split(path)
385    found_in_pycache_prefix = False
386    if sys.pycache_prefix is not None:
387        stripped_path = sys.pycache_prefix.rstrip(path_separators)
388        if head.startswith(stripped_path + path_sep):
389            head = head[len(stripped_path):]
390            found_in_pycache_prefix = True
391    if not found_in_pycache_prefix:
392        head, pycache = _path_split(head)
393        if pycache != _PYCACHE:
394            raise ValueError(f'{_PYCACHE} not bottom-level directory in '
395                             f'{path!r}')
396    dot_count = pycache_filename.count('.')
397    if dot_count not in {2, 3}:
398        raise ValueError(f'expected only 2 or 3 dots in {pycache_filename!r}')
399    elif dot_count == 3:
400        optimization = pycache_filename.rsplit('.', 2)[-2]
401        if not optimization.startswith(_OPT):
402            raise ValueError("optimization portion of filename does not start "
403                             f"with {_OPT!r}")
404        opt_level = optimization[len(_OPT):]
405        if not opt_level.isalnum():
406            raise ValueError(f"optimization level {optimization!r} is not an "
407                             "alphanumeric value")
408    base_filename = pycache_filename.partition('.')[0]
409    return _path_join(head, base_filename + SOURCE_SUFFIXES[0])
410
411
412def _get_sourcefile(bytecode_path):
413    """Convert a bytecode file path to a source path (if possible).
414
415    This function exists purely for backwards-compatibility for
416    PyImport_ExecCodeModuleWithFilenames() in the C API.
417
418    """
419    if len(bytecode_path) == 0:
420        return None
421    rest, _, extension = bytecode_path.rpartition('.')
422    if not rest or extension.lower()[-3:-1] != 'py':
423        return bytecode_path
424    try:
425        source_path = source_from_cache(bytecode_path)
426    except (NotImplementedError, ValueError):
427        source_path = bytecode_path[:-1]
428    return source_path if _path_isfile(source_path) else bytecode_path
429
430
431def _get_cached(filename):
432    if filename.endswith(tuple(SOURCE_SUFFIXES)):
433        try:
434            return cache_from_source(filename)
435        except NotImplementedError:
436            pass
437    elif filename.endswith(tuple(BYTECODE_SUFFIXES)):
438        return filename
439    else:
440        return None
441
442
443def _calc_mode(path):
444    """Calculate the mode permissions for a bytecode file."""
445    try:
446        mode = _path_stat(path).st_mode
447    except OSError:
448        mode = 0o666
449    # We always ensure write access so we can update cached files
450    # later even when the source files are read-only on Windows (#6074)
451    mode |= 0o200
452    return mode
453
454
455def _check_name(method):
456    """Decorator to verify that the module being requested matches the one the
457    loader can handle.
458
459    The first argument (self) must define _name which the second argument is
460    compared against. If the comparison fails then ImportError is raised.
461
462    """
463    def _check_name_wrapper(self, name=None, *args, **kwargs):
464        if name is None:
465            name = self.name
466        elif self.name != name:
467            raise ImportError('loader for %s cannot handle %s' %
468                                (self.name, name), name=name)
469        return method(self, name, *args, **kwargs)
470    try:
471        _wrap = _bootstrap._wrap
472    except NameError:
473        # XXX yuck
474        def _wrap(new, old):
475            for replace in ['__module__', '__name__', '__qualname__', '__doc__']:
476                if hasattr(old, replace):
477                    setattr(new, replace, getattr(old, replace))
478            new.__dict__.update(old.__dict__)
479    _wrap(_check_name_wrapper, method)
480    return _check_name_wrapper
481
482
483def _find_module_shim(self, fullname):
484    """Try to find a loader for the specified module by delegating to
485    self.find_loader().
486
487    This method is deprecated in favor of finder.find_spec().
488
489    """
490    # Call find_loader(). If it returns a string (indicating this
491    # is a namespace package portion), generate a warning and
492    # return None.
493    loader, portions = self.find_loader(fullname)
494    if loader is None and len(portions):
495        msg = 'Not importing directory {}: missing __init__'
496        _warnings.warn(msg.format(portions[0]), ImportWarning)
497    return loader
498
499
500def _classify_pyc(data, name, exc_details):
501    """Perform basic validity checking of a pyc header and return the flags field,
502    which determines how the pyc should be further validated against the source.
503
504    *data* is the contents of the pyc file. (Only the first 16 bytes are
505    required, though.)
506
507    *name* is the name of the module being imported. It is used for logging.
508
509    *exc_details* is a dictionary passed to ImportError if it raised for
510    improved debugging.
511
512    ImportError is raised when the magic number is incorrect or when the flags
513    field is invalid. EOFError is raised when the data is found to be truncated.
514
515    """
516    magic = data[:4]
517    if magic != MAGIC_NUMBER:
518        message = f'bad magic number in {name!r}: {magic!r}'
519        _bootstrap._verbose_message('{}', message)
520        raise ImportError(message, **exc_details)
521    if len(data) < 16:
522        message = f'reached EOF while reading pyc header of {name!r}'
523        _bootstrap._verbose_message('{}', message)
524        raise EOFError(message)
525    flags = _unpack_uint32(data[4:8])
526    # Only the first two flags are defined.
527    if flags & ~0b11:
528        message = f'invalid flags {flags!r} in {name!r}'
529        raise ImportError(message, **exc_details)
530    return flags
531
532
533def _validate_timestamp_pyc(data, source_mtime, source_size, name,
534                            exc_details):
535    """Validate a pyc against the source last-modified time.
536
537    *data* is the contents of the pyc file. (Only the first 16 bytes are
538    required.)
539
540    *source_mtime* is the last modified timestamp of the source file.
541
542    *source_size* is None or the size of the source file in bytes.
543
544    *name* is the name of the module being imported. It is used for logging.
545
546    *exc_details* is a dictionary passed to ImportError if it raised for
547    improved debugging.
548
549    An ImportError is raised if the bytecode is stale.
550
551    """
552    if _unpack_uint32(data[8:12]) != (source_mtime & 0xFFFFFFFF):
553        message = f'bytecode is stale for {name!r}'
554        _bootstrap._verbose_message('{}', message)
555        raise ImportError(message, **exc_details)
556    if (source_size is not None and
557        _unpack_uint32(data[12:16]) != (source_size & 0xFFFFFFFF)):
558        raise ImportError(f'bytecode is stale for {name!r}', **exc_details)
559
560
561def _validate_hash_pyc(data, source_hash, name, exc_details):
562    """Validate a hash-based pyc by checking the real source hash against the one in
563    the pyc header.
564
565    *data* is the contents of the pyc file. (Only the first 16 bytes are
566    required.)
567
568    *source_hash* is the importlib.util.source_hash() of the source file.
569
570    *name* is the name of the module being imported. It is used for logging.
571
572    *exc_details* is a dictionary passed to ImportError if it raised for
573    improved debugging.
574
575    An ImportError is raised if the bytecode is stale.
576
577    """
578    if data[8:16] != source_hash:
579        raise ImportError(
580            f'hash in bytecode doesn\'t match hash of source {name!r}',
581            **exc_details,
582        )
583
584
585def _compile_bytecode(data, name=None, bytecode_path=None, source_path=None):
586    """Compile bytecode as found in a pyc."""
587    code = marshal.loads(data)
588    if isinstance(code, _code_type):
589        _bootstrap._verbose_message('code object from {!r}', bytecode_path)
590        if source_path is not None:
591            _imp._fix_co_filename(code, source_path)
592        return code
593    else:
594        raise ImportError('Non-code object in {!r}'.format(bytecode_path),
595                          name=name, path=bytecode_path)
596
597
598def _code_to_timestamp_pyc(code, mtime=0, source_size=0):
599    "Produce the data for a timestamp-based pyc."
600    data = bytearray(MAGIC_NUMBER)
601    data.extend(_pack_uint32(0))
602    data.extend(_pack_uint32(mtime))
603    data.extend(_pack_uint32(source_size))
604    data.extend(marshal.dumps(code))
605    return data
606
607
608def _code_to_hash_pyc(code, source_hash, checked=True):
609    "Produce the data for a hash-based pyc."
610    data = bytearray(MAGIC_NUMBER)
611    flags = 0b1 | checked << 1
612    data.extend(_pack_uint32(flags))
613    assert len(source_hash) == 8
614    data.extend(source_hash)
615    data.extend(marshal.dumps(code))
616    return data
617
618
619def decode_source(source_bytes):
620    """Decode bytes representing source code and return the string.
621
622    Universal newline support is used in the decoding.
623    """
624    import tokenize  # To avoid bootstrap issues.
625    source_bytes_readline = _io.BytesIO(source_bytes).readline
626    encoding = tokenize.detect_encoding(source_bytes_readline)
627    newline_decoder = _io.IncrementalNewlineDecoder(None, True)
628    return newline_decoder.decode(source_bytes.decode(encoding[0]))
629
630
631# Module specifications #######################################################
632
633_POPULATE = object()
634
635
636def spec_from_file_location(name, location=None, *, loader=None,
637                            submodule_search_locations=_POPULATE):
638    """Return a module spec based on a file location.
639
640    To indicate that the module is a package, set
641    submodule_search_locations to a list of directory paths.  An
642    empty list is sufficient, though its not otherwise useful to the
643    import system.
644
645    The loader must take a spec as its only __init__() arg.
646
647    """
648    if location is None:
649        # The caller may simply want a partially populated location-
650        # oriented spec.  So we set the location to a bogus value and
651        # fill in as much as we can.
652        location = '<unknown>'
653        if hasattr(loader, 'get_filename'):
654            # ExecutionLoader
655            try:
656                location = loader.get_filename(name)
657            except ImportError:
658                pass
659    else:
660        location = _os.fspath(location)
661
662    # If the location is on the filesystem, but doesn't actually exist,
663    # we could return None here, indicating that the location is not
664    # valid.  However, we don't have a good way of testing since an
665    # indirect location (e.g. a zip file or URL) will look like a
666    # non-existent file relative to the filesystem.
667
668    spec = _bootstrap.ModuleSpec(name, loader, origin=location)
669    spec._set_fileattr = True
670
671    # Pick a loader if one wasn't provided.
672    if loader is None:
673        for loader_class, suffixes in _get_supported_file_loaders():
674            if location.endswith(tuple(suffixes)):
675                loader = loader_class(name, location)
676                spec.loader = loader
677                break
678        else:
679            return None
680
681    # Set submodule_search_paths appropriately.
682    if submodule_search_locations is _POPULATE:
683        # Check the loader.
684        if hasattr(loader, 'is_package'):
685            try:
686                is_package = loader.is_package(name)
687            except ImportError:
688                pass
689            else:
690                if is_package:
691                    spec.submodule_search_locations = []
692    else:
693        spec.submodule_search_locations = submodule_search_locations
694    if spec.submodule_search_locations == []:
695        if location:
696            dirname = _path_split(location)[0]
697            spec.submodule_search_locations.append(dirname)
698
699    return spec
700
701
702# Loaders #####################################################################
703
704class WindowsRegistryFinder:
705
706    """Meta path finder for modules declared in the Windows registry."""
707
708    REGISTRY_KEY = (
709        'Software\\Python\\PythonCore\\{sys_version}'
710        '\\Modules\\{fullname}')
711    REGISTRY_KEY_DEBUG = (
712        'Software\\Python\\PythonCore\\{sys_version}'
713        '\\Modules\\{fullname}\\Debug')
714    DEBUG_BUILD = False  # Changed in _setup()
715
716    @classmethod
717    def _open_registry(cls, key):
718        try:
719            return winreg.OpenKey(winreg.HKEY_CURRENT_USER, key)
720        except OSError:
721            return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key)
722
723    @classmethod
724    def _search_registry(cls, fullname):
725        if cls.DEBUG_BUILD:
726            registry_key = cls.REGISTRY_KEY_DEBUG
727        else:
728            registry_key = cls.REGISTRY_KEY
729        key = registry_key.format(fullname=fullname,
730                                  sys_version='%d.%d' % sys.version_info[:2])
731        try:
732            with cls._open_registry(key) as hkey:
733                filepath = winreg.QueryValue(hkey, '')
734        except OSError:
735            return None
736        return filepath
737
738    @classmethod
739    def find_spec(cls, fullname, path=None, target=None):
740        filepath = cls._search_registry(fullname)
741        if filepath is None:
742            return None
743        try:
744            _path_stat(filepath)
745        except OSError:
746            return None
747        for loader, suffixes in _get_supported_file_loaders():
748            if filepath.endswith(tuple(suffixes)):
749                spec = _bootstrap.spec_from_loader(fullname,
750                                                   loader(fullname, filepath),
751                                                   origin=filepath)
752                return spec
753
754    @classmethod
755    def find_module(cls, fullname, path=None):
756        """Find module named in the registry.
757
758        This method is deprecated.  Use exec_module() instead.
759
760        """
761        spec = cls.find_spec(fullname, path)
762        if spec is not None:
763            return spec.loader
764        else:
765            return None
766
767
768class _LoaderBasics:
769
770    """Base class of common code needed by both SourceLoader and
771    SourcelessFileLoader."""
772
773    def is_package(self, fullname):
774        """Concrete implementation of InspectLoader.is_package by checking if
775        the path returned by get_filename has a filename of '__init__.py'."""
776        filename = _path_split(self.get_filename(fullname))[1]
777        filename_base = filename.rsplit('.', 1)[0]
778        tail_name = fullname.rpartition('.')[2]
779        return filename_base == '__init__' and tail_name != '__init__'
780
781    def create_module(self, spec):
782        """Use default semantics for module creation."""
783
784    def exec_module(self, module):
785        """Execute the module."""
786        code = self.get_code(module.__name__)
787        if code is None:
788            raise ImportError('cannot load module {!r} when get_code() '
789                              'returns None'.format(module.__name__))
790        _bootstrap._call_with_frames_removed(exec, code, module.__dict__)
791
792    def load_module(self, fullname):
793        """This module is deprecated."""
794        return _bootstrap._load_module_shim(self, fullname)
795
796
797class SourceLoader(_LoaderBasics):
798
799    def path_mtime(self, path):
800        """Optional method that returns the modification time (an int) for the
801        specified path (a str).
802
803        Raises OSError when the path cannot be handled.
804        """
805        raise OSError
806
807    def path_stats(self, path):
808        """Optional method returning a metadata dict for the specified
809        path (a str).
810
811        Possible keys:
812        - 'mtime' (mandatory) is the numeric timestamp of last source
813          code modification;
814        - 'size' (optional) is the size in bytes of the source code.
815
816        Implementing this method allows the loader to read bytecode files.
817        Raises OSError when the path cannot be handled.
818        """
819        return {'mtime': self.path_mtime(path)}
820
821    def _cache_bytecode(self, source_path, cache_path, data):
822        """Optional method which writes data (bytes) to a file path (a str).
823
824        Implementing this method allows for the writing of bytecode files.
825
826        The source path is needed in order to correctly transfer permissions
827        """
828        # For backwards compatibility, we delegate to set_data()
829        return self.set_data(cache_path, data)
830
831    def set_data(self, path, data):
832        """Optional method which writes data (bytes) to a file path (a str).
833
834        Implementing this method allows for the writing of bytecode files.
835        """
836
837
838    def get_source(self, fullname):
839        """Concrete implementation of InspectLoader.get_source."""
840        path = self.get_filename(fullname)
841        try:
842            source_bytes = self.get_data(path)
843        except OSError as exc:
844            raise ImportError('source not available through get_data()',
845                              name=fullname) from exc
846        return decode_source(source_bytes)
847
848    def source_to_code(self, data, path, *, _optimize=-1):
849        """Return the code object compiled from source.
850
851        The 'data' argument can be any object type that compile() supports.
852        """
853        return _bootstrap._call_with_frames_removed(compile, data, path, 'exec',
854                                        dont_inherit=True, optimize=_optimize)
855
856    def get_code(self, fullname):
857        """Concrete implementation of InspectLoader.get_code.
858
859        Reading of bytecode requires path_stats to be implemented. To write
860        bytecode, set_data must also be implemented.
861
862        """
863        source_path = self.get_filename(fullname)
864        source_mtime = None
865        source_bytes = None
866        source_hash = None
867        hash_based = False
868        check_source = True
869        try:
870            bytecode_path = cache_from_source(source_path)
871        except NotImplementedError:
872            bytecode_path = None
873        else:
874            try:
875                st = self.path_stats(source_path)
876            except OSError:
877                pass
878            else:
879                source_mtime = int(st['mtime'])
880                try:
881                    data = self.get_data(bytecode_path)
882                except OSError:
883                    pass
884                else:
885                    exc_details = {
886                        'name': fullname,
887                        'path': bytecode_path,
888                    }
889                    try:
890                        flags = _classify_pyc(data, fullname, exc_details)
891                        bytes_data = memoryview(data)[16:]
892                        hash_based = flags & 0b1 != 0
893                        if hash_based:
894                            check_source = flags & 0b10 != 0
895                            if (_imp.check_hash_based_pycs != 'never' and
896                                (check_source or
897                                 _imp.check_hash_based_pycs == 'always')):
898                                source_bytes = self.get_data(source_path)
899                                source_hash = _imp.source_hash(
900                                    _RAW_MAGIC_NUMBER,
901                                    source_bytes,
902                                )
903                                _validate_hash_pyc(data, source_hash, fullname,
904                                                   exc_details)
905                        else:
906                            _validate_timestamp_pyc(
907                                data,
908                                source_mtime,
909                                st['size'],
910                                fullname,
911                                exc_details,
912                            )
913                    except (ImportError, EOFError):
914                        pass
915                    else:
916                        _bootstrap._verbose_message('{} matches {}', bytecode_path,
917                                                    source_path)
918                        return _compile_bytecode(bytes_data, name=fullname,
919                                                 bytecode_path=bytecode_path,
920                                                 source_path=source_path)
921        if source_bytes is None:
922            source_bytes = self.get_data(source_path)
923        code_object = self.source_to_code(source_bytes, source_path)
924        _bootstrap._verbose_message('code object from {}', source_path)
925        if (not sys.dont_write_bytecode and bytecode_path is not None and
926                source_mtime is not None):
927            if hash_based:
928                if source_hash is None:
929                    source_hash = _imp.source_hash(source_bytes)
930                data = _code_to_hash_pyc(code_object, source_hash, check_source)
931            else:
932                data = _code_to_timestamp_pyc(code_object, source_mtime,
933                                              len(source_bytes))
934            try:
935                self._cache_bytecode(source_path, bytecode_path, data)
936            except NotImplementedError:
937                pass
938        return code_object
939
940
941class FileLoader:
942
943    """Base file loader class which implements the loader protocol methods that
944    require file system usage."""
945
946    def __init__(self, fullname, path):
947        """Cache the module name and the path to the file found by the
948        finder."""
949        self.name = fullname
950        self.path = path
951
952    def __eq__(self, other):
953        return (self.__class__ == other.__class__ and
954                self.__dict__ == other.__dict__)
955
956    def __hash__(self):
957        return hash(self.name) ^ hash(self.path)
958
959    @_check_name
960    def load_module(self, fullname):
961        """Load a module from a file.
962
963        This method is deprecated.  Use exec_module() instead.
964
965        """
966        # The only reason for this method is for the name check.
967        # Issue #14857: Avoid the zero-argument form of super so the implementation
968        # of that form can be updated without breaking the frozen module
969        return super(FileLoader, self).load_module(fullname)
970
971    @_check_name
972    def get_filename(self, fullname):
973        """Return the path to the source file as found by the finder."""
974        return self.path
975
976    def get_data(self, path):
977        """Return the data from path as raw bytes."""
978        if isinstance(self, (SourceLoader, ExtensionFileLoader)):
979            with _io.open_code(str(path)) as file:
980                return file.read()
981        else:
982            with _io.FileIO(path, 'r') as file:
983                return file.read()
984
985    # ResourceReader ABC API.
986
987    @_check_name
988    def get_resource_reader(self, module):
989        if self.is_package(module):
990            return self
991        return None
992
993    def open_resource(self, resource):
994        path = _path_join(_path_split(self.path)[0], resource)
995        return _io.FileIO(path, 'r')
996
997    def resource_path(self, resource):
998        if not self.is_resource(resource):
999            raise FileNotFoundError
1000        path = _path_join(_path_split(self.path)[0], resource)
1001        return path
1002
1003    def is_resource(self, name):
1004        if path_sep in name:
1005            return False
1006        path = _path_join(_path_split(self.path)[0], name)
1007        return _path_isfile(path)
1008
1009    def contents(self):
1010        return iter(_os.listdir(_path_split(self.path)[0]))
1011
1012
1013class SourceFileLoader(FileLoader, SourceLoader):
1014
1015    """Concrete implementation of SourceLoader using the file system."""
1016
1017    def path_stats(self, path):
1018        """Return the metadata for the path."""
1019        st = _path_stat(path)
1020        return {'mtime': st.st_mtime, 'size': st.st_size}
1021
1022    def _cache_bytecode(self, source_path, bytecode_path, data):
1023        # Adapt between the two APIs
1024        mode = _calc_mode(source_path)
1025        return self.set_data(bytecode_path, data, _mode=mode)
1026
1027    def set_data(self, path, data, *, _mode=0o666):
1028        """Write bytes data to a file."""
1029        parent, filename = _path_split(path)
1030        path_parts = []
1031        # Figure out what directories are missing.
1032        while parent and not _path_isdir(parent):
1033            parent, part = _path_split(parent)
1034            path_parts.append(part)
1035        # Create needed directories.
1036        for part in reversed(path_parts):
1037            parent = _path_join(parent, part)
1038            try:
1039                _os.mkdir(parent)
1040            except FileExistsError:
1041                # Probably another Python process already created the dir.
1042                continue
1043            except OSError as exc:
1044                # Could be a permission error, read-only filesystem: just forget
1045                # about writing the data.
1046                _bootstrap._verbose_message('could not create {!r}: {!r}',
1047                                            parent, exc)
1048                return
1049        try:
1050            _write_atomic(path, data, _mode)
1051            _bootstrap._verbose_message('created {!r}', path)
1052        except OSError as exc:
1053            # Same as above: just don't write the bytecode.
1054            _bootstrap._verbose_message('could not create {!r}: {!r}', path,
1055                                        exc)
1056
1057
1058class SourcelessFileLoader(FileLoader, _LoaderBasics):
1059
1060    """Loader which handles sourceless file imports."""
1061
1062    def get_code(self, fullname):
1063        path = self.get_filename(fullname)
1064        data = self.get_data(path)
1065        # Call _classify_pyc to do basic validation of the pyc but ignore the
1066        # result. There's no source to check against.
1067        exc_details = {
1068            'name': fullname,
1069            'path': path,
1070        }
1071        _classify_pyc(data, fullname, exc_details)
1072        return _compile_bytecode(
1073            memoryview(data)[16:],
1074            name=fullname,
1075            bytecode_path=path,
1076        )
1077
1078    def get_source(self, fullname):
1079        """Return None as there is no source code."""
1080        return None
1081
1082
1083# Filled in by _setup().
1084EXTENSION_SUFFIXES = []
1085
1086
1087class ExtensionFileLoader(FileLoader, _LoaderBasics):
1088
1089    """Loader for extension modules.
1090
1091    The constructor is designed to work with FileFinder.
1092
1093    """
1094
1095    def __init__(self, name, path):
1096        self.name = name
1097        self.path = path
1098
1099    def __eq__(self, other):
1100        return (self.__class__ == other.__class__ and
1101                self.__dict__ == other.__dict__)
1102
1103    def __hash__(self):
1104        return hash(self.name) ^ hash(self.path)
1105
1106    def create_module(self, spec):
1107        """Create an unitialized extension module"""
1108        module = _bootstrap._call_with_frames_removed(
1109            _imp.create_dynamic, spec)
1110        _bootstrap._verbose_message('extension module {!r} loaded from {!r}',
1111                         spec.name, self.path)
1112        return module
1113
1114    def exec_module(self, module):
1115        """Initialize an extension module"""
1116        _bootstrap._call_with_frames_removed(_imp.exec_dynamic, module)
1117        _bootstrap._verbose_message('extension module {!r} executed from {!r}',
1118                         self.name, self.path)
1119
1120    def is_package(self, fullname):
1121        """Return True if the extension module is a package."""
1122        file_name = _path_split(self.path)[1]
1123        return any(file_name == '__init__' + suffix
1124                   for suffix in EXTENSION_SUFFIXES)
1125
1126    def get_code(self, fullname):
1127        """Return None as an extension module cannot create a code object."""
1128        return None
1129
1130    def get_source(self, fullname):
1131        """Return None as extension modules have no source code."""
1132        return None
1133
1134    @_check_name
1135    def get_filename(self, fullname):
1136        """Return the path to the source file as found by the finder."""
1137        return self.path
1138
1139
1140class _NamespacePath:
1141    """Represents a namespace package's path.  It uses the module name
1142    to find its parent module, and from there it looks up the parent's
1143    __path__.  When this changes, the module's own path is recomputed,
1144    using path_finder.  For top-level modules, the parent module's path
1145    is sys.path."""
1146
1147    def __init__(self, name, path, path_finder):
1148        self._name = name
1149        self._path = path
1150        self._last_parent_path = tuple(self._get_parent_path())
1151        self._path_finder = path_finder
1152
1153    def _find_parent_path_names(self):
1154        """Returns a tuple of (parent-module-name, parent-path-attr-name)"""
1155        parent, dot, me = self._name.rpartition('.')
1156        if dot == '':
1157            # This is a top-level module. sys.path contains the parent path.
1158            return 'sys', 'path'
1159        # Not a top-level module. parent-module.__path__ contains the
1160        #  parent path.
1161        return parent, '__path__'
1162
1163    def _get_parent_path(self):
1164        parent_module_name, path_attr_name = self._find_parent_path_names()
1165        return getattr(sys.modules[parent_module_name], path_attr_name)
1166
1167    def _recalculate(self):
1168        # If the parent's path has changed, recalculate _path
1169        parent_path = tuple(self._get_parent_path()) # Make a copy
1170        if parent_path != self._last_parent_path:
1171            spec = self._path_finder(self._name, parent_path)
1172            # Note that no changes are made if a loader is returned, but we
1173            #  do remember the new parent path
1174            if spec is not None and spec.loader is None:
1175                if spec.submodule_search_locations:
1176                    self._path = spec.submodule_search_locations
1177            self._last_parent_path = parent_path     # Save the copy
1178        return self._path
1179
1180    def __iter__(self):
1181        return iter(self._recalculate())
1182
1183    def __getitem__(self, index):
1184        return self._recalculate()[index]
1185
1186    def __setitem__(self, index, path):
1187        self._path[index] = path
1188
1189    def __len__(self):
1190        return len(self._recalculate())
1191
1192    def __repr__(self):
1193        return '_NamespacePath({!r})'.format(self._path)
1194
1195    def __contains__(self, item):
1196        return item in self._recalculate()
1197
1198    def append(self, item):
1199        self._path.append(item)
1200
1201
1202# We use this exclusively in module_from_spec() for backward-compatibility.
1203class _NamespaceLoader:
1204    def __init__(self, name, path, path_finder):
1205        self._path = _NamespacePath(name, path, path_finder)
1206
1207    @classmethod
1208    def module_repr(cls, module):
1209        """Return repr for the module.
1210
1211        The method is deprecated.  The import machinery does the job itself.
1212
1213        """
1214        return '<module {!r} (namespace)>'.format(module.__name__)
1215
1216    def is_package(self, fullname):
1217        return True
1218
1219    def get_source(self, fullname):
1220        return ''
1221
1222    def get_code(self, fullname):
1223        return compile('', '<string>', 'exec', dont_inherit=True)
1224
1225    def create_module(self, spec):
1226        """Use default semantics for module creation."""
1227
1228    def exec_module(self, module):
1229        pass
1230
1231    def load_module(self, fullname):
1232        """Load a namespace module.
1233
1234        This method is deprecated.  Use exec_module() instead.
1235
1236        """
1237        # The import system never calls this method.
1238        _bootstrap._verbose_message('namespace module loaded with path {!r}',
1239                                    self._path)
1240        return _bootstrap._load_module_shim(self, fullname)
1241
1242
1243# Finders #####################################################################
1244
1245class PathFinder:
1246
1247    """Meta path finder for sys.path and package __path__ attributes."""
1248
1249    @classmethod
1250    def invalidate_caches(cls):
1251        """Call the invalidate_caches() method on all path entry finders
1252        stored in sys.path_importer_caches (where implemented)."""
1253        for name, finder in list(sys.path_importer_cache.items()):
1254            if finder is None:
1255                del sys.path_importer_cache[name]
1256            elif hasattr(finder, 'invalidate_caches'):
1257                finder.invalidate_caches()
1258
1259    @classmethod
1260    def _path_hooks(cls, path):
1261        """Search sys.path_hooks for a finder for 'path'."""
1262        if sys.path_hooks is not None and not sys.path_hooks:
1263            _warnings.warn('sys.path_hooks is empty', ImportWarning)
1264        for hook in sys.path_hooks:
1265            try:
1266                return hook(path)
1267            except ImportError:
1268                continue
1269        else:
1270            return None
1271
1272    @classmethod
1273    def _path_importer_cache(cls, path):
1274        """Get the finder for the path entry from sys.path_importer_cache.
1275
1276        If the path entry is not in the cache, find the appropriate finder
1277        and cache it. If no finder is available, store None.
1278
1279        """
1280        if path == '':
1281            try:
1282                path = _os.getcwd()
1283            except FileNotFoundError:
1284                # Don't cache the failure as the cwd can easily change to
1285                # a valid directory later on.
1286                return None
1287        try:
1288            finder = sys.path_importer_cache[path]
1289        except KeyError:
1290            finder = cls._path_hooks(path)
1291            sys.path_importer_cache[path] = finder
1292        return finder
1293
1294    @classmethod
1295    def _legacy_get_spec(cls, fullname, finder):
1296        # This would be a good place for a DeprecationWarning if
1297        # we ended up going that route.
1298        if hasattr(finder, 'find_loader'):
1299            loader, portions = finder.find_loader(fullname)
1300        else:
1301            loader = finder.find_module(fullname)
1302            portions = []
1303        if loader is not None:
1304            return _bootstrap.spec_from_loader(fullname, loader)
1305        spec = _bootstrap.ModuleSpec(fullname, None)
1306        spec.submodule_search_locations = portions
1307        return spec
1308
1309    @classmethod
1310    def _get_spec(cls, fullname, path, target=None):
1311        """Find the loader or namespace_path for this module/package name."""
1312        # If this ends up being a namespace package, namespace_path is
1313        #  the list of paths that will become its __path__
1314        namespace_path = []
1315        for entry in path:
1316            if not isinstance(entry, (str, bytes)):
1317                continue
1318            finder = cls._path_importer_cache(entry)
1319            if finder is not None:
1320                if hasattr(finder, 'find_spec'):
1321                    spec = finder.find_spec(fullname, target)
1322                else:
1323                    spec = cls._legacy_get_spec(fullname, finder)
1324                if spec is None:
1325                    continue
1326                if spec.loader is not None:
1327                    return spec
1328                portions = spec.submodule_search_locations
1329                if portions is None:
1330                    raise ImportError('spec missing loader')
1331                # This is possibly part of a namespace package.
1332                #  Remember these path entries (if any) for when we
1333                #  create a namespace package, and continue iterating
1334                #  on path.
1335                namespace_path.extend(portions)
1336        else:
1337            spec = _bootstrap.ModuleSpec(fullname, None)
1338            spec.submodule_search_locations = namespace_path
1339            return spec
1340
1341    @classmethod
1342    def find_spec(cls, fullname, path=None, target=None):
1343        """Try to find a spec for 'fullname' on sys.path or 'path'.
1344
1345        The search is based on sys.path_hooks and sys.path_importer_cache.
1346        """
1347        if path is None:
1348            path = sys.path
1349        spec = cls._get_spec(fullname, path, target)
1350        if spec is None:
1351            return None
1352        elif spec.loader is None:
1353            namespace_path = spec.submodule_search_locations
1354            if namespace_path:
1355                # We found at least one namespace path.  Return a spec which
1356                # can create the namespace package.
1357                spec.origin = None
1358                spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec)
1359                return spec
1360            else:
1361                return None
1362        else:
1363            return spec
1364
1365    @classmethod
1366    def find_module(cls, fullname, path=None):
1367        """find the module on sys.path or 'path' based on sys.path_hooks and
1368        sys.path_importer_cache.
1369
1370        This method is deprecated.  Use find_spec() instead.
1371
1372        """
1373        spec = cls.find_spec(fullname, path)
1374        if spec is None:
1375            return None
1376        return spec.loader
1377
1378    @classmethod
1379    def find_distributions(cls, *args, **kwargs):
1380        """
1381        Find distributions.
1382
1383        Return an iterable of all Distribution instances capable of
1384        loading the metadata for packages matching ``context.name``
1385        (or all names if ``None`` indicated) along the paths in the list
1386        of directories ``context.path``.
1387        """
1388        from importlib.metadata import MetadataPathFinder
1389        return MetadataPathFinder.find_distributions(*args, **kwargs)
1390
1391
1392class FileFinder:
1393
1394    """File-based finder.
1395
1396    Interactions with the file system are cached for performance, being
1397    refreshed when the directory the finder is handling has been modified.
1398
1399    """
1400
1401    def __init__(self, path, *loader_details):
1402        """Initialize with the path to search on and a variable number of
1403        2-tuples containing the loader and the file suffixes the loader
1404        recognizes."""
1405        loaders = []
1406        for loader, suffixes in loader_details:
1407            loaders.extend((suffix, loader) for suffix in suffixes)
1408        self._loaders = loaders
1409        # Base (directory) path
1410        self.path = path or '.'
1411        self._path_mtime = -1
1412        self._path_cache = set()
1413        self._relaxed_path_cache = set()
1414
1415    def invalidate_caches(self):
1416        """Invalidate the directory mtime."""
1417        self._path_mtime = -1
1418
1419    find_module = _find_module_shim
1420
1421    def find_loader(self, fullname):
1422        """Try to find a loader for the specified module, or the namespace
1423        package portions. Returns (loader, list-of-portions).
1424
1425        This method is deprecated.  Use find_spec() instead.
1426
1427        """
1428        spec = self.find_spec(fullname)
1429        if spec is None:
1430            return None, []
1431        return spec.loader, spec.submodule_search_locations or []
1432
1433    def _get_spec(self, loader_class, fullname, path, smsl, target):
1434        loader = loader_class(fullname, path)
1435        return spec_from_file_location(fullname, path, loader=loader,
1436                                       submodule_search_locations=smsl)
1437
1438    def find_spec(self, fullname, target=None):
1439        """Try to find a spec for the specified module.
1440
1441        Returns the matching spec, or None if not found.
1442        """
1443        is_namespace = False
1444        tail_module = fullname.rpartition('.')[2]
1445        try:
1446            mtime = _path_stat(self.path or _os.getcwd()).st_mtime
1447        except OSError:
1448            mtime = -1
1449        if mtime != self._path_mtime:
1450            self._fill_cache()
1451            self._path_mtime = mtime
1452        # tail_module keeps the original casing, for __file__ and friends
1453        if _relax_case():
1454            cache = self._relaxed_path_cache
1455            cache_module = tail_module.lower()
1456        else:
1457            cache = self._path_cache
1458            cache_module = tail_module
1459        # Check if the module is the name of a directory (and thus a package).
1460        if cache_module in cache:
1461            base_path = _path_join(self.path, tail_module)
1462            for suffix, loader_class in self._loaders:
1463                init_filename = '__init__' + suffix
1464                full_path = _path_join(base_path, init_filename)
1465                if _path_isfile(full_path):
1466                    return self._get_spec(loader_class, fullname, full_path, [base_path], target)
1467            else:
1468                # If a namespace package, return the path if we don't
1469                #  find a module in the next section.
1470                is_namespace = _path_isdir(base_path)
1471        # Check for a file w/ a proper suffix exists.
1472        for suffix, loader_class in self._loaders:
1473            full_path = _path_join(self.path, tail_module + suffix)
1474            _bootstrap._verbose_message('trying {}', full_path, verbosity=2)
1475            if cache_module + suffix in cache:
1476                if _path_isfile(full_path):
1477                    return self._get_spec(loader_class, fullname, full_path,
1478                                          None, target)
1479        if is_namespace:
1480            _bootstrap._verbose_message('possible namespace for {}', base_path)
1481            spec = _bootstrap.ModuleSpec(fullname, None)
1482            spec.submodule_search_locations = [base_path]
1483            return spec
1484        return None
1485
1486    def _fill_cache(self):
1487        """Fill the cache of potential modules and packages for this directory."""
1488        path = self.path
1489        try:
1490            contents = _os.listdir(path or _os.getcwd())
1491        except (FileNotFoundError, PermissionError, NotADirectoryError):
1492            # Directory has either been removed, turned into a file, or made
1493            # unreadable.
1494            contents = []
1495        # We store two cached versions, to handle runtime changes of the
1496        # PYTHONCASEOK environment variable.
1497        if not sys.platform.startswith('win'):
1498            self._path_cache = set(contents)
1499        else:
1500            # Windows users can import modules with case-insensitive file
1501            # suffixes (for legacy reasons). Make the suffix lowercase here
1502            # so it's done once instead of for every import. This is safe as
1503            # the specified suffixes to check against are always specified in a
1504            # case-sensitive manner.
1505            lower_suffix_contents = set()
1506            for item in contents:
1507                name, dot, suffix = item.partition('.')
1508                if dot:
1509                    new_name = '{}.{}'.format(name, suffix.lower())
1510                else:
1511                    new_name = name
1512                lower_suffix_contents.add(new_name)
1513            self._path_cache = lower_suffix_contents
1514        if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS):
1515            self._relaxed_path_cache = {fn.lower() for fn in contents}
1516
1517    @classmethod
1518    def path_hook(cls, *loader_details):
1519        """A class method which returns a closure to use on sys.path_hook
1520        which will return an instance using the specified loaders and the path
1521        called on the closure.
1522
1523        If the path called on the closure is not a directory, ImportError is
1524        raised.
1525
1526        """
1527        def path_hook_for_FileFinder(path):
1528            """Path hook for importlib.machinery.FileFinder."""
1529            if not _path_isdir(path):
1530                raise ImportError('only directories are supported', path=path)
1531            return cls(path, *loader_details)
1532
1533        return path_hook_for_FileFinder
1534
1535    def __repr__(self):
1536        return 'FileFinder({!r})'.format(self.path)
1537
1538
1539# Import setup ###############################################################
1540
1541def _fix_up_module(ns, name, pathname, cpathname=None):
1542    # This function is used by PyImport_ExecCodeModuleObject().
1543    loader = ns.get('__loader__')
1544    spec = ns.get('__spec__')
1545    if not loader:
1546        if spec:
1547            loader = spec.loader
1548        elif pathname == cpathname:
1549            loader = SourcelessFileLoader(name, pathname)
1550        else:
1551            loader = SourceFileLoader(name, pathname)
1552    if not spec:
1553        spec = spec_from_file_location(name, pathname, loader=loader)
1554    try:
1555        ns['__spec__'] = spec
1556        ns['__loader__'] = loader
1557        ns['__file__'] = pathname
1558        ns['__cached__'] = cpathname
1559    except Exception:
1560        # Not important enough to report.
1561        pass
1562
1563
1564def _get_supported_file_loaders():
1565    """Returns a list of file-based module loaders.
1566
1567    Each item is a tuple (loader, suffixes).
1568    """
1569    extensions = ExtensionFileLoader, _imp.extension_suffixes()
1570    source = SourceFileLoader, SOURCE_SUFFIXES
1571    bytecode = SourcelessFileLoader, BYTECODE_SUFFIXES
1572    return [extensions, source, bytecode]
1573
1574
1575def _setup(_bootstrap_module):
1576    """Setup the path-based importers for importlib by importing needed
1577    built-in modules and injecting them into the global namespace.
1578
1579    Other components are extracted from the core bootstrap module.
1580
1581    """
1582    global sys, _imp, _bootstrap
1583    _bootstrap = _bootstrap_module
1584    sys = _bootstrap.sys
1585    _imp = _bootstrap._imp
1586
1587    self_module = sys.modules[__name__]
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
1607    setattr(self_module, '_os', os_module)
1608    setattr(self_module, 'path_sep', path_sep)
1609    setattr(self_module, 'path_separators', ''.join(path_separators))
1610    setattr(self_module, '_pathseps_with_colon', {f':{s}' for s in path_separators})
1611
1612    # Directly load built-in modules needed during bootstrap.
1613    builtin_names = ['_io', '_warnings', 'marshal']
1614    if builtin_os == 'nt':
1615        builtin_names.append('winreg')
1616    for builtin_name in builtin_names:
1617        if builtin_name not in sys.modules:
1618            builtin_module = _bootstrap._builtin_from_name(builtin_name)
1619        else:
1620            builtin_module = sys.modules[builtin_name]
1621        setattr(self_module, builtin_name, builtin_module)
1622
1623    # Constants
1624    setattr(self_module, '_relax_case', _make_relax_case())
1625    EXTENSION_SUFFIXES.extend(_imp.extension_suffixes())
1626    if builtin_os == 'nt':
1627        SOURCE_SUFFIXES.append('.pyw')
1628        if '_d.pyd' in EXTENSION_SUFFIXES:
1629            WindowsRegistryFinder.DEBUG_BUILD = True
1630
1631
1632def _install(_bootstrap_module):
1633    """Install the path-based import components."""
1634    _setup(_bootstrap_module)
1635    supported_loaders = _get_supported_file_loaders()
1636    sys.path_hooks.extend([FileFinder.path_hook(*supported_loaders)])
1637    sys.meta_path.append(PathFinder)
1638