1"""This module provides the components needed to build your own __import__
2function.  Undocumented functions are obsolete.
3
4In most cases it is preferred you consider using the importlib module's
5functionality over this module.
6
7"""
8# (Probably) need to stay in _imp
9from _imp import (lock_held, acquire_lock, release_lock,
10                  get_frozen_object, is_frozen_package,
11                  init_frozen, is_builtin, is_frozen,
12                  _fix_co_filename)
13try:
14    from _imp import create_dynamic
15except ImportError:
16    # Platform doesn't support dynamic loading.
17    create_dynamic = None
18
19from importlib._bootstrap import _ERR_MSG, _exec, _load, _builtin_from_name
20from importlib._bootstrap_external import SourcelessFileLoader
21
22from importlib import machinery
23from importlib import util
24import importlib
25import os
26import sys
27import tokenize
28import types
29import warnings
30
31warnings.warn("the imp module is deprecated in favour of importlib; "
32              "see the module's documentation for alternative uses",
33              DeprecationWarning, stacklevel=2)
34
35# DEPRECATED
36SEARCH_ERROR = 0
37PY_SOURCE = 1
38PY_COMPILED = 2
39C_EXTENSION = 3
40PY_RESOURCE = 4
41PKG_DIRECTORY = 5
42C_BUILTIN = 6
43PY_FROZEN = 7
44PY_CODERESOURCE = 8
45IMP_HOOK = 9
46
47
48def new_module(name):
49    """**DEPRECATED**
50
51    Create a new module.
52
53    The module is not entered into sys.modules.
54
55    """
56    return types.ModuleType(name)
57
58
59def get_magic():
60    """**DEPRECATED**
61
62    Return the magic number for .pyc files.
63    """
64    return util.MAGIC_NUMBER
65
66
67def get_tag():
68    """Return the magic tag for .pyc files."""
69    return sys.implementation.cache_tag
70
71
72def cache_from_source(path, debug_override=None):
73    """**DEPRECATED**
74
75    Given the path to a .py file, return the path to its .pyc file.
76
77    The .py file does not need to exist; this simply returns the path to the
78    .pyc file calculated as if the .py file were imported.
79
80    If debug_override is not None, then it must be a boolean and is used in
81    place of sys.flags.optimize.
82
83    If sys.implementation.cache_tag is None then NotImplementedError is raised.
84
85    """
86    with warnings.catch_warnings():
87        warnings.simplefilter('ignore')
88        return util.cache_from_source(path, debug_override)
89
90
91def source_from_cache(path):
92    """**DEPRECATED**
93
94    Given the path to a .pyc. file, return the path to its .py file.
95
96    The .pyc file does not need to exist; this simply returns the path to
97    the .py file calculated to correspond to the .pyc file.  If path does
98    not conform to PEP 3147 format, ValueError will be raised. If
99    sys.implementation.cache_tag is None then NotImplementedError is raised.
100
101    """
102    return util.source_from_cache(path)
103
104
105def get_suffixes():
106    """**DEPRECATED**"""
107    extensions = [(s, 'rb', C_EXTENSION) for s in machinery.EXTENSION_SUFFIXES]
108    source = [(s, 'r', PY_SOURCE) for s in machinery.SOURCE_SUFFIXES]
109    bytecode = [(s, 'rb', PY_COMPILED) for s in machinery.BYTECODE_SUFFIXES]
110
111    return extensions + source + bytecode
112
113
114class NullImporter:
115
116    """**DEPRECATED**
117
118    Null import object.
119
120    """
121
122    def __init__(self, path):
123        if path == '':
124            raise ImportError('empty pathname', path='')
125        elif os.path.isdir(path):
126            raise ImportError('existing directory', path=path)
127
128    def find_module(self, fullname):
129        """Always returns None."""
130        return None
131
132
133class _HackedGetData:
134
135    """Compatibility support for 'file' arguments of various load_*()
136    functions."""
137
138    def __init__(self, fullname, path, file=None):
139        super().__init__(fullname, path)
140        self.file = file
141
142    def get_data(self, path):
143        """Gross hack to contort loader to deal w/ load_*()'s bad API."""
144        if self.file and path == self.path:
145            # The contract of get_data() requires us to return bytes. Reopen the
146            # file in binary mode if needed.
147            if not self.file.closed:
148                file = self.file
149                if 'b' not in file.mode:
150                    file.close()
151            if self.file.closed:
152                self.file = file = open(self.path, 'rb')
153
154            with file:
155                return file.read()
156        else:
157            return super().get_data(path)
158
159
160class _LoadSourceCompatibility(_HackedGetData, machinery.SourceFileLoader):
161
162    """Compatibility support for implementing load_source()."""
163
164
165def load_source(name, pathname, file=None):
166    loader = _LoadSourceCompatibility(name, pathname, file)
167    spec = util.spec_from_file_location(name, pathname, loader=loader)
168    if name in sys.modules:
169        module = _exec(spec, sys.modules[name])
170    else:
171        module = _load(spec)
172    # To allow reloading to potentially work, use a non-hacked loader which
173    # won't rely on a now-closed file object.
174    module.__loader__ = machinery.SourceFileLoader(name, pathname)
175    module.__spec__.loader = module.__loader__
176    return module
177
178
179class _LoadCompiledCompatibility(_HackedGetData, SourcelessFileLoader):
180
181    """Compatibility support for implementing load_compiled()."""
182
183
184def load_compiled(name, pathname, file=None):
185    """**DEPRECATED**"""
186    loader = _LoadCompiledCompatibility(name, pathname, file)
187    spec = util.spec_from_file_location(name, pathname, loader=loader)
188    if name in sys.modules:
189        module = _exec(spec, sys.modules[name])
190    else:
191        module = _load(spec)
192    # To allow reloading to potentially work, use a non-hacked loader which
193    # won't rely on a now-closed file object.
194    module.__loader__ = SourcelessFileLoader(name, pathname)
195    module.__spec__.loader = module.__loader__
196    return module
197
198
199def load_package(name, path):
200    """**DEPRECATED**"""
201    if os.path.isdir(path):
202        extensions = (machinery.SOURCE_SUFFIXES[:] +
203                      machinery.BYTECODE_SUFFIXES[:])
204        for extension in extensions:
205            init_path = os.path.join(path, '__init__' + extension)
206            if os.path.exists(init_path):
207                path = init_path
208                break
209        else:
210            raise ValueError('{!r} is not a package'.format(path))
211    spec = util.spec_from_file_location(name, path,
212                                        submodule_search_locations=[])
213    if name in sys.modules:
214        return _exec(spec, sys.modules[name])
215    else:
216        return _load(spec)
217
218
219def load_module(name, file, filename, details):
220    """**DEPRECATED**
221
222    Load a module, given information returned by find_module().
223
224    The module name must include the full package name, if any.
225
226    """
227    suffix, mode, type_ = details
228    if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
229        raise ValueError('invalid file open mode {!r}'.format(mode))
230    elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
231        msg = 'file object required for import (type code {})'.format(type_)
232        raise ValueError(msg)
233    elif type_ == PY_SOURCE:
234        return load_source(name, filename, file)
235    elif type_ == PY_COMPILED:
236        return load_compiled(name, filename, file)
237    elif type_ == C_EXTENSION and load_dynamic is not None:
238        if file is None:
239            with open(filename, 'rb') as opened_file:
240                return load_dynamic(name, filename, opened_file)
241        else:
242            return load_dynamic(name, filename, file)
243    elif type_ == PKG_DIRECTORY:
244        return load_package(name, filename)
245    elif type_ == C_BUILTIN:
246        return init_builtin(name)
247    elif type_ == PY_FROZEN:
248        return init_frozen(name)
249    else:
250        msg =  "Don't know how to import {} (type code {})".format(name, type_)
251        raise ImportError(msg, name=name)
252
253
254def find_module(name, path=None):
255    """**DEPRECATED**
256
257    Search for a module.
258
259    If path is omitted or None, search for a built-in, frozen or special
260    module and continue search in sys.path. The module name cannot
261    contain '.'; to search for a submodule of a package, pass the
262    submodule name and the package's __path__.
263
264    """
265    if not isinstance(name, str):
266        raise TypeError("'name' must be a str, not {}".format(type(name)))
267    elif not isinstance(path, (type(None), list)):
268        # Backwards-compatibility
269        raise RuntimeError("'path' must be None or a list, "
270                           "not {}".format(type(path)))
271
272    if path is None:
273        if is_builtin(name):
274            return None, None, ('', '', C_BUILTIN)
275        elif is_frozen(name):
276            return None, None, ('', '', PY_FROZEN)
277        else:
278            path = sys.path
279
280    for entry in path:
281        package_directory = os.path.join(entry, name)
282        for suffix in ['.py', machinery.BYTECODE_SUFFIXES[0]]:
283            package_file_name = '__init__' + suffix
284            file_path = os.path.join(package_directory, package_file_name)
285            if os.path.isfile(file_path):
286                return None, package_directory, ('', '', PKG_DIRECTORY)
287        for suffix, mode, type_ in get_suffixes():
288            file_name = name + suffix
289            file_path = os.path.join(entry, file_name)
290            if os.path.isfile(file_path):
291                break
292        else:
293            continue
294        break  # Break out of outer loop when breaking out of inner loop.
295    else:
296        raise ImportError(_ERR_MSG.format(name), name=name)
297
298    encoding = None
299    if 'b' not in mode:
300        with open(file_path, 'rb') as file:
301            encoding = tokenize.detect_encoding(file.readline)[0]
302    file = open(file_path, mode, encoding=encoding)
303    return file, file_path, (suffix, mode, type_)
304
305
306def reload(module):
307    """**DEPRECATED**
308
309    Reload the module and return it.
310
311    The module must have been successfully imported before.
312
313    """
314    return importlib.reload(module)
315
316
317def init_builtin(name):
318    """**DEPRECATED**
319
320    Load and return a built-in module by name, or None is such module doesn't
321    exist
322    """
323    try:
324        return _builtin_from_name(name)
325    except ImportError:
326        return None
327
328
329if create_dynamic:
330    def load_dynamic(name, path, file=None):
331        """**DEPRECATED**
332
333        Load an extension module.
334        """
335        import importlib.machinery
336        loader = importlib.machinery.ExtensionFileLoader(name, path)
337
338        # Issue #24748: Skip the sys.modules check in _load_module_shim;
339        # always load new extension
340        spec = importlib.machinery.ModuleSpec(
341            name=name, loader=loader, origin=path)
342        return _load(spec)
343
344else:
345    load_dynamic = None
346