]> granicus.if.org Git - python/commitdiff
Implement InspectLoader for BuiltinImporter.
authorBrett Cannon <bcannon@gmail.com>
Sun, 15 Mar 2009 01:41:33 +0000 (01:41 +0000)
committerBrett Cannon <bcannon@gmail.com>
Sun, 15 Mar 2009 01:41:33 +0000 (01:41 +0000)
Doc/library/importlib.rst
Lib/importlib/NOTES
Lib/importlib/_bootstrap.py
Lib/importlib/abc.py
Lib/importlib/test/builtin/test_finder.py
Lib/importlib/test/builtin/test_loader.py
Lib/importlib/test/builtin/util.py [new file with mode: 0644]

index 3b2a288fa22791780d9521e1be99c8e47b6ac990..92fb7875de1f803c2fc00f99aac5637cc9a6c84b 100644 (file)
@@ -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.
index 2220a166d82e2f206dec8c2430d1a8a7a7519a77..44cfc09bd632a4014e512e8c85bd4bc0a98e44d0 100644 (file)
@@ -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.
 
index e94c1d2ddd1f6d34ba20c88203a703c843c88e31..736e1b6665ed0b86657c9d11bce25beabec7b0e8 100644 (file)
@@ -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:
 
index 6b00569ef17cf3a40a22e1240e251bb6615c2e61..c9c542ad1fa7f1515b0ca3c5fb842d9aaa31e33e 100644 (file)
@@ -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):
 
index eacc36c27a5ac5d192bdcd2322f3131595ad8991..ef8e8fe67ab526d99f571d284a814c2fa1eac766 100644 (file)
@@ -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)
 
 
index 8a69d049ff1f2b03036f4d21e82d3dda42c7ddcf..cfedb5d3c7fdcd284b2e4a073c26fef9d6e6248b 100644 (file)
@@ -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__':
diff --git a/Lib/importlib/test/builtin/util.py b/Lib/importlib/test/builtin/util.py
new file mode 100644 (file)
index 0000000..5704699
--- /dev/null
@@ -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'