Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d2476c6

Browse files
committed
Issue #19698: Remove exec_module() from the built-in and extension
module loaders. Due to the fact that the call signatures for extension modules and built-in modules does not allow for the specifying of what module to initialize and that on Windows all extension modules are built-in modules, work to clean up built-in and extension module initialization will have to wait until Python 3.5. Because of this the semantics of exec_module() would be incorrect, so removing the methods for now is the best option; load_module() is still used as a fallback by importlib and so this won't affect semantics.
1 parent 0e90e99 commit d2476c6

5 files changed

Lines changed: 4234 additions & 4324 deletions

File tree

Lib/importlib/_bootstrap.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,24 @@ def _new_module(name):
133133
_code_type = type(_wrap.__code__)
134134

135135

136+
137+
class _ManageReload:
138+
139+
"""Manages the possible clean-up of sys.modules for load_module()."""
140+
141+
def __init__(self, name):
142+
self._name = name
143+
144+
def __enter__(self):
145+
self._is_reload = self._name in sys.modules
146+
147+
def __exit__(self, *args):
148+
if any(arg is not None for arg in args) and not self._is_reload:
149+
try:
150+
del sys.modules[self._name]
151+
except KeyError:
152+
pass
153+
136154
# Module-level locking ########################################################
137155

138156
# A dict mapping module names to weakrefs of _ModuleLock instances
@@ -1242,23 +1260,15 @@ def find_module(cls, fullname, path=None):
12421260
spec = cls.find_spec(fullname, path)
12431261
return spec.loader if spec is not None else None
12441262

1245-
@staticmethod
1246-
def exec_module(module):
1247-
spec = module.__spec__
1248-
name = spec.name
1249-
if not _imp.is_builtin(name):
1250-
raise ImportError('{!r} is not a built-in module'.format(name),
1251-
name=name)
1252-
_call_with_frames_removed(_imp.init_builtin, name)
1253-
# Have to manually initialize attributes since init_builtin() is not
1254-
# going to do it for us.
1255-
# XXX: Create _imp.exec_builtin(module)
1256-
_SpecMethods(spec).init_module_attrs(sys.modules[name])
1257-
12581263
@classmethod
1264+
@_requires_builtin
12591265
def load_module(cls, fullname):
12601266
"""Load a built-in module."""
1261-
return _load_module_shim(cls, fullname)
1267+
with _ManageReload(fullname):
1268+
module = _call_with_frames_removed(_imp.init_builtin, fullname)
1269+
module.__loader__ = cls
1270+
module.__package__ = ''
1271+
return module
12621272

12631273
@classmethod
12641274
@_requires_builtin
@@ -1639,22 +1649,21 @@ def __init__(self, name, path):
16391649
self.name = name
16401650
self.path = path
16411651

1642-
def exec_module(self, module):
1643-
# XXX create _imp.exec_dynamic()
1644-
spec = module.__spec__
1645-
fullname = spec.name
1646-
module = _call_with_frames_removed(_imp.load_dynamic,
1647-
fullname, self.path)
1648-
_verbose_message('extension module loaded from {!r}', self.path)
1649-
if self.is_package(fullname) and not hasattr(module, '__path__'):
1650-
module.__path__ = [_path_split(self.path)[0]]
1651-
_SpecMethods(spec).init_module_attrs(module)
1652-
1653-
# XXX deprecate
16541652
@_check_name
16551653
def load_module(self, fullname):
16561654
"""Load an extension module."""
1657-
return _load_module_shim(self, fullname)
1655+
with _ManageReload(fullname):
1656+
module = _call_with_frames_removed(_imp.load_dynamic,
1657+
fullname, self.path)
1658+
_verbose_message('extension module loaded from {!r}', self.path)
1659+
is_package = self.is_package(fullname)
1660+
if is_package and not hasattr(module, '__path__'):
1661+
module.__path__ = [_path_split(self.path)[0]]
1662+
module.__loader__ = self
1663+
module.__package__ = module.__name__
1664+
if not is_package:
1665+
module.__package__ = module.__package__.rpartition('.')[0]
1666+
return module
16581667

16591668
def is_package(self, fullname):
16601669
"""Return True if the extension module is a package."""

Lib/test/test_importlib/builtin/test_loader.py

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -9,78 +9,6 @@
99
import unittest
1010

1111

