Rev 5288: (vila) BZR_PLUGINS_AT should import packages properly to handle in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Fri Jun 11 12:01:09 BST 2010


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 5288 [merge]
revision-id: pqm at pqm.ubuntu.com-20100611110107-t1zug4icv4ipz3dt
parent: pqm at pqm.ubuntu.com-20100611094453-lcedy2ld8qgmjwsq
parent: v.ladeuil+lp at free.fr-20100611080242-rlitsvrv2kmqizuj
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Fri 2010-06-11 12:01:07 +0100
message:
  (vila) BZR_PLUGINS_AT should import packages properly to handle
  	relative imports
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/plugin.py               plugin.py-20050622060424-829b654519533d69
  bzrlib/tests/test_plugins.py   plugins.py-20050622075746-32002b55e5e943e9
=== modified file 'NEWS'
--- a/NEWS	2010-06-11 06:39:24 +0000
+++ b/NEWS	2010-06-11 08:02:42 +0000
@@ -45,6 +45,10 @@
   arguments on Windows, because bzr script does the same.
   (Alexander Belchenko, #588277)
 
+* Relative imports in plugins are now handled correctly when using
+  BZR_PLUGINS_AT.
+  (Vincent Ladeuil, #588959)
+
 Improvements
 ************
 

=== modified file 'bzrlib/plugin.py'
--- a/bzrlib/plugin.py	2010-06-09 18:08:25 +0000
+++ b/bzrlib/plugin.py	2010-06-11 08:02:42 +0000
@@ -587,7 +587,6 @@
         # We are called only for specific paths
         plugin_path = self.specific_paths[fullname]
         loading_path = None
-        package = False
         if os.path.isdir(plugin_path):
             for suffix, mode, kind in imp.get_suffixes():
                 if kind not in (imp.PY_SOURCE, imp.PY_COMPILED):
@@ -595,8 +594,12 @@
                     continue
                 init_path = osutils.pathjoin(plugin_path, '__init__' + suffix)
                 if os.path.isfile(init_path):
-                    loading_path = init_path
-                    package = True
+                    # We've got a module here and load_module needs specific
+                    # parameters.
+                    loading_path = plugin_path
+                    suffix = ''
+                    mode = ''
+                    kind = imp.PKG_DIRECTORY
                     break
         else:
             for suffix, mode, kind in imp.get_suffixes():
@@ -606,17 +609,18 @@
         if loading_path is None:
             raise ImportError('%s cannot be loaded from %s'
                               % (fullname, plugin_path))
-        f = open(loading_path, mode)
+        if kind is imp.PKG_DIRECTORY:
+            f = None
+        else:
+            f = open(loading_path, mode)
         try:
             mod = imp.load_module(fullname, f, loading_path,
                                   (suffix, mode, kind))
-            if package:
-                # The plugin can contain modules, so be ready
-                mod.__path__ = [plugin_path]
             mod.__package__ = fullname
             return mod
         finally:
-            f.close()
+            if f is not None:
+                f.close()
 
 
 # Install a dedicated importer for plugins requiring special handling

=== modified file 'bzrlib/tests/test_plugins.py'
--- a/bzrlib/tests/test_plugins.py	2010-06-09 18:08:25 +0000
+++ b/bzrlib/tests/test_plugins.py	2010-06-11 08:02:42 +0000
@@ -80,6 +80,16 @@
         if getattr(bzrlib.plugins, name, None) is not None:
             delattr(bzrlib.plugins, name)
 
+    def _unregister_plugin_submodule(self, plugin_name, submodule_name):
+        """Remove the submodule from sys.modules and the bzrlib namespace."""
+        py_name = 'bzrlib.plugins.%s.%s' % (plugin_name, submodule_name)
+        if py_name in sys.modules:
+            del sys.modules[py_name]
+        plugin = getattr(bzrlib.plugins, plugin_name, None)
+        if plugin is not None:
+            if getattr(plugin, submodule_name, None) is not None:
+                delattr(plugin, submodule_name)
+
     def assertPluginUnknown(self, name):
         self.failIf(getattr(bzrlib.plugins, name, None) is not None)
         self.failIf('bzrlib.plugins.%s' % name in sys.modules)
@@ -828,8 +838,6 @@
         super(TestLoadPluginAt, self).setUp()
         # Make sure we don't pollute the plugins namespace
         self.overrideAttr(plugins, '__path__')
-        # Be paranoid in case a test fail
-        self.addCleanup(self._unregister_plugin, 'test_foo')
         # Reset the flag that protect against double loading
         self.overrideAttr(plugin, '_loaded', False)
         # Create the same plugin in two directories
@@ -837,6 +845,8 @@
         # The "normal" directory, we use 'standard' instead of 'plugins' to
         # avoid depending on the precise naming.
         self.create_plugin_package('test_foo', dir='standard/test_foo')
+        # All the tests will load the 'test_foo' plugin from various locations
+        self.addCleanup(self._unregister_plugin, 'test_foo')
 
     def assertTestFooLoadedFrom(self, path):
         self.assertPluginKnown('test_foo')
@@ -884,6 +894,8 @@
     def test_submodule_loading(self):
         # We create an additional directory under the one for test_foo
         self.create_plugin_package('test_bar', dir='non-standard-dir/test_bar')
+        self.addCleanup(self._unregister_plugin_submodule,
+                        'test_foo', 'test_bar')
         osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo at non-standard-dir')
         plugin.set_plugins_path(['standard'])
         import bzrlib.plugins.test_foo
@@ -893,6 +905,22 @@
         self.assertIsSameRealPath('non-standard-dir/test_bar/__init__.py',
                                   bzrlib.plugins.test_foo.test_bar.__file__)
 
+    def test_relative_submodule_loading(self):
+        self.create_plugin_package('test_foo', dir='another-dir', source='''
+import test_bar
+''')
+        # We create an additional directory under the one for test_foo
+        self.create_plugin_package('test_bar', dir='another-dir/test_bar')
+        self.addCleanup(self._unregister_plugin_submodule,
+                        'test_foo', 'test_bar')
+        osutils.set_or_unset_env('BZR_PLUGINS_AT', 'test_foo at another-dir')
+        plugin.set_plugins_path(['standard'])
+        import bzrlib.plugins.test_foo
+        self.assertEqual('bzrlib.plugins.test_foo',
+                         bzrlib.plugins.test_foo.__package__)
+        self.assertIsSameRealPath('another-dir/test_bar/__init__.py',
+                                  bzrlib.plugins.test_foo.test_bar.__file__)
+
     def test_loading_from___init__only(self):
         # We rename the existing __init__.py file to ensure that we don't load
         # a random file




More information about the bazaar-commits mailing list