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:
Brett Cannon 2009-01-22 22:43:07 +00:00
parent 7b3c89d88c
commit 5abdc93eb8
7 changed files with 68 additions and 75 deletions

View File

@ -1,9 +1,16 @@
to do
/////
* Document:
+ The terms "importer", "finder", and "loader".
+ machinery.BuiltinImporter.
+ machinery.FrozenImporter.
* Expose resolve_name().
* Backport to Python 2.7.
+ import_module
+ resolve_name
@ -11,9 +18,11 @@ to do
that various implementations can just subclass as needed.
* Expose built-in and frozen importers.
+ Make staticmethods so that class can be used directly.
* Reorganize support code.
+ Separate general support code and importer-specific (e.g. source) support
code.
- Create support modules for each subdirectory (as needed).
@ -22,12 +31,14 @@ to do
- Use in source/test_load_module_mixed.
* API simplification?
+ read_source -> get_data/source_path
+ read_bytecode -> get_data/bytecode_path
+ write_bytecode -> complete set of bytes for bytecode instead of
individual arguments.
* Implement PEP 302 protocol for loaders (should just be a matter of testing).
+ Built-in.
+ Frozen.
+ Extension.
@ -36,39 +47,59 @@ to do
* Create meta_path importer for sys.path.
* OPTIMIZE!
+ Write benchmark suite.
+ Fast path common cases.
- Absolute name from sys.path.
- Relative name from sys.path.
* Public API to expose (w/ docs!)
+ abc
- Finder
* find_module
- Loader
* load_module
- ResourceLoader(Loader)
* get_data
- InspectLoader(Loader)
* is_package
* get_code
* get_source
- (?) SourceLoader(ResourceLoader)
* source_path
* bytecode_path
* write_bytecode
+ util
- get_module decorator (new name)
- check_name decorator (new name)
+ hooks (?)
+ machinery
- (?) Chained path hook/finder
- BuiltinImporter
- FrozenImporter
- (?) FileFinder
- Extensions importers
* ExtensionFinder
* (?) Loader
- Source/bytecode importers
* SourceFinder
* (?) Loader

View File

@ -90,60 +90,17 @@ def __exit__(self, *args):
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:
* _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.
All methods are either class or static methods, allowing direct use of the
class.
"""
def find_module(self, fullname, path=None):
"""Find a module."""
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):
@classmethod
def find_module(cls, fullname, path=None):
"""Try to find the built-in module.
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:
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."""
if fullname not in sys.builtin_module_names:
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'
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.
All methods are either class or static method to allow direct use of the
class.
"""
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."""
if not self.find_module(fullname):
if cls.find_module(fullname) is None:
raise ImportError("{0} is not a frozen module".format(fullname))
return super().load_module(fullname)
return imp.init_frozen(fullname)
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
sys.meta_path by (passing in None uses default importers)."""
if extended_meta_path is None:
self.extended_meta_path = BuiltinImporter(), FrozenImporter()
self.extended_meta_path = BuiltinImporter, FrozenImporter
else:
self.extended_meta_path = extended_meta_path
self.default_path_hook = default_path_hook

View File

@ -0,0 +1,4 @@
"""The machinery of importlib: finders, loaders, hooks, etc."""
from ._bootstrap import BuiltinImporter
from ._bootstrap import FrozenImporter

View File

@ -1,4 +1,4 @@
import importlib
from importlib import machinery
from .. import support
import sys
@ -12,7 +12,7 @@ class FinderTests(unittest.TestCase):
name = 'errno'
find_module = staticmethod(lambda name, path=None:
importlib.BuiltinImporter().find_module(name, path))
machinery.BuiltinImporter.find_module(name, path))
def test_find_module(self):

View File

@ -1,4 +1,5 @@
import importlib
from importlib import machinery
from .. import support
import sys
@ -23,7 +24,7 @@ def verify(self, module):
self.assert_(module.__name__ in sys.modules)
load_module = staticmethod(lambda name:
importlib.BuiltinImporter().load_module(name))
machinery.BuiltinImporter.load_module(name))
def test_load_module(self):
# Common case.

View File

@ -1,4 +1,4 @@
import importlib
from importlib import machinery
from ..builtin import test_finder
from .. import support
@ -10,7 +10,7 @@ class FinderTests(test_finder.FinderTests):
"""Test finding frozen modules."""
def find(self, name, path=None):
finder = importlib.FrozenImporter()
finder = machinery.FrozenImporter
return finder.find_module(name, path)

View File

@ -1,4 +1,4 @@
import importlib
from importlib import machinery
from ..builtin import test_loader
@ -6,7 +6,7 @@ class LoaderTests(test_loader.LoaderTests):
name = '__phello__'
load_module = staticmethod(lambda name:
importlib.FrozenImporter().load_module(name))
machinery.FrozenImporter.load_module(name))
verification = {'__name__': '__phello__', '__file__': '<frozen>',
'__package__': None, '__path__': ['__phello__']}