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

Skip to content

Commit 2cf03a8

Browse files
committed
Implement importlib.util.set_loader: a decorator to automatically set
__loader__ on modules.
1 parent d43b30b commit 2cf03a8

7 files changed

Lines changed: 34 additions & 12 deletions

File tree

Doc/library/importlib.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,15 @@ an :term:`importer`.
348348
loader should initialize as specified by :pep:`302`.
349349

350350

351-
.. function:: set_package(method)
351+
.. function:: set_loader(fxn)
352+
353+
A :term:`decorator` for a :term:`loader` to set the :attr:`__loader__`
354+
attribute on loaded modules. If the attribute is already set the decorator
355+
does nothing. It is assumed that the first positional argument to the
356+
wrapped method is what :attr:`__loader__` should be set to.
357+
358+
359+
.. function:: set_package(fxn)
352360

353361
A :term:`decorator` for a :term:`loader` to set the :attr:`__package__`
354362
attribute on the module returned by the loader. If :attr:`__package__` is

Lib/importlib/NOTES

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
to do
22
/////
33

4-
* Public API left to expose (w/ docs!)
5-
6-
+ util.set_loader
7-
84
* Implement InspectLoader for BuiltinImporter and FrozenImporter.
95

106
+ Expose function to see if a frozen module is a package.

Lib/importlib/_bootstrap.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ def wrapper(*args, **kwargs):
110110
return wrapper
111111

112112

113+
def set_loader(fxn):
114+
"""Set __loader__ on the returned module."""
115+
def wrapper(self, *args, **kwargs):
116+
module = fxn(self, *args, **kwargs)
117+
if not hasattr(module, '__loader__'):
118+
module.__loader__ = self
119+
return module
120+
wrap(wrapper, fxn)
121+
return wrapper
122+
123+
113124
class BuiltinImporter:
114125

115126
"""Meta path loader for built-in modules.
@@ -132,6 +143,7 @@ def find_module(cls, fullname, path=None):
132143

133144
@classmethod
134145
@set_package
146+
@set_loader
135147
def load_module(cls, fullname):
136148
"""Load a built-in module."""
137149
if fullname not in sys.builtin_module_names:
@@ -161,6 +173,7 @@ def find_module(cls, fullname, path=None):
161173

162174
@classmethod
163175
@set_package
176+
@set_loader
164177
def load_module(cls, fullname):
165178
"""Load a frozen module."""
166179
if cls.find_module(fullname) is None:
@@ -249,13 +262,12 @@ def __init__(self, name, path, is_pkg):
249262

250263
@check_name
251264
@set_package
265+
@set_loader
252266
def load_module(self, fullname):
253267
"""Load an extension module."""
254268
is_reload = fullname in sys.modules
255269
try:
256-
module = imp.load_dynamic(fullname, self._path)
257-
module.__loader__ = self
258-
return module
270+
return imp.load_dynamic(fullname, self._path)
259271
except:
260272
if not is_reload and fullname in sys.modules:
261273
del sys.modules[fullname]

Lib/importlib/test/builtin/test_loader.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ class LoaderTests(abc.LoaderTests):
1515
assert 'errno' in sys.builtin_module_names
1616
name = 'errno'
1717

18-
verification = {'__name__': 'errno', '__package__': ''}
18+
verification = {'__name__': 'errno', '__package__': '',
19+
'__loader__': machinery.BuiltinImporter}
1920

2021
def verify(self, module):
2122
"""Verify that the module matches against what it should have."""

Lib/importlib/test/extension/test_loader.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ def test_module(self):
2424
('__package__', '')]:
2525
self.assertEqual(getattr(module, attr), value)
2626
self.assert_(ext_util.NAME in sys.modules)
27+
self.assert_(isinstance(module.__loader__,
28+
importlib._ExtensionFileLoader))
2729

2830
def test_package(self):
2931
# Extensions are not found in packages.

Lib/importlib/test/frozen/test_loader.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ def test_module(self):
99
with util.uncache('__hello__'):
1010
module = machinery.FrozenImporter.load_module('__hello__')
1111
check = {'__name__': '__hello__', '__file__': '<frozen>',
12-
'__package__': ''}
12+
'__package__': '', '__loader__': machinery.FrozenImporter}
1313
for attr, value in check.items():
1414
self.assertEqual(getattr(module, attr), value)
1515

1616
def test_package(self):
1717
with util.uncache('__phello__'):
1818
module = machinery.FrozenImporter.load_module('__phello__')
1919
check = {'__name__': '__phello__', '__file__': '<frozen>',
20-
'__package__': '__phello__', '__path__': ['__phello__']}
20+
'__package__': '__phello__', '__path__': ['__phello__'],
21+
'__loader__': machinery.FrozenImporter}
2122
for attr, value in check.items():
2223
attr_value = getattr(module, attr)
2324
self.assertEqual(attr_value, value,
@@ -28,7 +29,8 @@ def test_lacking_parent(self):
2829
with util.uncache('__phello__', '__phello__.spam'):
2930
module = machinery.FrozenImporter.load_module('__phello__.spam')
3031
check = {'__name__': '__phello__.spam', '__file__': '<frozen>',
31-
'__package__': '__phello__'}
32+
'__package__': '__phello__',
33+
'__loader__': machinery.FrozenImporter}
3234
for attr, value in check.items():
3335
attr_value = getattr(module, attr)
3436
self.assertEqual(attr_value, value,

Lib/importlib/util.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
"""Utility code for constructing importers, etc."""
22
from ._bootstrap import module_for_loader
3+
from ._bootstrap import set_loader
34
from ._bootstrap import set_package

0 commit comments

Comments
 (0)