Skip to content

Commit e69f0df

Browse files
committed
Issue #13959: Re-implement imp.find_module() in Lib/imp.py.
Thanks to Eric Snow for taking an initial stab at the implementation.
1 parent b8c0206 commit e69f0df

File tree

2 files changed

+68
-755
lines changed

2 files changed

+68
-755
lines changed

Lib/imp.py

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,29 @@
1515
# Can (probably) move to importlib
1616
from _imp import get_suffixes
1717
# Should be re-implemented here (and mostly deprecated)
18-
from _imp import (find_module, NullImporter,
19-
SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION,
20-
PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN,
21-
PY_CODERESOURCE, IMP_HOOK)
18+
from _imp import NullImporter
2219

2320
from importlib._bootstrap import _new_module as new_module
2421
from importlib._bootstrap import _cache_from_source as cache_from_source
2522

2623
from importlib import _bootstrap
2724
import os
25+
import sys
26+
import tokenize
27+
28+
29+
# XXX "deprecate" once find_module(), load_module(), and get_suffixes() are
30+
# deprecated.
31+
SEARCH_ERROR = 0
32+
PY_SOURCE = 1
33+
PY_COMPILED = 2
34+
C_EXTENSION = 3
35+
PY_RESOURCE = 4
36+
PKG_DIRECTORY = 5
37+
C_BUILTIN = 6
38+
PY_FROZEN = 7
39+
PY_CODERESOURCE = 8
40+
IMP_HOOK = 9
2841

2942

3043
def source_from_cache(path):
@@ -131,3 +144,54 @@ def load_module(name, file, filename, details):
131144
else:
132145
msg = "Don't know how to import {} (type code {}".format(name, type_)
133146
raise ImportError(msg, name=name)
147+
148+
149+
def find_module(name, path=None):
150+
"""Search for a module.
151+
152+
If path is omitted or None, search for a built-in, frozen or special
153+
module and continue search in sys.path. The module name cannot
154+
contain '.'; to search for a submodule of a package, pass the
155+
submodule name and the package's __path__.
156+
157+
"""
158+
if not isinstance(name, str):
159+
raise TypeError("'name' must be a str, not {}".format(type(name)))
160+
elif not isinstance(path, (type(None), list)):
161+
# Backwards-compatibility
162+
raise RuntimeError("'list' must be None or a list, "
163+
"not {}".format(type(name)))
164+
165+
if path is None:
166+
if is_builtin(name):
167+
return None, None, ('', '', C_BUILTIN)
168+
elif is_frozen(name):
169+
return None, None, ('', '', PY_FROZEN)
170+
else:
171+
path = sys.path
172+
173+
for entry in path:
174+
package_directory = os.path.join(entry, name)
175+
for suffix in ['.py', _bootstrap.BYTECODE_SUFFIX]:
176+
package_file_name = '__init__' + suffix
177+
file_path = os.path.join(package_directory, package_file_name)
178+
if os.path.isfile(file_path):
179+
return None, package_directory, ('', '', PKG_DIRECTORY)
180+
for suffix, mode, type_ in get_suffixes():
181+
file_name = name + suffix
182+
file_path = os.path.join(entry, file_name)
183+
if os.path.isfile(file_path):
184+
break
185+
else:
186+
continue
187+
break # Break out of outer loop when breaking out of inner loop.
188+
else:
189+
raise ImportError('No module name {!r}'.format(name), name=name)
190+
191+
encoding = None
192+
if mode == 'U':
193+
with open(file_path, 'rb') as file:
194+
encoding = tokenize.detect_encoding(file.readline)[0]
195+
file = open(file_path, mode, encoding=encoding)
196+
return file, file_path, (suffix, mode, type_)
197+

0 commit comments

Comments
 (0)