mirror of https://github.com/python/cpython.git
Add importlib.machinery with its first tenants, BuitinImporter and
FrozenImporter. Docs forthcoming. I plan on all finders and loaders (and most likely hooks) to live in imoprtlib.machinery. Utility stuff will end up in importlib.util. Higher-level API stuff will stay on imoprtlib directly (e.g. import_module).
This commit is contained in:
parent
7b3c89d88c
commit
5abdc93eb8
|
@ -1,9 +1,16 @@
|
||||||
to do
|
to do
|
||||||
/////
|
/////
|
||||||
|
|
||||||
|
* Document:
|
||||||
|
|
||||||
|
+ The terms "importer", "finder", and "loader".
|
||||||
|
+ machinery.BuiltinImporter.
|
||||||
|
+ machinery.FrozenImporter.
|
||||||
|
|
||||||
* Expose resolve_name().
|
* Expose resolve_name().
|
||||||
|
|
||||||
* Backport to Python 2.7.
|
* Backport to Python 2.7.
|
||||||
|
|
||||||
+ import_module
|
+ import_module
|
||||||
+ resolve_name
|
+ resolve_name
|
||||||
|
|
||||||
|
@ -11,9 +18,11 @@ to do
|
||||||
that various implementations can just subclass as needed.
|
that various implementations can just subclass as needed.
|
||||||
|
|
||||||
* Expose built-in and frozen importers.
|
* Expose built-in and frozen importers.
|
||||||
|
|
||||||
+ Make staticmethods so that class can be used directly.
|
+ Make staticmethods so that class can be used directly.
|
||||||
|
|
||||||
* Reorganize support code.
|
* Reorganize support code.
|
||||||
|
|
||||||
+ Separate general support code and importer-specific (e.g. source) support
|
+ Separate general support code and importer-specific (e.g. source) support
|
||||||
code.
|
code.
|
||||||
- Create support modules for each subdirectory (as needed).
|
- Create support modules for each subdirectory (as needed).
|
||||||
|
@ -22,12 +31,14 @@ to do
|
||||||
- Use in source/test_load_module_mixed.
|
- Use in source/test_load_module_mixed.
|
||||||
|
|
||||||
* API simplification?
|
* API simplification?
|
||||||
|
|
||||||
+ read_source -> get_data/source_path
|
+ read_source -> get_data/source_path
|
||||||
+ read_bytecode -> get_data/bytecode_path
|
+ read_bytecode -> get_data/bytecode_path
|
||||||
+ write_bytecode -> complete set of bytes for bytecode instead of
|
+ write_bytecode -> complete set of bytes for bytecode instead of
|
||||||
individual arguments.
|
individual arguments.
|
||||||
|
|
||||||
* Implement PEP 302 protocol for loaders (should just be a matter of testing).
|
* Implement PEP 302 protocol for loaders (should just be a matter of testing).
|
||||||
|
|
||||||
+ Built-in.
|
+ Built-in.
|
||||||
+ Frozen.
|
+ Frozen.
|
||||||
+ Extension.
|
+ Extension.
|
||||||
|
@ -36,39 +47,59 @@ to do
|
||||||
* Create meta_path importer for sys.path.
|
* Create meta_path importer for sys.path.
|
||||||
|
|
||||||
* OPTIMIZE!
|
* OPTIMIZE!
|
||||||
|
|
||||||
+ Write benchmark suite.
|
+ Write benchmark suite.
|
||||||
+ Fast path common cases.
|
+ Fast path common cases.
|
||||||
|
|
||||||
- Absolute name from sys.path.
|
- Absolute name from sys.path.
|
||||||
- Relative name from sys.path.
|
- Relative name from sys.path.
|
||||||
|
|
||||||
* Public API to expose (w/ docs!)
|
* Public API to expose (w/ docs!)
|
||||||
|
|
||||||
+ abc
|
+ abc
|
||||||
|
|
||||||
- Finder
|
- Finder
|
||||||
|
|
||||||
* find_module
|
* find_module
|
||||||
|
|
||||||
- Loader
|
- Loader
|
||||||
|
|
||||||
* load_module
|
* load_module
|
||||||
|
|
||||||
- ResourceLoader(Loader)
|
- ResourceLoader(Loader)
|
||||||
|
|
||||||
* get_data
|
* get_data
|
||||||
|
|
||||||
- InspectLoader(Loader)
|
- InspectLoader(Loader)
|
||||||
|
|
||||||
* is_package
|
* is_package
|
||||||
* get_code
|
* get_code
|
||||||
* get_source
|
* get_source
|
||||||
|
|
||||||
- (?) SourceLoader(ResourceLoader)
|
- (?) SourceLoader(ResourceLoader)
|
||||||
|
|
||||||
* source_path
|
* source_path
|
||||||
* bytecode_path
|
* bytecode_path
|
||||||
* write_bytecode
|
* write_bytecode
|
||||||
|
|
||||||
+ util
|
+ util
|
||||||
|
|
||||||
- get_module decorator (new name)
|
- get_module decorator (new name)
|
||||||
- check_name decorator (new name)
|
- check_name decorator (new name)
|
||||||
+ hooks (?)
|
|
||||||
|
+ machinery
|
||||||
|
|
||||||
- (?) Chained path hook/finder
|
- (?) Chained path hook/finder
|
||||||
- BuiltinImporter
|
- BuiltinImporter
|
||||||
- FrozenImporter
|
- FrozenImporter
|
||||||
- (?) FileFinder
|
- (?) FileFinder
|
||||||
- Extensions importers
|
- Extensions importers
|
||||||
|
|
||||||
* ExtensionFinder
|
* ExtensionFinder
|
||||||
* (?) Loader
|
* (?) Loader
|
||||||
|
|
||||||
- Source/bytecode importers
|
- Source/bytecode importers
|
||||||
|
|
||||||
* SourceFinder
|
* SourceFinder
|
||||||
* (?) Loader
|
* (?) Loader
|
||||||
|
|
||||||
|
|
|
@ -90,60 +90,17 @@ def __exit__(self, *args):
|
||||||
self.obj.close()
|
self.obj.close()
|
||||||
|
|
||||||
|
|
||||||
class _BuiltinFrozenBaseLoader(object):
|
class BuiltinImporter:
|
||||||
|
|
||||||
"""Base class for meta_path loaders for built-in and frozen modules.
|
"""Meta path loader for built-in modules.
|
||||||
|
|
||||||
Subclasses must implement:
|
All methods are either class or static methods, allowing direct use of the
|
||||||
|
class.
|
||||||
* _find(fullname:str) -> bool
|
|
||||||
Finder which returns whether the class can handle the module.
|
|
||||||
|
|
||||||
* _load(fullname:str) -> module
|
|
||||||
Loader which returns the loaded module. The check for sys.modules
|
|
||||||
does not need to be handled by this method.
|
|
||||||
|
|
||||||
* type_:str
|
|
||||||
Name of the type of module being handled. Used in error messages.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def find_module(self, fullname, path=None):
|
@classmethod
|
||||||
"""Find a module."""
|
def find_module(cls, fullname, path=None):
|
||||||
if not self._find(fullname):
|
|
||||||
return None
|
|
||||||
return self
|
|
||||||
|
|
||||||
def load_module(self, fullname):
|
|
||||||
"""Load a module."""
|
|
||||||
try:
|
|
||||||
return sys.modules[fullname]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
mod = self._load(fullname)
|
|
||||||
if not mod:
|
|
||||||
raise ImportError("expected {0} module not "
|
|
||||||
"loaded".format(self.type_))
|
|
||||||
return mod
|
|
||||||
|
|
||||||
|
|
||||||
class BuiltinImporter(_BuiltinFrozenBaseLoader):
|
|
||||||
|
|
||||||
"""Meta path loader for built-in modules."""
|
|
||||||
|
|
||||||
type_ = "built-in"
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
"""Set the methods needed by the class.
|
|
||||||
|
|
||||||
Cannot be set at the class level because the imp module is not
|
|
||||||
necessarily injected until after the class is created.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._find = imp.is_builtin
|
|
||||||
self._load = imp.init_builtin
|
|
||||||
|
|
||||||
def find_module(self, fullname, path=None):
|
|
||||||
"""Try to find the built-in module.
|
"""Try to find the built-in module.
|
||||||
|
|
||||||
If 'path' is ever specified then the search is considered a failure.
|
If 'path' is ever specified then the search is considered a failure.
|
||||||
|
@ -151,36 +108,36 @@ def find_module(self, fullname, path=None):
|
||||||
"""
|
"""
|
||||||
if path is not None:
|
if path is not None:
|
||||||
return None
|
return None
|
||||||
return super().find_module(fullname, path)
|
return cls if imp.is_builtin(fullname) else None
|
||||||
|
|
||||||
def load_module(self, fullname):
|
@staticmethod
|
||||||
|
def load_module(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:
|
||||||
raise ImportError("{0} is not a built-in module".format(fullname))
|
raise ImportError("{0} is not a built-in module".format(fullname))
|
||||||
return super().load_module(fullname)
|
return imp.init_builtin(fullname)
|
||||||
|
|
||||||
|
|
||||||
class FrozenImporter(_BuiltinFrozenBaseLoader):
|
class FrozenImporter:
|
||||||
|
|
||||||
"""Meta path class for importing frozen modules."""
|
"""Meta path class for importing frozen modules.
|
||||||
|
|
||||||
type_ = 'frozen'
|
All methods are either class or static method to allow direct use of the
|
||||||
|
class.
|
||||||
def __init__(self):
|
|
||||||
"""Specify the methods needed by the superclass.
|
|
||||||
|
|
||||||
Because imp may not be injected until after class creation these
|
|
||||||
methods cannot be set at the class level.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._find = imp.is_frozen
|
|
||||||
self._load = imp.init_frozen
|
|
||||||
|
|
||||||
def load_module(self, fullname):
|
@classmethod
|
||||||
|
def find_module(cls, fullname, path=None):
|
||||||
|
"""Find a frozen module."""
|
||||||
|
return cls if imp.is_frozen(fullname) else None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def load_module(cls, fullname):
|
||||||
"""Load a frozen module."""
|
"""Load a frozen module."""
|
||||||
if not self.find_module(fullname):
|
if cls.find_module(fullname) is None:
|
||||||
raise ImportError("{0} is not a frozen module".format(fullname))
|
raise ImportError("{0} is not a frozen module".format(fullname))
|
||||||
return super().load_module(fullname)
|
return imp.init_frozen(fullname)
|
||||||
|
|
||||||
|
|
||||||
class ChainedImporter(object):
|
class ChainedImporter(object):
|
||||||
|
@ -707,7 +664,7 @@ def __init__(self, default_path_hook=None,
|
||||||
"""Store a default path hook entry and a sequence to internally extend
|
"""Store a default path hook entry and a sequence to internally extend
|
||||||
sys.meta_path by (passing in None uses default importers)."""
|
sys.meta_path by (passing in None uses default importers)."""
|
||||||
if extended_meta_path is None:
|
if extended_meta_path is None:
|
||||||
self.extended_meta_path = BuiltinImporter(), FrozenImporter()
|
self.extended_meta_path = BuiltinImporter, FrozenImporter
|
||||||
else:
|
else:
|
||||||
self.extended_meta_path = extended_meta_path
|
self.extended_meta_path = extended_meta_path
|
||||||
self.default_path_hook = default_path_hook
|
self.default_path_hook = default_path_hook
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
"""The machinery of importlib: finders, loaders, hooks, etc."""
|
||||||
|
|
||||||
|
from ._bootstrap import BuiltinImporter
|
||||||
|
from ._bootstrap import FrozenImporter
|
|
@ -1,4 +1,4 @@
|
||||||
import importlib
|
from importlib import machinery
|
||||||
from .. import support
|
from .. import support
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
@ -12,7 +12,7 @@ class FinderTests(unittest.TestCase):
|
||||||
name = 'errno'
|
name = 'errno'
|
||||||
|
|
||||||
find_module = staticmethod(lambda name, path=None:
|
find_module = staticmethod(lambda name, path=None:
|
||||||
importlib.BuiltinImporter().find_module(name, path))
|
machinery.BuiltinImporter.find_module(name, path))
|
||||||
|
|
||||||
|
|
||||||
def test_find_module(self):
|
def test_find_module(self):
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import importlib
|
import importlib
|
||||||
|
from importlib import machinery
|
||||||
from .. import support
|
from .. import support
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
@ -23,7 +24,7 @@ def verify(self, module):
|
||||||
self.assert_(module.__name__ in sys.modules)
|
self.assert_(module.__name__ in sys.modules)
|
||||||
|
|
||||||
load_module = staticmethod(lambda name:
|
load_module = staticmethod(lambda name:
|
||||||
importlib.BuiltinImporter().load_module(name))
|
machinery.BuiltinImporter.load_module(name))
|
||||||
|
|
||||||
def test_load_module(self):
|
def test_load_module(self):
|
||||||
# Common case.
|
# Common case.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import importlib
|
from importlib import machinery
|
||||||
from ..builtin import test_finder
|
from ..builtin import test_finder
|
||||||
from .. import support
|
from .. import support
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ class FinderTests(test_finder.FinderTests):
|
||||||
"""Test finding frozen modules."""
|
"""Test finding frozen modules."""
|
||||||
|
|
||||||
def find(self, name, path=None):
|
def find(self, name, path=None):
|
||||||
finder = importlib.FrozenImporter()
|
finder = machinery.FrozenImporter
|
||||||
return finder.find_module(name, path)
|
return finder.find_module(name, path)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import importlib
|
from importlib import machinery
|
||||||
from ..builtin import test_loader
|
from ..builtin import test_loader
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ class LoaderTests(test_loader.LoaderTests):
|
||||||
|
|
||||||
name = '__phello__'
|
name = '__phello__'
|
||||||
load_module = staticmethod(lambda name:
|
load_module = staticmethod(lambda name:
|
||||||
importlib.FrozenImporter().load_module(name))
|
machinery.FrozenImporter.load_module(name))
|
||||||
verification = {'__name__': '__phello__', '__file__': '<frozen>',
|
verification = {'__name__': '__phello__', '__file__': '<frozen>',
|
||||||
'__package__': None, '__path__': ['__phello__']}
|
'__package__': None, '__path__': ['__phello__']}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue