Skip to content

Commit 6f44d66

Browse files
committed
Issue #13959: Rename imp to _imp and add Lib/imp.py and begin
rewriting functionality in pure Python. To start, imp.new_module() has been rewritten in pure Python, put into importlib (privately) and then publicly exposed in imp.
1 parent 7788838 commit 6f44d66

File tree

10 files changed

+2844
-2808
lines changed

10 files changed

+2844
-2808
lines changed

Lib/imp.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""This module provides the components needed to build your own __import__
2+
function. Undocumented functions are obsolete.
3+
4+
In most cases it is preferred you consider using the importlib module's
5+
functionality over this module.
6+
7+
"""
8+
# (Probably) need to stay in _imp
9+
from _imp import (lock_held, acquire_lock, release_lock, reload,
10+
get_frozen_object, is_frozen_package, init_builtin,
11+
init_frozen, is_builtin, is_frozen, _fix_co_filename)
12+
# Can (probably) move to importlib
13+
from _imp import (get_magic, get_tag, get_suffixes, cache_from_source,
14+
source_from_cache)
15+
# Should be re-implemented here (and mostly deprecated)
16+
from _imp import (find_module, load_module, load_compiled, load_dynamic,
17+
load_package, load_source, NullImporter,
18+
SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION,
19+
PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN,
20+
PY_CODERESOURCE, IMP_HOOK)
21+
22+
from importlib._bootstrap import _new_module as new_module

Lib/importlib/_bootstrap.py

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
"""
99

10-
# Injected modules are '_warnings', 'imp', 'sys', 'marshal', '_io',
10+
# Injected modules are '_warnings', '_imp', 'sys', 'marshal', '_io',
1111
# and '_os' (a.k.a. 'posix', 'nt' or 'os2').
1212
# Injected attribute is path_sep.
1313
# Most injection is handled by _setup().
@@ -158,6 +158,16 @@ def _wrap(new, old):
158158

159159
code_type = type(_wrap.__code__)
160160

161+
162+
def _new_module(name):
163+
"""Create a new module.
164+
165+
The module is not entered into sys.modules.
166+
167+
"""
168+
return type(sys)(name)
169+
170+
161171
# Finder/loader utility code ##################################################
162172

163173
def verbose_message(message, *args):
@@ -212,7 +222,7 @@ def module_for_loader_wrapper(self, fullname, *args, **kwargs):
212222
# This must be done before open() is called as the 'io' module
213223
# implicitly imports 'locale' and would otherwise trigger an
214224
# infinite loop.
215-
module = imp.new_module(fullname)
225+
module = _new_module(fullname)
216226
sys.modules[fullname] = module
217227
try:
218228
return fxn(self, module, *args, **kwargs)
@@ -254,7 +264,7 @@ def _requires_builtin_wrapper(self, fullname):
254264
def _requires_frozen(fxn):
255265
"""Decorator to verify the named module is frozen."""
256266
def _requires_frozen_wrapper(self, fullname):
257-
if not imp.is_frozen(fullname):
267+
if not _imp.is_frozen(fullname):
258268
raise ImportError("{0} is not a frozen module".format(fullname),
259269
name=fullname)
260270
return fxn(self, fullname)
@@ -264,7 +274,7 @@ def _requires_frozen_wrapper(self, fullname):
264274

