]> granicus.if.org Git - python/commitdiff
Implement importlib.util.set_loader: a decorator to automatically set
authorBrett Cannon <bcannon@gmail.com>
Tue, 10 Mar 2009 05:17:37 +0000 (05:17 +0000)
committerBrett Cannon <bcannon@gmail.com>
Tue, 10 Mar 2009 05:17:37 +0000 (05:17 +0000)
__loader__ on modules.

Doc/library/importlib.rst
Lib/importlib/NOTES
Lib/importlib/_bootstrap.py
Lib/importlib/test/builtin/test_loader.py
Lib/importlib/test/extension/test_loader.py
Lib/importlib/test/frozen/test_loader.py
Lib/importlib/util.py

index c1874f6af5916b89504cb4bb88a30ddebeac0b95..4610b575dd2ef34e01e4ae80a4c3e64844ad38dc 100644 (file)
@@ -348,7 +348,15 @@ an :term:`importer`.
     loader should initialize as specified by :pep:`302`.
 
 
-.. function:: set_package(method)
+.. function:: set_loader(fxn)
+
+    A :term:`decorator` for a :term:`loader` to set the :attr:`__loader__`
+    attribute on loaded modules. If the attribute is already set the decorator
+    does nothing. It is assumed that the first positional argument to the
+    wrapped method is what :attr:`__loader__` should be set to.
+
+
+.. function:: set_package(fxn)
 
     A :term:`decorator` for a :term:`loader` to set the :attr:`__package__`
     attribute on the module returned by the loader. If :attr:`__package__` is
index f7384197fc1a5ed7ef1db8e511a7f23ad10bfc8c..8d05a16494c619b45a5e9fbc58c5df87094c0f1b 100644 (file)
@@ -1,10 +1,6 @@
 to do
 /////
 
-* Public API left to expose (w/ docs!)
-
-    + util.set_loader
-
 * Implement InspectLoader for BuiltinImporter and FrozenImporter.
 
     + Expose function to see if a frozen module is a package.
index 73f651384b1be2bb128bedffb49b1bf42870bc50..1b460062e0d20ac24f83f879472d5e7ca8c5e2fc 100644 (file)
@@ -110,6 +110,17 @@ def set_package(fxn):
     return wrapper
 
 
+def set_loader(fxn):
+    """Set __loader__ on the returned module."""
+    def wrapper(self, *args, **kwargs):
+        module = fxn(self, *args, **kwargs)
+        if not hasattr(module, '__loader__'):
+            module.__loader__ = self
+        return module
+    wrap(wrapper, fxn)
+    return wrapper
+
+
 class BuiltinImporter:
 
     """Meta path loader for built-in modules.
@@ -132,6 +143,7 @@ class BuiltinImporter:
 
     @classmethod
     @set_package
+    @set_loader
     def load_module(cls, fullname):
         """Load a built-in module."""
         if fullname not in sys.builtin_module_names:
@@ -161,6 +173,7 @@ class FrozenImporter:
 
     @classmethod
     @set_package
+    @set_loader
     def load_module(cls, fullname):
         """Load a frozen module."""
         if cls.find_module(fullname) is None:
@@ -249,13 +262,12 @@ class _ExtensionFileLoader:
 
     @check_name
     @set_package
+    @set_loader
     def load_module(self, fullname):
         """Load an extension module."""
         is_reload = fullname in sys.modules
         try:
-            module = imp.load_dynamic(fullname, self._path)
-            module.__loader__ = self
-            return module
+            return imp.load_dynamic(fullname, self._path)
         except:
             if not is_reload and fullname in sys.modules:
                 del sys.modules[fullname]
index 117196075659acaf765fb3d1e8313e62f47bd5ee..8a69d049ff1f2b03036f4d21e82d3dda42c7ddcf 100644 (file)
@@ -15,7 +15,8 @@ class LoaderTests(abc.LoaderTests):
     assert 'errno' in sys.builtin_module_names
     name = 'errno'
 
-    verification = {'__name__': 'errno', '__package__': ''}
+    verification = {'__name__': 'errno', '__package__': '',
+                    '__loader__': machinery.BuiltinImporter}
 
     def verify(self, module):
         """Verify that the module matches against what it should have."""
index ca9f2a7caf6c13005ee375fe362c8124a3fefdf8..f961a630812c8f7db01d478fb6df7d9ffc3c474e 100644 (file)
@@ -24,6 +24,8 @@ class LoaderTests(abc.LoaderTests):
                                 ('__package__', '')]:
                 self.assertEqual(getattr(module, attr), value)
             self.assert_(ext_util.NAME in sys.modules)
+            self.assert_(isinstance(module.__loader__,
+                                    importlib._ExtensionFileLoader))
 
     def test_package(self):
         # Extensions are not found in packages.
index 9032b0bb69b242011f79c5d91a22ee65c212db48..54d805d783c28694a1c3e3bde32be836b1f49b11 100644 (file)
@@ -9,7 +9,7 @@ class LoaderTests(abc.LoaderTests):
         with util.uncache('__hello__'):
             module = machinery.FrozenImporter.load_module('__hello__')
             check = {'__name__': '__hello__', '__file__': '<frozen>',
-                        '__package__': ''}
+                    '__package__': '', '__loader__': machinery.FrozenImporter}
             for attr, value in check.items():
                 self.assertEqual(getattr(module, attr), value)
 
@@ -17,7 +17,8 @@ class LoaderTests(abc.LoaderTests):
         with util.uncache('__phello__'):
             module = machinery.FrozenImporter.load_module('__phello__')
             check = {'__name__': '__phello__', '__file__': '<frozen>',
-                     '__package__': '__phello__', '__path__': ['__phello__']}
+                     '__package__': '__phello__', '__path__': ['__phello__'],
+                     '__loader__': machinery.FrozenImporter}
             for attr, value in check.items():
                 attr_value = getattr(module, attr)
                 self.assertEqual(attr_value, value,
@@ -28,7 +29,8 @@ class LoaderTests(abc.LoaderTests):
         with util.uncache('__phello__', '__phello__.spam'):
             module = machinery.FrozenImporter.load_module('__phello__.spam')
             check = {'__name__': '__phello__.spam', '__file__': '<frozen>',
-                     '__package__': '__phello__'}
+                    '__package__': '__phello__',
+                    '__loader__': machinery.FrozenImporter}
             for attr, value in check.items():
                 attr_value = getattr(module, attr)
                 self.assertEqual(attr_value, value,
index 9022ab878fab5e8cc3b135cd61a044d596606dbc..3abc6a957b825be7574bb037ac34c39ebbb10064 100644 (file)
@@ -1,3 +1,4 @@
 """Utility code for constructing importers, etc."""
 from ._bootstrap import module_for_loader
+from ._bootstrap import set_loader
 from ._bootstrap import set_package