Require __loader__ and __package__ to be set by loaders.

This commit is contained in:
Brett Cannon 2012-04-27 17:41:29 -04:00
parent d321dc54a4
commit 04fc727e6f
1 changed files with 18 additions and 22 deletions

View File

@ -273,25 +273,33 @@ Specification part 1: The Importer Protocol
be a list, but may be empty if __path__ has no further
significance to the importer (more on this later).
- It should add an __loader__ attribute to the module, set to the
loader object. This is mostly for introspection, but can be used
- The __loader__ attribute must be set to the loader object.
This is mostly for introspection and reloading, but can be used
for importer-specific extras, for example getting data associated
with an importer.
- The __package__ attribute [10] must be set.
If the module is a Python module (as opposed to a built-in module or
a dynamically loaded extension), it should execute the module's code
in the module's global name space (module.__dict__).
Here is a minimal pattern for a load_module() method:
# Consider using importlib.util.module_for_loader() to handle
# most of these details for you.
def load_module(self, fullname):
ispkg, code = self._get_code(fullname)
code = self.get_code(fullname)
ispkg = self.is_package(fullname)
mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
mod.__file__ = "<%s>" % self.__class__.__name__
mod.__loader__ = self
if ispkg:
mod.__path__ = []
exec code in mod.__dict__
mod.__package__ = fullname
else:
mod.__package__ = fullname.rpartition('.')[0]
exec(code, mod.__dict__)
return mod
@ -485,24 +493,9 @@ Open Issues
importer object, zipimport also adds an attribute "__loader__"
to the module, containing the zipimport object used to load the
module. If such an approach is used, it is important that client
code takes care not to break if the get_data method (or the
__loader__ attribute) is not available, so it is not clear that
this approach offers a general answer to the problem.
Requiring loaders to set the module's __loader__ attribute means
that the loader will not get thrown away once the load is complete.
This increases memory usage, and stops loaders from being
lightweight, "throwaway" objects. As loader objects are not
required to offer any useful functionality (any such functionality,
such as the zipimport get_data() method mentioned above, is
optional) it is not clear that the __loader__ attribute will be
helpful, in practice.
On the other hand, finder objects are mostly permanent, as they
live or are kept alive on sys.meta_path, sys.path_importer_cache, so
for a loader to keep a reference to the importer costs us nothing
extra. Whether loaders will ever need to carry so much independent
state for this to become a real issue is questionable.
code takes care not to break if the get_data method is not available,
so it is not clear that this approach offers a general answer to the
problem.
It was suggested on python-dev that it would be useful to be able to
receive a list of available modules from an importer and/or a list
@ -586,6 +579,9 @@ References and Footnotes
[9] PEP 338: Executing modules as scripts
http://www.python.org/dev/peps/pep-0338/
[10] PEP 366: Main module explicit relative imports
http://www.python.org/dev/peps/pep-0366/
Copyright