265275
def _suffix_list(suffix_type):
266276
"""Return a list of file suffixes based on the imp file type."""
267-
return [suffix[0] for suffix in imp.get_suffixes()
277+
return [suffix[0] for suffix in _imp.get_suffixes()
268278
if suffix[2] == suffix_type]
269279

270280

@@ -288,7 +298,7 @@ def find_module(cls, fullname, path=None):
288298
"""
289299
if path is not None:
290300
return None
291-
return cls if imp.is_builtin(fullname) else None
301+
return cls if _imp.is_builtin(fullname) else None
292302

293303
@classmethod
294304
@set_package
@@ -298,7 +308,7 @@ def load_module(cls, fullname):
298308
"""Load a built-in module."""
299309
is_reload = fullname in sys.modules
300310
try:
301-
return imp.init_builtin(fullname)
311+
return _imp.init_builtin(fullname)
302312
except:
303313
if not is_reload and fullname in sys.modules:
304314
del sys.modules[fullname]
@@ -335,7 +345,7 @@ class FrozenImporter:
335345
@classmethod
336346
def find_module(cls, fullname, path=None):
337347
"""Find a frozen module."""
338-
return cls if imp.is_frozen(fullname) else None
348+
return cls if _imp.is_frozen(fullname) else None
339349

340350
@classmethod
341351
@set_package
@@ -345,7 +355,7 @@ def load_module(cls, fullname):
345355
"""Load a frozen module."""
346356
is_reload = fullname in sys.modules
347357
try:
348-
return imp.init_frozen(fullname)
358+
return _imp.init_frozen(fullname)
349359
except:
350360
if not is_reload and fullname in sys.modules:
351361
del sys.modules[fullname]
@@ -355,7 +365,7 @@ def load_module(cls, fullname):
355365
@_requires_frozen
356366
def get_code(cls, fullname):
357367
"""Return the code object for the frozen module."""
358-
return imp.get_frozen_object(fullname)
368+
return _imp.get_frozen_object(fullname)
359369

360370
@classmethod
361371
@_requires_frozen
@@ -367,7 +377,7 @@ def get_source(cls, fullname):
367377
@_requires_frozen
368378
def is_package(cls, fullname):
369379
"""Return if the frozen module is a package."""
370-
return imp.is_frozen_package(fullname)
380+
return _imp.is_frozen_package(fullname)
371381

372382

373383
class _LoaderBasics:
@@ -391,7 +401,7 @@ def _bytes_from_bytecode(self, fullname, data, bytecode_path, source_stats):
391401
magic = data[:4]
392402
raw_timestamp = data[4:8]
393403
raw_size = data[8:12]
394-
if len(magic) != 4 or magic != imp.get_magic():
404+
if len(magic) != 4 or magic != _imp.get_magic():
395405
raise ImportError("bad magic number in {}".format(fullname),
396406
name=fullname, path=bytecode_path)
397407
elif len(raw_timestamp) != 4:
@@ -434,7 +444,7 @@ def _load_module(self, module, *, sourceless=False):
434444
code_object = self.get_code(name)
435445
module.__file__ = self.get_filename(name)
436446
if not sourceless:
437-
module.__cached__ = imp.cache_from_source(module.__file__)
447+
module.__cached__ = _imp.cache_from_source(module.__file__)
438448
else:
439449
module.__cached__ = module.__file__
440450
module.__package__ = name
@@ -497,7 +507,7 @@ def get_code(self, fullname):
497507
498508
"""
499509
source_path = self.get_filename(fullname)
500-
bytecode_path = imp.cache_from_source(source_path)
510+
bytecode_path = _imp.cache_from_source(source_path)
501511
source_mtime = None
502512
if bytecode_path is not None:
503513
try:
@@ -522,7 +532,7 @@ def get_code(self, fullname):
522532
source_path)
523533
found = marshal.loads(bytes_data)
524534
if isinstance(found, code_type):
525-
imp._fix_co_filename(found, source_path)
535+
_imp._fix_co_filename(found, source_path)
526536
verbose_message('code object from {}',
527537
bytecode_path)
528538
return found
@@ -539,7 +549,7 @@ def get_code(self, fullname):
539549
# If e.g. Jython ever implements imp.cache_from_source to have
540550
# their own cached file format, this block of code will most likely
541551
# throw an exception.
542-
data = bytearray(imp.get_magic())
552+
data = bytearray(_imp.get_magic())
543553
data.extend(_w_long(source_mtime))
544554
data.extend(_w_long(len(source_bytes)))
545555
data.extend(marshal.dumps(code_object))
@@ -664,7 +674,7 @@ def load_module(self, fullname):
664674
"""Load an extension module."""
665675
is_reload = fullname in sys.modules
666676
try:
667-
module = imp.load_dynamic(fullname, self._path)
677+
module = _imp.load_dynamic(fullname, self._path)
668678
verbose_message('extension module loaded from {!r}', self._path)
669679
return module
670680
except:
@@ -841,15 +851,15 @@ class _SourceFinderDetails:
841851
supports_packages = True
842852

843853
def __init__(self):
844-
self.suffixes = _suffix_list(imp.PY_SOURCE)
854+
self.suffixes = _suffix_list(_imp.PY_SOURCE)
845855

846856
class _SourcelessFinderDetails:
847857

848858
loader = _SourcelessFileLoader
849859
supports_packages = True
850860

851861
def __init__(self):
852-
self.suffixes = _suffix_list(imp.PY_COMPILED)
862+
self.suffixes = _suffix_list(_imp.PY_COMPILED)
853863

854864

855865
class _ExtensionFinderDetails:
@@ -858,7 +868,7 @@ class _ExtensionFinderDetails:
858868
supports_packages = False
859869

860870
def __init__(self):
861-
self.suffixes = _suffix_list(imp.C_EXTENSION)
871+
self.suffixes = _suffix_list(_imp.C_EXTENSION)
862872

863873

864874
# Import itself ###############################################################
@@ -886,7 +896,7 @@ def _path_hooks(cls, path):
886896
try:
887897
return super()._path_hooks(path)
888898
except ImportError:
889-
implicit_hooks = [_DEFAULT_PATH_HOOK, imp.NullImporter]
899+
implicit_hooks = [_DEFAULT_PATH_HOOK, _imp.NullImporter]
890900
return super()._path_hooks(path, implicit_hooks)
891901

892902
@classmethod
@@ -902,11 +912,11 @@ class _ImportLockContext:
902912

903913
def __enter__(self):
904914
"""Acquire the import lock."""
905-
imp.acquire_lock()
915+
_imp.acquire_lock()
906916

907917
def __exit__(self, exc_type, exc_value, exc_traceback):
908918
"""Release the import lock regardless of any raised exceptions."""
909-
imp.release_lock()
919+
_imp.release_lock()
910920

911921

912922
def _resolve_name(name, package, level):
@@ -1092,19 +1102,19 @@ def __import__(name, globals={}, locals={}, fromlist=[], level=0):
10921102
return _handle_fromlist(module, fromlist, _gcd_import)
10931103

10941104

1095-
def _setup(sys_module, imp_module):
1105+
def _setup(sys_module, _imp_module):
10961106
"""Setup importlib by importing needed built-in modules and injecting them
10971107
into the global namespace.
10981108
1099-
As sys is needed for sys.modules access and imp is needed to load built-in
1109+
As sys is needed for sys.modules access and _imp is needed to load built-in
11001110
modules, those two modules must be explicitly passed in.
11011111
11021112
"""
1103-
global imp, sys
1104-
imp = imp_module
1113+
global _imp, sys
1114+
_imp = _imp_module
11051115
sys = sys_module
11061116

1107-
for module in (imp, sys):
1117+
for module in (_imp, sys):
11081118
if not hasattr(module, '__loader__'):
11091119
module.__loader__ = BuiltinImporter
11101120

@@ -1137,14 +1147,14 @@ def _setup(sys_module, imp_module):
11371147
setattr(self_module, '_relax_case', _make_relax_case())
11381148

11391149

1140-
def _install(sys_module, imp_module):
1150+
def _install(sys_module, _imp_module):
11411151
"""Install importlib as the implementation of import.
11421152
1143-
It is assumed that imp and sys have been imported and injected into the
1153+
It is assumed that _imp and sys have been imported and injected into the
11441154
global namespace for the module prior to calling this function.
11451155
11461156
"""
1147-
_setup(sys_module, imp_module)
1157+
_setup(sys_module, _imp_module)
11481158
orig_import = builtins.__import__
11491159
builtins.__import__ = __import__
11501160
builtins.__original_import__ = orig_import

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Core and Builtins
3232
Library
3333
-------
3434

35+
- Issue #13959: Add imp.py and rename the built-in module to _imp, allowing for
36+
re-implementing parts of the module in pure Python.
37+
3538
- Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied
3639
to a collection of size > sys.maxsize / 2.
3740

