[PEP 451] Add namespace package support to example code and explain more about reloading.

This commit is contained in:
Eric Snow 2013-10-28 22:56:35 -06:00
parent 1db087f304
commit 88fe8028a0
1 changed files with 69 additions and 20 deletions

View File

@ -295,6 +295,8 @@ For loaders:
over its module execution functionality.
* importlib.abc.Loader.create_module(spec) (optional) will return the
module to use for loading.
* importlib.abc.Loader.supports_reload(name) (optional) will return True
(the default) if the loader supports reloading the module.
For modules:
@ -445,27 +447,31 @@ How Loading Will Work
Here is an outline of what the import machinery does during loading,
adjusted to take advantage of the module's spec and the new loader API::
module = None
if hasattr(spec.loader, 'create_module'):
module = spec.loader.create_module(spec)
if module is None:
module = ModuleType(spec.name)
# The import-related module attributes get set here:
_init_module_attrs(spec, module)
if not hasattr(spec.loader, 'exec_module'):
module = spec.loader.load_module(spec.name)
else:
sys.modules[spec.name] = module
try:
spec.loader.exec_module(module)
except BaseException:
try:
del sys.modules[spec.name]
except KeyError:
pass
raise
module_to_return = sys.modules[spec.name]
module = None
if spec.loader is not None and hasattr(spec.loader, 'create_module'):
module = spec.loader.create_module(spec)
if module is None:
module = ModuleType(spec.name)
# The import-related module attributes get set here:
_init_module_attrs(spec, module)
if spec.loader is None and spec.submodule_search_locations is not None:
# namespace package
sys.modules[spec.name] = module
elif not hasattr(spec.loader, 'exec_module'):
module = spec.loader.load_module(spec.name)
else:
sys.modules[spec.name] = module
try:
spec.loader.exec_module(module)
except BaseException:
try:
del sys.modules[spec.name]
except KeyError:
pass
raise
module_to_return = sys.modules[spec.name]
These steps are exactly what Loader.load_module() is already
expected to do. Loaders will thus be simplified since they will only
@ -479,6 +485,42 @@ import-related module attributes on the object. The module writer is on
their own if they are doing this.
How Reloading Will Work
=======================
Here is the corresponding outline for reload()::
_RELOADING = {}
def reload(module):
try:
name = module.__spec__.name
except AttributeError:
name = module.__name__
spec = find_spec(name)
if sys.modules.get(name) is not module:
raise ImportError
if spec in _RELOADING:
return _RELOADING[name]
_RELOADING[name] = module
try:
if spec.loader is None:
# namespace loader
_init_module_attrs(spec, module)
return module
if not spec.loader.supports_reload(name):
raise ImportError
if spec.parent and spec.parent not in sys.modules:
raise ImportError
_init_module_attrs(spec, module)
spec.loader.exec_module(module)
return sys.modules[name]
finally:
del _RELOADING[name]
ModuleSpec
==========
@ -749,6 +791,13 @@ raising ImportError.
module attributes. The fact that load_module() does is a design flaw
that this proposal aims to correct.
**Loader.supports_reload(name)**
In cases where a module should not be reloaded, Loaders should implement
supports_reload() and have it return False. If the method is defined
and returns a false value, importlib.reload() will raise an ImportError.
Otherwise reloading proceeds as normal.
Other changes:
PEP 420 introduced the optional module_repr() loader method to limit