From c9ba4a97561c92f464cd49f0f5fb7f6634f421c5 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Sat, 26 Oct 2013 18:30:41 -0600 Subject: [PATCH] [PEP 451] Updates in response to the latest feedback. This includes removing the remaining ModuleSpec methods and de-emphasizing that find_spec() returns actual ModuleSpec instances. --- pep-0451.txt | 73 ++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/pep-0451.txt b/pep-0451.txt index 3d1b41604..93b19e9fa 100644 --- a/pep-0451.txt +++ b/pep-0451.txt @@ -240,8 +240,8 @@ detail is available in later sections. importlib.machinery.ModuleSpec (new) ------------------------------------ -A specification for a module's import-system-related state. See the -`ModuleSpec`_ section below for a more detailed description. +An encapsulation of a module's import-system-related state during import. +See the `ModuleSpec`_ section below for a more detailed description. * ModuleSpec(name, loader, \*, origin=None, loader_state=None, is_package=None) @@ -263,13 +263,6 @@ Attributes: * has_location (RO-property) - a flag indicating whether or not the module's "origin" attribute refers to a location. -Instance Methods: - -* module_repr() - provide a repr string for the spec'ed module; - non-locatable modules will use their origin (e.g. "built-in"). -* init_module_attrs(module) - set any of a module's import-related - attributes that aren't already set. - importlib.util Additions ------------------------ @@ -289,6 +282,12 @@ Other API Additions importlib.find_loader() (which it replaces), but return a spec instead of a loader. +For finders: + +* importlib.abc.MetaPathFinder.find_spec(name, path) and + importlib.abc.PathEntryFinder.find_spec(name) will return a module + spec to use during import. + For loaders: * importlib.abc.Loader.exec_module(module) will execute a module in its @@ -443,34 +442,30 @@ factory functions nor any the instance methods. How Loading Will Work ===================== -Here is an outline of what ModuleSpec does during loading:: +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:: - def load(self): - if not hasattr(self.loader, 'exec_module'): - module = self.loader.load_module(self.name) - self.init_module_attrs(module) - return sys.modules[self.name] + 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(module) - module = None - if hasattr(self.loader, 'create_module'): - module = self.loader.create_module(self) - if module is None: - module = ModuleType(self.name) - self.init_module_attrs(module) - - sys.modules[self.name] = module + if not hasattr(spec.loader, 'exec_module'): + module = spec.loader.load_module(spec.name) + else: + sys.modules[spec.name] = module try: - self.loader.exec_module(module) + spec.loader.exec_module(module) except BaseException: try: - del sys.modules[self.name] + del sys.modules[spec.name] except KeyError: pass raise - return sys.modules[self.name] - -Note: no "load" method is actually implemented as part of the public -ModuleSpec API. + 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 @@ -494,8 +489,8 @@ Each of the following names is an attribute on ModuleSpec objects. A value of None indicates "not set". This contrasts with module objects where the attribute simply doesn't exist. Most of the attributes correspond to the import-related attributes of modules. Here -is the mapping. The reverse of this mapping is used by -ModuleSpec.init_module_attrs(). +is the mapping. The reverse of this mapping describes how the import +machinery sets the module attributes right before calling exec_module(). ========================== ============== On ModuleSpec On Modules @@ -523,7 +518,7 @@ involve changing the state of a module's spec. "origin" is a string for the name of the place from which the module originates. See `origin`_ above. Aside from the informational value, -it is also used in module_repr(). In the case of a spec where +it is also used in the module's repr. In the case of a spec where "has_location" is true, ``__file__`` is set to the value of "origin". For built-in modules "origin" would be set to "built-in". @@ -655,7 +650,7 @@ Simply setting loader_state or adding functionality to a custom finder or loader will likely be a better fit and should be tried first. However, as long as a subclass still fulfills the requirements of the import system, objects of that type are completely fine as the return -value of Finder.find_spec(). +value of Finder.find_spec(). The same points apply to duck-typing. Existing Types @@ -695,7 +690,7 @@ the cost until later. **PathEntryFinder.find_spec(name)** -Finders will return ModuleSpec objects when find_spec() is +Finders must return ModuleSpec objects when find_spec() is called. This new method replaces find_module() and find_loader() (in the PathEntryFinder case). If a loader does not have find_spec(), find_module() and find_loader() are @@ -715,8 +710,9 @@ Currently a path entry finder may return (None, portions) from find_loader() to indicate it found part of a possible namespace package. To achieve the same effect, find_spec() must return a spec with "loader" set to None (a.k.a. not set) and with -submodule_search_locations set to the same portions as were provided by -find_loader(). It's up to PathFinder how to handle such specs. +submodule_search_locations set to the same portions as would have been +provided by find_loader(). It's up to PathFinder how to handle such +specs. Loaders ------- @@ -777,6 +773,11 @@ Other Changes * The various finders and loaders provided by importlib will be updated to comply with this proposal. +* Any other implmentations of or dependencies on the import-related APIs + (particularly finders and loaders) in the stdlib will be likewise + adjusted to this PEP. While they should continue to work, any such + changes that get missed should be considered bugs for the Python 3.4.x + series. * The spec for the ``__main__`` module will reflect how the interpreter was started. For instance, with ``-m`` the spec's name will be that of the run module, while ``__main__.__name__`` will still be