mirror of
https://github.com/python/cpython.git
synced 2025-10-09 08:31:26 +00:00
Implement importlib.util.set_loader: a decorator to automatically set
__loader__ on modules.
This commit is contained in:
parent
d43b30b046
commit
2cf03a8204
7 changed files with 34 additions and 12 deletions
|
@ -348,7 +348,15 @@ an :term:`importer`.
|
||||||
loader should initialize as specified by :pep:`302`.
|
loader should initialize as specified by :pep:`302`.
|
||||||
|
|
||||||
|
|
||||||
.. function:: set_package(method)
|
.. function:: set_loader(fxn)
|
||||||
|
|
||||||
|
A :term:`decorator` for a :term:`loader` to set the :attr:`__loader__`
|
||||||
|
attribute on loaded modules. If the attribute is already set the decorator
|
||||||
|
does nothing. It is assumed that the first positional argument to the
|
||||||
|
wrapped method is what :attr:`__loader__` should be set to.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: set_package(fxn)
|
||||||
|
|
||||||
A :term:`decorator` for a :term:`loader` to set the :attr:`__package__`
|
A :term:`decorator` for a :term:`loader` to set the :attr:`__package__`
|
||||||
attribute on the module returned by the loader. If :attr:`__package__` is
|
attribute on the module returned by the loader. If :attr:`__package__` is
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
to do
|
to do
|
||||||
/////
|
/////
|
||||||
|
|
||||||
* Public API left to expose (w/ docs!)
|
|
||||||
|
|
||||||
+ util.set_loader
|
|
||||||
|
|
||||||
* Implement InspectLoader for BuiltinImporter and FrozenImporter.
|
* Implement InspectLoader for BuiltinImporter and FrozenImporter.
|
||||||
|
|
||||||
+ Expose function to see if a frozen module is a package.
|
+ Expose function to see if a frozen module is a package.
|
||||||
|
|
|
@ -110,6 +110,17 @@ def set_package(fxn):
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def set_loader(fxn):
|
||||||
|
"""Set __loader__ on the returned module."""
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
module = fxn(self, *args, **kwargs)
|
||||||
|
if not hasattr(module, '__loader__'):
|
||||||
|
module.__loader__ = self
|
||||||
|
return module
|
||||||
|
wrap(wrapper, fxn)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class BuiltinImporter:
|
class BuiltinImporter:
|
||||||
|
|
||||||
"""Meta path loader for built-in modules.
|
"""Meta path loader for built-in modules.
|
||||||
|
@ -132,6 +143,7 @@ class BuiltinImporter:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@set_package
|
@set_package
|
||||||
|
@set_loader
|
||||||
def load_module(cls, fullname):
|
def load_module(cls, fullname):
|
||||||
"""Load a built-in module."""
|
"""Load a built-in module."""
|
||||||
if fullname not in sys.builtin_module_names:
|
if fullname not in sys.builtin_module_names:
|
||||||
|
@ -161,6 +173,7 @@ class FrozenImporter:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@set_package
|
@set_package
|
||||||
|
@set_loader
|
||||||
def load_module(cls, fullname):
|
def load_module(cls, fullname):
|
||||||
"""Load a frozen module."""
|
"""Load a frozen module."""
|
||||||
if cls.find_module(fullname) is None:
|
if cls.find_module(fullname) is None:
|
||||||
|
@ -249,13 +262,12 @@ class _ExtensionFileLoader:
|
||||||
|
|
||||||
@check_name
|
@check_name
|
||||||
@set_package
|
@set_package
|
||||||
|
@set_loader
|
||||||
def load_module(self, fullname):
|
def load_module(self, fullname):
|
||||||
"""Load an extension module."""
|
"""Load an extension module."""
|
||||||
is_reload = fullname in sys.modules
|
is_reload = fullname in sys.modules
|
||||||
try:
|
try:
|
||||||
module = imp.load_dynamic(fullname, self._path)
|
return imp.load_dynamic(fullname, self._path)
|
||||||
module.__loader__ = self
|
|
||||||
return module
|
|
||||||
except:
|
except:
|
||||||
if not is_reload and fullname in sys.modules:
|
if not is_reload and fullname in sys.modules:
|
||||||
del sys.modules[fullname]
|
del sys.modules[fullname]
|
||||||
|
|
|
@ -15,7 +15,8 @@ class LoaderTests(abc.LoaderTests):
|
||||||
assert 'errno' in sys.builtin_module_names
|
assert 'errno' in sys.builtin_module_names
|
||||||
name = 'errno'
|
name = 'errno'
|
||||||
|
|
||||||
verification = {'__name__': 'errno', '__package__': ''}
|
verification = {'__name__': 'errno', '__package__': '',
|
||||||
|
'__loader__': machinery.BuiltinImporter}
|
||||||
|
|
||||||
def verify(self, module):
|
def verify(self, module):
|
||||||
"""Verify that the module matches against what it should have."""
|
"""Verify that the module matches against what it should have."""
|
||||||
|
|
|
@ -24,6 +24,8 @@ class LoaderTests(abc.LoaderTests):
|
||||||
('__package__', '')]:
|
('__package__', '')]:
|
||||||
self.assertEqual(getattr(module, attr), value)
|
self.assertEqual(getattr(module, attr), value)
|
||||||
self.assert_(ext_util.NAME in sys.modules)
|
self.assert_(ext_util.NAME in sys.modules)
|
||||||
|
self.assert_(isinstance(module.__loader__,
|
||||||
|
importlib._ExtensionFileLoader))
|
||||||
|
|
||||||
def test_package(self):
|
def test_package(self):
|
||||||
# Extensions are not found in packages.
|
# Extensions are not found in packages.
|
||||||
|
|
|
@ -9,7 +9,7 @@ class LoaderTests(abc.LoaderTests):
|
||||||
with util.uncache('__hello__'):
|
with util.uncache('__hello__'):
|
||||||
module = machinery.FrozenImporter.load_module('__hello__')
|
module = machinery.FrozenImporter.load_module('__hello__')
|
||||||
check = {'__name__': '__hello__', '__file__': '<frozen>',
|
check = {'__name__': '__hello__', '__file__': '<frozen>',
|
||||||
'__package__': ''}
|
'__package__': '', '__loader__': machinery.FrozenImporter}
|
||||||
for attr, value in check.items():
|
for attr, value in check.items():
|
||||||
self.assertEqual(getattr(module, attr), value)
|
self.assertEqual(getattr(module, attr), value)
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@ class LoaderTests(abc.LoaderTests):
|
||||||
with util.uncache('__phello__'):
|
with util.uncache('__phello__'):
|
||||||
module = machinery.FrozenImporter.load_module('__phello__')
|
module = machinery.FrozenImporter.load_module('__phello__')
|
||||||
check = {'__name__': '__phello__', '__file__': '<frozen>',
|
check = {'__name__': '__phello__', '__file__': '<frozen>',
|
||||||
'__package__': '__phello__', '__path__': ['__phello__']}
|
'__package__': '__phello__', '__path__': ['__phello__'],
|
||||||
|
'__loader__': machinery.FrozenImporter}
|
||||||
for attr, value in check.items():
|
for attr, value in check.items():
|
||||||
attr_value = getattr(module, attr)
|
attr_value = getattr(module, attr)
|
||||||
self.assertEqual(attr_value, value,
|
self.assertEqual(attr_value, value,
|
||||||
|
@ -28,7 +29,8 @@ class LoaderTests(abc.LoaderTests):
|
||||||
with util.uncache('__phello__', '__phello__.spam'):
|
with util.uncache('__phello__', '__phello__.spam'):
|
||||||
module = machinery.FrozenImporter.load_module('__phello__.spam')
|
module = machinery.FrozenImporter.load_module('__phello__.spam')
|
||||||
check = {'__name__': '__phello__.spam', '__file__': '<frozen>',
|
check = {'__name__': '__phello__.spam', '__file__': '<frozen>',
|
||||||
'__package__': '__phello__'}
|
'__package__': '__phello__',
|
||||||
|
'__loader__': machinery.FrozenImporter}
|
||||||
for attr, value in check.items():
|
for attr, value in check.items():
|
||||||
attr_value = getattr(module, attr)
|
attr_value = getattr(module, attr)
|
||||||
self.assertEqual(attr_value, value,
|
self.assertEqual(attr_value, value,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
"""Utility code for constructing importers, etc."""
|
"""Utility code for constructing importers, etc."""
|
||||||
from ._bootstrap import module_for_loader
|
from ._bootstrap import module_for_loader
|
||||||
|
from ._bootstrap import set_loader
|
||||||
from ._bootstrap import set_package
|
from ._bootstrap import set_package
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue