mirror of https://github.com/python/cpython
Implement InspectLoader for BuiltinImporter.
This commit is contained in:
parent
7aa21f75c1
commit
a113ac58be
|
@ -175,11 +175,12 @@ are also provided to help in implementing the core ABCs.
|
|||
An abstract base class for a :term:`loader` which implements the optional
|
||||
:pep:`302` protocol for loaders which inspect modules.
|
||||
|
||||
.. method:: is_package(fullname)
|
||||
.. method:: get_code(fullname)
|
||||
|
||||
An abstract method to return a true value if the module is a package, a
|
||||
false value otherwise. :exc:`ImportError` is raised if the
|
||||
:term:`loader` cannot find the module.
|
||||
An abstract method to return the :class:`code` object for a module.
|
||||
:keyword:`None` is returned if the module does not have a code object
|
||||
(e.g. built-in module). :exc:`ImportError` is raised if loader cannot
|
||||
find the requested module.
|
||||
|
||||
.. method:: get_source(fullname)
|
||||
|
||||
|
@ -188,12 +189,11 @@ are also provided to help in implementing the core ABCs.
|
|||
source is available (e.g. a built-in module). Raises :exc:`ImportError`
|
||||
if the loader cannot find the module specified.
|
||||
|
||||
.. method:: get_code(fullname)
|
||||
.. method:: is_package(fullname)
|
||||
|
||||
An abstract method to return the :class:`code` object for a module.
|
||||
:keyword:`None` is returned if the module does not have a code object
|
||||
(e.g. built-in module). :exc:`ImportError` is raised if loader cannot
|
||||
find the requested module.
|
||||
An abstract method to return a true value if the module is a package, a
|
||||
false value otherwise. :exc:`ImportError` is raised if the
|
||||
:term:`loader` cannot find the module.
|
||||
|
||||
|
||||
.. class:: PyLoader
|
||||
|
@ -274,7 +274,8 @@ find and load modules.
|
|||
|
||||
An :term:`importer` for built-in modules. All known built-in modules are
|
||||
listed in :data:`sys.builtin_module_names`. This class implements the
|
||||
:class:`importlib.abc.Finder` and :class:`importlib.abc.Loader` ABCs.
|
||||
:class:`importlib.abc.Finder` and :class:`importlib.abc.InspectLoader`
|
||||
ABCs.
|
||||
|
||||
Only class methods are defined by this class to alleviate the need for
|
||||
instantiation.
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
to do
|
||||
/////
|
||||
|
||||
* Fill in docstrings for ABCs.
|
||||
|
||||
* Implement InspectLoader for BuiltinImporter and FrozenImporter.
|
||||
* Implement InspectLoader for FrozenImporter.
|
||||
|
||||
+ Expose function to see if a frozen module is a package.
|
||||
|
||||
|
|
|
@ -173,6 +173,16 @@ def _check_name(method):
|
|||
return inner
|
||||
|
||||
|
||||
def _requires_builtin(fxn):
|
||||
"""Decorator to verify the named module is built-in."""
|
||||
def wrapper(self, fullname):
|
||||
if fullname not in sys.builtin_module_names:
|
||||
raise ImportError("{0} is not a built-in module".format(fullname))
|
||||
return fxn(self, fullname)
|
||||
_wrap(wrapper, fxn)
|
||||
return wrapper
|
||||
|
||||
|
||||
def _suffix_list(suffix_type):
|
||||
"""Return a list of file suffixes based on the imp file type."""
|
||||
return [suffix[0] for suffix in imp.get_suffixes()
|
||||
|
@ -204,10 +214,9 @@ class BuiltinImporter:
|
|||
@classmethod
|
||||
@set_package
|
||||
@set_loader
|
||||
@_requires_builtin
|
||||
def load_module(cls, 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))
|
||||
is_reload = fullname in sys.modules
|
||||
try:
|
||||
return imp.init_builtin(fullname)
|
||||
|
@ -216,6 +225,24 @@ class BuiltinImporter:
|
|||
del sys.modules[fullname]
|
||||
raise
|
||||
|
||||
@classmethod
|
||||
@_requires_builtin
|
||||
def get_code(cls, fullname):
|
||||
"""Return None as built-in modules do not have code objects."""
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
@_requires_builtin
|
||||
def get_source(cls, fullname):
|
||||
"""Return None as built-in modules do not have source code."""
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
@_requires_builtin
|
||||
def is_package(cls, fullname):
|
||||
"""Return None as built-in module are never packages."""
|
||||
return False
|
||||
|
||||
|
||||
class FrozenImporter:
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ class Loader(metaclass=abc.ABCMeta):
|
|||
"""Abstract method which when implemented should load a module."""
|
||||
raise NotImplementedError
|
||||
|
||||
Loader.register(machinery.BuiltinImporter)
|
||||
Loader.register(machinery.FrozenImporter)
|
||||
|
||||
|
||||
|
@ -75,6 +74,8 @@ class InspectLoader(Loader):
|
|||
module."""
|
||||
return NotImplementedError
|
||||
|
||||
InspectLoader.register(machinery.BuiltinImporter)
|
||||
|
||||
|
||||
class PyLoader(_bootstrap.PyLoader, InspectLoader):
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from importlib import machinery
|
||||
from .. import abc
|
||||
from .. import util
|
||||
from . import util as builtin_util
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
@ -9,13 +10,11 @@ class FinderTests(abc.FinderTests):
|
|||
|
||||
"""Test find_module() for built-in modules."""
|
||||
|
||||
assert 'errno' in sys.builtin_module_names
|
||||
name = 'errno'
|
||||
|
||||
def test_module(self):
|
||||
# Common case.
|
||||
with util.uncache(self.name):
|
||||
self.assert_(machinery.BuiltinImporter.find_module(self.name))
|
||||
with util.uncache(builtin_util.NAME):
|
||||
found = machinery.BuiltinImporter.find_module(builtin_util.NAME)
|
||||
self.assert_(found)
|
||||
|
||||
def test_package(self):
|
||||
# Built-in modules cannot be a package.
|
||||
|
@ -40,8 +39,9 @@ class FinderTests(abc.FinderTests):
|
|||
|
||||
def test_ignore_path(self):
|
||||
# The value for 'path' should always trigger a failed import.
|
||||
with util.uncache(self.name):
|
||||
loader = machinery.BuiltinImporter.find_module(self.name, ['pkg'])
|
||||
with util.uncache(builtin_util.NAME):
|
||||
loader = machinery.BuiltinImporter.find_module(builtin_util.NAME,
|
||||
['pkg'])
|
||||
self.assert_(loader is None)
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import importlib
|
|||
from importlib import machinery
|
||||
from .. import abc
|
||||
from .. import util
|
||||
from . import util as builtin_util
|
||||
|
||||
import sys
|
||||
import types
|
||||
|
@ -12,9 +13,6 @@ class LoaderTests(abc.LoaderTests):
|
|||
|
||||
"""Test load_module() for built-in modules."""
|
||||
|
||||
assert 'errno' in sys.builtin_module_names
|
||||
name = 'errno'
|
||||
|
||||
verification = {'__name__': 'errno', '__package__': '',
|
||||
'__loader__': machinery.BuiltinImporter}
|
||||
|
||||
|
@ -30,8 +28,8 @@ class LoaderTests(abc.LoaderTests):
|
|||
|
||||
def test_module(self):
|
||||
# Common case.
|
||||
with util.uncache(self.name):
|
||||
module = self.load_module(self.name)
|
||||
with util.uncache(builtin_util.NAME):
|
||||
module = self.load_module(builtin_util.NAME)
|
||||
self.verify(module)
|
||||
|
||||
def test_package(self):
|
||||
|
@ -48,9 +46,9 @@ class LoaderTests(abc.LoaderTests):
|
|||
|
||||
def test_module_reuse(self):
|
||||
# Test that the same module is used in a reload.
|
||||
with util.uncache(self.name):
|
||||
module1 = self.load_module(self.name)
|
||||
module2 = self.load_module(self.name)
|
||||
with util.uncache(builtin_util.NAME):
|
||||
module1 = self.load_module(builtin_util.NAME)
|
||||
module2 = self.load_module(builtin_util.NAME)
|
||||
self.assert_(module1 is module2)
|
||||
|
||||
def test_unloadable(self):
|
||||
|
@ -65,9 +63,36 @@ class LoaderTests(abc.LoaderTests):
|
|||
self.assertRaises(ImportError, self.load_module, 'importlib')
|
||||
|
||||
|
||||
class InspectLoaderTests(unittest.TestCase):
|
||||
|
||||
"""Tests for InspectLoader methods for BuiltinImporter."""
|
||||
|
||||
def test_get_code(self):
|
||||
# There is no code object.
|
||||
result = machinery.BuiltinImporter.get_code(builtin_util.NAME)
|
||||
self.assert_(result is None)
|
||||
|
||||
def test_get_source(self):
|
||||
# There is no source.
|
||||
result = machinery.BuiltinImporter.get_source(builtin_util.NAME)
|
||||
self.assert_(result is None)
|
||||
|
||||
def test_is_package(self):
|
||||
# Cannot be a package.
|
||||
result = machinery.BuiltinImporter.is_package(builtin_util.NAME)
|
||||
self.assert_(not result)
|
||||
|
||||
def test_not_builtin(self):
|
||||
# Modules not built-in should raise ImportError.
|
||||
for meth_name in ('get_code', 'get_source', 'is_package'):
|
||||
method = getattr(machinery.BuiltinImporter, meth_name)
|
||||
self.assertRaises(ImportError, method, builtin_util.BAD_NAME)
|
||||
|
||||
|
||||
|
||||
def test_main():
|
||||
from test.support import run_unittest
|
||||
run_unittest(LoaderTests)
|
||||
run_unittest(LoaderTests, InspectLoaderTests)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import sys
|
||||
|
||||
assert 'errno' in sys.builtin_module_names
|
||||
NAME = 'errno'
|
||||
|
||||
assert 'importlib' not in sys.builtin_module_names
|
||||
BAD_NAME = 'importlib'
|
Loading…
Reference in New Issue