summaryrefslogtreecommitdiffstats
path: root/Lib/imp.py
blob: 6a86ba9bb6395c2a7f3fab21841250998f24332c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
"""This module provides the components needed to build your own __import__
function.  Undocumented functions are obsolete.

In most cases it is preferred you consider using the importlib module's
functionality over this module.

"""
# (Probably) need to stay in _imp
from _imp import (lock_held, acquire_lock, release_lock, reload,
                  load_dynamic, get_frozen_object, is_frozen_package,
                  init_builtin, init_frozen, is_builtin, is_frozen,
                  _fix_co_filename)
# Can (probably) move to importlib
from _imp import (get_magic, get_tag, get_suffixes, cache_from_source,
                  source_from_cache)
# Should be re-implemented here (and mostly deprecated)
from _imp import (find_module, NullImporter,
                  SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION,
                  PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN,
                  PY_CODERESOURCE, IMP_HOOK)

from importlib._bootstrap import _new_module as new_module

from importlib import _bootstrap
import os


class _HackedGetData:

    """Compatibiilty support for 'file' arguments of various load_*()
    functions."""

    def __init__(self, fullname, path, file=None):
        super().__init__(fullname, path)
        self.file = file

    def get_data(self, path):
        """Gross hack to contort loader to deal w/ load_*()'s bad API."""
        if self.file and path == self._path:
            with self.file:
                # Technically should be returning bytes, but
                # SourceLoader.get_code() just passed what is returned to
                # compile() which can handle str. And converting to bytes would
                # require figuring out the encoding to decode to and
                # tokenize.detect_encoding() only accepts bytes.
                return self.file.read()
        else:
            return super().get_data(path)


class _LoadSourceCompatibility(_HackedGetData, _bootstrap._SourceFileLoader):

    """Compatibility support for implementing load_source()."""


def load_source(name, pathname, file=None):
    return _LoadSourceCompatibility(name, pathname, file).load_module(name)


class _LoadCompiledCompatibility(_HackedGetData,
        _bootstrap._SourcelessFileLoader):

    """Compatibility support for implementing load_compiled()."""


def load_compiled(name, pathname, file=None):
    return _LoadCompiledCompatibility(name, pathname, file).load_module(name)


def load_package(name, path):
    if os.path.isdir(path):
        extensions = _bootstrap._suffix_list(PY_SOURCE)
        extensions += _bootstrap._suffix_list(PY_COMPILED)
        for extension in extensions:
            path = os.path.join(path, '__init__'+extension)
            if os.path.exists(path):
                break
        else:
            raise ValueError('{!r} is not a package'.format(path))
    return _bootstrap._SourceFileLoader(name, path).load_module(name)


def load_module(name, file, filename, details):
    """Load a module, given information returned by find_module().

    The module name must include the full package name, if any.

    """
    suffix, mode, type_ = details
    if mode and (not mode.startswith(('r', 'U')) or '+' in mode):
        raise ValueError('invalid file open mode {!r}'.format(mode))
    elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
        msg = 'file object required for import (type code {})'.format(type_)
        raise ValueError(msg)
    elif type_ == PY_SOURCE:
        return load_source(name, filename, file)
    elif type_ == PY_COMPILED:
        return load_compiled(name, filename, file)
    elif type_ == PKG_DIRECTORY:
        return load_package(name, filename)
    elif type_ == C_BUILTIN:
        return init_builtin(name)
    elif type_ == PY_FROZEN:
        return init_frozen(name)
    else:
        msg =  "Don't know how to import {} (type code {}".format(name, type_)
        raise ImportError(msg, name=name)