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