Modules/config.c.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ struct _inittab _PyImport_Inittab[] = {
3939
{"marshal", PyMarshal_Init},
4040

4141
/* This lives in import.c */
42-
{"imp", PyInit_imp},
42+
{"_imp", PyInit_imp},
4343

4444
/* This lives in Python/Python-ast.c */
4545
{"_ast", PyInit__ast},

PC/config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ struct _inittab _PyImport_Inittab[] = {
143143
{"marshal", PyMarshal_Init},
144144

145145
/* This lives it with import.c */
146-
{"imp", PyInit_imp},
146+
{"_imp", PyInit_imp},
147147

148148
/* These entries are here for sys.builtin_module_names */
149149
{"__main__", NULL},

PC/os2emx/config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ struct _inittab _PyImport_Inittab[] = {
150150
{"marshal", PyMarshal_Init},
151151

152152
/* This lives it with import.c */
153-
{"imp", initimp},
153+
{"_imp", initimp},
154154

155155
/* These entries are here for sys.builtin_module_names */
156156
{"__main__", NULL},

PC/os2vacpp/config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct _inittab _PyImport_Inittab[] = {
8888
{"marshal", PyMarshal_Init},
8989

9090
/* This lives it with import.c */
91-
{"imp", initimp},
91+
{"_imp", initimp},
9292

9393
/* These entries are here for sys.builtin_module_names */
9494
{"__main__", NULL},

Python/import.c

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3684,15 +3684,6 @@ imp_load_package(PyObject *self, PyObject *args)
36843684
return ret;
36853685
}
36863686

3687-
static PyObject *
3688-
imp_new_module(PyObject *self, PyObject *args)
3689-
{
3690-
PyObject *name;
3691-
if (!PyArg_ParseTuple(args, "U:new_module", &name))
3692-
return NULL;
3693-
return PyModule_NewObject(name);
3694-
}
3695-
36963687
static PyObject *
36973688
imp_reload(PyObject *self, PyObject *v)
36983689
{
@@ -3781,8 +3772,7 @@ does not conform to PEP 3147 format, ValueError will be raised.");
37813772
/* Doc strings */
37823773

37833774
PyDoc_STRVAR(doc_imp,
3784-
"This module provides the components needed to build your own\n\
3785-
__import__ function. Undocumented functions are obsolete.");
3775+
"(Extremely) low-level import machinery bits as used by importlib and imp.");
37863776

37873777
PyDoc_STRVAR(doc_find_module,
37883778
"find_module(name, [path]) -> (file, filename, (suffix, mode, type))\n\
@@ -3809,11 +3799,6 @@ PyDoc_STRVAR(doc_get_suffixes,
38093799
Return a list of (suffix, mode, type) tuples describing the files\n\
38103800
that find_module() looks for.");
38113801

3812-
PyDoc_STRVAR(doc_new_module,
3813-
"new_module(name) -> module\n\
3814-
Create a new module. Do not enter it in sys.modules.\n\
3815-
The module name must include the full package name, if any.");
3816-
38173802
PyDoc_STRVAR(doc_lock_held,
38183803
"lock_held() -> boolean\n\
38193804
Return True if the import lock is currently held, else False.\n\
@@ -3837,7 +3822,6 @@ static PyMethodDef imp_methods[] = {
38373822
{"get_tag", imp_get_tag, METH_NOARGS, doc_get_tag},
38383823
{"get_suffixes", imp_get_suffixes, METH_NOARGS, doc_get_suffixes},
38393824
{"load_module", imp_load_module, METH_VARARGS, doc_load_module},
3840-
{"new_module", imp_new_module, METH_VARARGS, doc_new_module},
38413825
{"lock_held", imp_lock_held, METH_NOARGS, doc_lock_held},
38423826
{"acquire_lock", imp_acquire_lock, METH_NOARGS, doc_acquire_lock},
38433827
{"release_lock", imp_release_lock, METH_NOARGS, doc_release_lock},
@@ -4005,7 +3989,7 @@ PyTypeObject PyNullImporter_Type = {
40053989

40063990
static struct PyModuleDef impmodule = {
40073991
PyModuleDef_HEAD_INIT,
4008-
"imp",
3992+
"_imp",
40093993
doc_imp,
40103994
0,
40113995
imp_methods,

0 commit comments

Comments
 (0)