12-
class ExecModTests(abc.LoaderTests):
13-
14-
"""Test exec_module() for built-in modules."""
15-
16-
@classmethod
17-
def setUpClass(cls):
18-
cls.verification = {'__name__': 'errno', '__package__': '',
19-
'__loader__': cls.machinery.BuiltinImporter}
20-
21-
def verify(self, module):
22-
"""Verify that the module matches against what it should have."""
23-
self.assertIsInstance(module, types.ModuleType)
24-
for attr, value in self.verification.items():
25-
self.assertEqual(getattr(module, attr), value)
26-
self.assertIn(module.__name__, sys.modules)
27-
self.assertTrue(hasattr(module, '__spec__'))
28-
self.assertEqual(module.__spec__.origin, 'built-in')
29-
30-
def load_spec(self, name):
31-
spec = self.machinery.ModuleSpec(name, self.machinery.BuiltinImporter,
32-
origin='built-in')
33-
module = types.ModuleType(name)
34-
module.__spec__ = spec
35-
self.machinery.BuiltinImporter.exec_module(module)
36-
# Strictly not what exec_module() is supposed to do, but since
37-
# _imp.init_builtin() does this we can't get around it.
38-
return sys.modules[name]
39-
40-
def test_module(self):
41-
# Common case.
42-
with util.uncache(builtin_util.NAME):
43-
module = self.load_spec(builtin_util.NAME)
44-
self.verify(module)
45-
self.assertIn('built-in', str(module))
46-
47-
# Built-in modules cannot be a package.
48-
test_package = None
49-
50-
# Built-in modules cannot be a package.
51-
test_lacking_parent = None
52-
53-
# Not way to force an import failure.
54-
test_state_after_failure = None
55-
56-
def test_unloadable(self):
57-
name = 'dssdsdfff'
58-
assert name not in sys.builtin_module_names
59-
with self.assertRaises(ImportError) as cm:
60-
self.load_spec(name)
61-
self.assertEqual(cm.exception.name, name)
62-
63-
def test_already_imported(self):
64-
# Using the name of a module already imported but not a built-in should
65-
# still fail.
66-
module_name = 'builtin_reload_test'
67-
assert module_name not in sys.builtin_module_names
68-
with util.uncache(module_name):
69-
module = types.ModuleType(module_name)
70-
spec = self.machinery.ModuleSpec(module_name,
71-
self.machinery.BuiltinImporter,
72-
origin='built-in')
73-
module.__spec__ = spec
74-
sys.modules[module_name] = module
75-
with self.assertRaises(ImportError) as cm:
76-
self.machinery.BuiltinImporter.exec_module(module)
77-
self.assertEqual(cm.exception.name, module_name)
78-
79-
80-
Frozen_ExecModTests, Source_ExecModTests = util.test_both(ExecModTests,
81-
machinery=[frozen_machinery, source_machinery])
82-
83-
8412
class LoaderTests(abc.LoaderTests):
8513

8614
"""Test load_module() for built-in modules."""

Lib/test/test_importlib/extension/test_loader.py

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -10,71 +10,6 @@
1010
import unittest
1111

1212

13-
class ExecModuleTests(abc.LoaderTests):
14-
15-
"""Test load_module() for extension modules."""
16-
17-
def setUp(self):
18-
self.loader = self.machinery.ExtensionFileLoader(ext_util.NAME,
19-
ext_util.FILEPATH)
20-
21-
def exec_module(self, fullname):
22-
module = types.ModuleType(fullname)
23-
module.__spec__ = self.machinery.ModuleSpec(fullname, self.loader)
24-
self.loader.exec_module(module)
25-
return sys.modules[fullname]
26-
27-
def test_exec_module_API(self):
28-
with self.assertRaises(ImportError):
29-
self.exec_module('XXX')
30-
31-
32-
def test_module(self):
33-
with util.uncache(ext_util.NAME):
34-
module = self.exec_module(ext_util.NAME)
35-
for attr, value in [('__name__', ext_util.NAME),
36-
('__file__', ext_util.FILEPATH),
37-
('__package__', '')]:
38-
given = getattr(module, attr)
39-
self.assertEqual(given, value,
40-
'{}: {!r} != {!r}'.format(attr, given, value))
41-
self.assertIn(ext_util.NAME, sys.modules)
42-
self.assertIsInstance(module.__loader__,
43-
self.machinery.ExtensionFileLoader)
44-
45-
# No extension module as __init__ available for testing.
46-
test_package = None
47-
48-
# No extension module in a package available for testing.
49-
test_lacking_parent = None
50-
51-
def test_module_reuse(self):
52-
with util.uncache(ext_util.NAME):
53-
module1 = self.exec_module(ext_util.NAME)
54-
module2 = self.exec_module(ext_util.NAME)
55-
self.assertIs(module1, module2)
56-
57-
def test_state_after_failure(self):
58-
# No easy way to trigger a failure after a successful import.
59-
pass
60-
61-
def test_unloadable(self):
62-
name = 'asdfjkl;'
63-
with self.assertRaises(ImportError) as cm:
64-
self.exec_module(name)
65-
self.assertEqual(cm.exception.name, name)
66-
67-
def test_is_package(self):
68-
self.assertFalse(self.loader.is_package(ext_util.NAME))
69-
for suffix in self.machinery.EXTENSION_SUFFIXES:
70-
path = os.path.join('some', 'path', 'pkg', '__init__' + suffix)
71-
loader = self.machinery.ExtensionFileLoader('pkg', path)
72-
self.assertTrue(loader.is_package('pkg'))
73-
74-
Frozen_ExecModuleTests, Source_ExecModuleTests = util.test_both(
75-
ExecModuleTests, machinery=machinery)
76-
77-
7813
class LoaderTests(abc.LoaderTests):
7914

8015
"""Test load_module() for extension modules."""

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Core and Builtins
1818
Library
1919
-------
2020

21+
- Issue #19698: Removed exec_module() methods from
22+
importlib.machinery.BuiltinImporter and ExtensionFileLoader.
23+
2124
- ssl.create_default_context() sets OP_NO_COMPRESSION to prevent CRIME.
2225

2326
- Issue #19802: Add socket.SO_PRIORITY.

0 commit comments

Comments
 (0)