mirror of https://github.com/python/cpython.git
Expose importlib.util.set___package__.
This commit is contained in:
parent
4d4975c0e4
commit
57b46f5b0e
|
@ -167,20 +167,28 @@ an :term:`importer`.
|
||||||
A :term:`decorator` for a :term:`loader` which handles selecting the proper
|
A :term:`decorator` for a :term:`loader` which handles selecting the proper
|
||||||
module object to load with. The decorated method is expected to have a call
|
module object to load with. The decorated method is expected to have a call
|
||||||
signature of ``method(self, module_object)`` for which the second argument
|
signature of ``method(self, module_object)`` for which the second argument
|
||||||
will be the module object to be used (note that the decorator will not work
|
will be the module object to be used by the loader (note that the decorator
|
||||||
on static methods because of the assumption of two arguments).
|
will not work on static methods because of the assumption of two
|
||||||
|
arguments).
|
||||||
|
|
||||||
The decorated method will take in the name of the module to be loaded as
|
The decorated method will take in the name of the module to be loaded as
|
||||||
normal. If the module is not found in :data:`sys.modules` then a new one is
|
expected for a :term:`loader`. If the module is not found in
|
||||||
constructed with its :attr:`__name__` attribute set. Otherwise the module
|
:data:`sys.modules` then a new one is constructed with its
|
||||||
found in :data:`sys.modules` will be passed into the method. If an
|
:attr:`__name__` attribute set. Otherwise the module found in
|
||||||
|
:data:`sys.modules` will be passed into the method. If an
|
||||||
exception is raised by the decorated method and a module was added to
|
exception is raised by the decorated method and a module was added to
|
||||||
:data:`sys.modules` it will be removed to prevent a partially initialized
|
:data:`sys.modules` it will be removed to prevent a partially initialized
|
||||||
module from being in left in :data:`sys.modules` If an exception is raised
|
module from being in left in :data:`sys.modules`. If the module was already
|
||||||
by the decorated method and a module was added to :data:`sys.modules` it
|
in :data:`sys.modules` then it is left alone.
|
||||||
will be removed to prevent a partially initialized module from being in
|
|
||||||
left in :data:`sys.modules`. If the module was already in
|
|
||||||
:data:`sys.modules` then it is left alone.
|
|
||||||
|
|
||||||
Use of this decorator handles all the details of what module a loader
|
Use of this decorator handles all the details of what module object a
|
||||||
should use as specified by :pep:`302`.
|
loader should initialize as specified by :pep:`302`.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: set___package__(method)
|
||||||
|
|
||||||
|
A :term:`decorator` for a :term:`loader` to set the :attr:`__package__`
|
||||||
|
attribute on the module returned by the loader. If :attr:`__package__` is
|
||||||
|
set and has a value other than :keyword:`None` it will not be changed.
|
||||||
|
Note that the module returned by the loader is what has the attribute
|
||||||
|
set on and not the module found in :data:`sys.modules`.
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
to do
|
to do
|
||||||
/////
|
/////
|
||||||
|
|
||||||
* Implement PEP 302 protocol for loaders (should just be a matter of testing).
|
|
||||||
|
|
||||||
+ Source/bytecode.
|
|
||||||
|
|
||||||
* Public API left to expose (w/ docs!)
|
* Public API left to expose (w/ docs!)
|
||||||
|
|
||||||
+ abc
|
+ abc
|
||||||
|
@ -27,27 +23,15 @@ to do
|
||||||
* get_code
|
* get_code
|
||||||
* get_source
|
* get_source
|
||||||
|
|
||||||
- (?) SourceLoader(ResourceLoader)
|
- PyLoader(ResourceLoader)
|
||||||
|
|
||||||
* source_path
|
* source_path
|
||||||
|
|
||||||
|
- PyPycLoader(PyLoader)
|
||||||
|
|
||||||
|
* source_mtime
|
||||||
* bytecode_path
|
* bytecode_path
|
||||||
* write_bytecode (not abstract)
|
* write_bytecode
|
||||||
|
|
||||||
+ util
|
|
||||||
|
|
||||||
- set___package__ decorator
|
|
||||||
|
|
||||||
+ machinery
|
|
||||||
|
|
||||||
- Extensions importers
|
|
||||||
|
|
||||||
* ExtensionFinder
|
|
||||||
* (?) Loader
|
|
||||||
|
|
||||||
- Source/bytecode importers
|
|
||||||
|
|
||||||
* SourceFinder
|
|
||||||
* (?) Loader
|
|
||||||
|
|
||||||
+ test (Really want to worry about compatibility with future versions?)
|
+ test (Really want to worry about compatibility with future versions?)
|
||||||
|
|
||||||
|
|
|
@ -60,9 +60,58 @@ def test_reload_failure(self):
|
||||||
self.assert_(sys.modules[name] is module)
|
self.assert_(sys.modules[name] is module)
|
||||||
|
|
||||||
|
|
||||||
|
class SetPackageTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
||||||
|
"""Tests for importlib.util.set___package__."""
|
||||||
|
|
||||||
|
def verify(self, module, expect):
|
||||||
|
"""Verify the module has the expected value for __package__ after
|
||||||
|
passing through set___package__."""
|
||||||
|
fxn = lambda: module
|
||||||
|
wrapped = util.set___package__(fxn)
|
||||||
|
wrapped()
|
||||||
|
self.assert_(hasattr(module, '__package__'))
|
||||||
|
self.assertEqual(expect, module.__package__)
|
||||||
|
|
||||||
|
def test_top_level(self):
|
||||||
|
# __package__ should be set to the empty string if a top-level module.
|
||||||
|
# Implicitly tests when package is set to None.
|
||||||
|
module = imp.new_module('module')
|
||||||
|
module.__package__ = None
|
||||||
|
self.verify(module, '')
|
||||||
|
|
||||||
|
def test_package(self):
|
||||||
|
# Test setting __package__ for a package.
|
||||||
|
module = imp.new_module('pkg')
|
||||||
|
module.__path__ = ['<path>']
|
||||||
|
module.__package__ = None
|
||||||
|
self.verify(module, 'pkg')
|
||||||
|
|
||||||
|
def test_submodule(self):
|
||||||
|
# Test __package__ for a module in a package.
|
||||||
|
module = imp.new_module('pkg.mod')
|
||||||
|
module.__package__ = None
|
||||||
|
self.verify(module, 'pkg')
|
||||||
|
|
||||||
|
def test_setting_if_missing(self):
|
||||||
|
# __package__ should be set if it is missing.
|
||||||
|
module = imp.new_module('mod')
|
||||||
|
if hasattr(module, '__package__'):
|
||||||
|
delattr(module, '__package__')
|
||||||
|
self.verify(module, '')
|
||||||
|
|
||||||
|
def test_leaving_alone(self):
|
||||||
|
# If __package__ is set and not None then leave it alone.
|
||||||
|
for value in (True, False):
|
||||||
|
module = imp.new_module('mod')
|
||||||
|
module.__package__ = value
|
||||||
|
self.verify(module, value)
|
||||||
|
|
||||||
|
|
||||||
def test_main():
|
def test_main():
|
||||||
from test import support
|
from test import support
|
||||||
support.run_unittest(ModuleForLoaderTests)
|
support.run_unittest(ModuleForLoaderTests, SetPackageTests)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
"""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___package__
|
||||||
|
|
Loading…
Reference in New Issue