Commit 5abdc93e authored by Brett Cannon's avatar Brett Cannon

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).
parent 7b3c89d8
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
......
......@@ -90,60 +90,17 @@ class closing:
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 @@ class BuiltinImporter(_BuiltinFrozenBaseLoader):
"""
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):
"""Meta path class for importing frozen modules."""
class FrozenImporter:
type_ = 'frozen'
"""Meta path class for importing frozen modules.
def __init__(self):
"""Specify the methods needed by the superclass.
All methods are either class or static method to allow direct use of the
class.
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
@classmethod
def find_module(cls, fullname, path=None):
"""Find a frozen module."""
return cls if imp.is_frozen(fullname) else None
def load_module(self, fullname):
@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 @@ class Import(object):
"""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
......
"""The machinery of importlib: finders, loaders, hooks, etc."""
from ._bootstrap import BuiltinImporter
from ._bootstrap import FrozenImporter
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):
......
import importlib
from importlib import machinery
from .. import support
import sys
......@@ -23,7 +24,7 @@ class LoaderTests(unittest.TestCase):
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.
......
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)
......
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__']}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment