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