Rev 4630: Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH. in file:///home/vila/src/bzr/bugs/412930-plugin-path/

Vincent Ladeuil v.ladeuil+lp at free.fr
Thu Aug 20 10:47:23 BST 2009


At file:///home/vila/src/bzr/bugs/412930-plugin-path/

------------------------------------------------------------
revno: 4630
revision-id: v.ladeuil+lp at free.fr-20090820094722-ng0j9r3re8tk52y7
parent: v.ladeuil+lp at free.fr-20090819170106-v652tu3p0mqnqs09
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 412930-plugin-path
timestamp: Thu 2009-08-20 11:47:22 +0200
message:
  Add [+-]{user|core|site} handling in BZR_PLUGIN_PATH.
  
  * bzrlib/plugin.py:
  (get_standard_plugins_path): Change the way the BZR_PLUGIN_PATH is
  handled to give more control.
  
  * bzrlib/tests/test_plugins.py:
  (TestSetPluginsPath): Deleted, covered by other tests.
  (TestLoadFromPath.test_get_standard_plugins_path,
  TestLoadFromPath.test_get_standard_plugins_path_env): Fix the
  failing parts covered elsewhere.
  (TestEnvPluginPath): Add tests for the new behaviors. 
-------------- next part --------------
=== modified file 'bzrlib/plugin.py'
--- a/bzrlib/plugin.py	2009-08-19 17:01:06 +0000
+++ b/bzrlib/plugin.py	2009-08-20 09:47:22 +0000
@@ -139,42 +139,58 @@
 
 def get_standard_plugins_path():
     """Determine a plugin path suitable for general use."""
-    path = os.environ.get('BZR_PLUGIN_PATH',
-                          get_default_plugin_path()).split(os.pathsep)
+    # Ad-Hoc default: core is not overriden by site but user can overrides both
+    defaults = ['+user', '+core', '+site']
+    env_paths = []
+    env_path = os.environ.get('BZR_PLUGIN_PATH', None)
+    if env_path:
+        env_paths = env_path.split(os.pathsep)
+
+    # The predefined references
+    refs = dict(core=get_core_plugin_path(),
+                site=get_site_plugin_path(),
+                user=get_user_plugin_path())
+
+    # Handle removals first
+    def unset_ref(p):
+        if p.startswith('-'):
+            key = p[1:]
+            if key in refs: # Needed to handle multiple removals
+                refs[key] = None
+                p = None
+        return p
+
+    defaults = [p for p in defaults if unset_ref(p) is not None]
+    env_paths = [p for p in env_paths if unset_ref(p) is not None]
+
+    for k, v in refs.iteritems():
+        added = '+%s' % k
+        if v is None:
+            # References removed can't be used anymore
+            if added in env_paths:
+                env_paths.remove(added)
+            if added in defaults:
+                defaults.remove(added)
+        else:
+            # Explicit beats implicit
+            if added in env_paths:
+                defaults.remove(added)
+
+    # Prepend the remaining defaults
+    paths = defaults + env_paths
+
+    # Resolve references
+    def resolve_ref(p):
+        if p.startswith('+') and refs.get(p[1:], None) is not None:
+            p = refs[p[1:]]
+        return p
+
+    paths = [resolve_ref(p) for p in paths]
+
     # Get rid of trailing slashes, since Python can't handle them when
     # it tries to import modules.
-    path = map(_strip_trailing_sep, path)
-    bzr_exe = bool(getattr(sys, 'frozen', None))
-    if bzr_exe:    # expand path for bzr.exe
-        # We need to use relative path to system-wide plugin
-        # directory because bzrlib from standalone bzr.exe
-        # could be imported by another standalone program
-        # (e.g. bzr-config; or TortoiseBzr/Olive if/when they
-        # will become standalone exe). [bialix 20071123]
-        # __file__ typically is
-        # C:\Program Files\Bazaar\lib\library.zip\bzrlib\plugin.pyc
-        # then plugins directory is
-        # C:\Program Files\Bazaar\plugins
-        # so relative path is ../../../plugins
-        path.append(osutils.abspath(osutils.pathjoin(
-            osutils.dirname(__file__), '../../../plugins')))
-    if not bzr_exe:     # don't look inside library.zip
-        # search the plugin path before the bzrlib installed dir
-        path.append(os.path.dirname(_mod_plugins.__file__))
-    # search the arch independent path if we can determine that and
-    # the plugin is found nowhere else
-    if sys.platform != 'win32':
-        try:
-            from distutils.sysconfig import get_python_lib
-        except ImportError:
-            # If distutuils is not available, we just won't add that path
-            pass
-        else:
-            archless_path = osutils.pathjoin(get_python_lib(), 'bzrlib',
-                    'plugins')
-            if archless_path not in path:
-                path.append(archless_path)
-    return path
+    paths = map(_strip_trailing_sep, paths)
+    return paths
 
 
 def load_plugins(path=None):

=== modified file 'bzrlib/tests/test_plugins.py'
--- a/bzrlib/tests/test_plugins.py	2009-08-19 17:01:06 +0000
+++ b/bzrlib/tests/test_plugins.py	2009-08-20 09:47:22 +0000
@@ -26,7 +26,11 @@
 import sys
 import zipfile
 
-from bzrlib import plugin, tests
+from bzrlib import (
+    osutils,
+    plugin,
+    tests,
+    )
 import bzrlib.plugin
 import bzrlib.plugins
 import bzrlib.commands
@@ -454,41 +458,6 @@
                 delattr(bzrlib.plugins, 'myplug')
 
 
-class TestSetPluginsPath(TestCase):
-
-    def test_set_plugins_path(self):
-        """set_plugins_path should set the module __path__ correctly."""
-        old_path = bzrlib.plugins.__path__
-        try:
-            bzrlib.plugins.__path__ = []
-            expected_path = bzrlib.plugin.set_plugins_path()
-            self.assertEqual(expected_path, bzrlib.plugins.__path__)
-        finally:
-            bzrlib.plugins.__path__ = old_path
-
-    def test_set_plugins_path_with_trailing_slashes(self):
-        """set_plugins_path should set the module __path__ based on
-        BZR_PLUGIN_PATH after removing all trailing slashes."""
-        old_path = bzrlib.plugins.__path__
-        old_env = os.environ.get('BZR_PLUGIN_PATH')
-        try:
-            bzrlib.plugins.__path__ = []
-            os.environ['BZR_PLUGIN_PATH'] = "first\\//\\" + os.pathsep + \
-                "second/\\/\\/"
-            bzrlib.plugin.set_plugins_path()
-            # We expect our nominated paths to have all path-seps removed,
-            # and this is testing only that.
-            expected_path = ['first', 'second']
-            self.assertEqual(expected_path,
-                bzrlib.plugins.__path__[:len(expected_path)])
-        finally:
-            bzrlib.plugins.__path__ = old_path
-            if old_env is not None:
-                os.environ['BZR_PLUGIN_PATH'] = old_env
-            else:
-                del os.environ['BZR_PLUGIN_PATH']
-
-
 class TestHelpIndex(tests.TestCase):
     """Tests for the PluginsHelpIndex class."""
 
@@ -633,7 +602,6 @@
 
     def test_get_standard_plugins_path(self):
         path = plugin.get_standard_plugins_path()
-        self.assertEqual(plugin.get_default_plugin_path(), path[0])
         for directory in path:
             self.assertNotContainsRe(directory, r'\\/$')
         try:
@@ -651,7 +619,9 @@
 
     def test_get_standard_plugins_path_env(self):
         os.environ['BZR_PLUGIN_PATH'] = 'foo/'
-        self.assertEqual('foo', plugin.get_standard_plugins_path()[0])
+        path = plugin.get_standard_plugins_path()
+        for directory in path:
+            self.assertNotContainsRe(directory, r'\\/$')
 
     def test_load_plugins(self):
         plugin.load_plugins(['.'])
@@ -683,13 +653,70 @@
         self.site = plugin.get_site_plugin_path()
         self.core = plugin.get_core_plugin_path()
 
-    def _list2path(self, *args):
+    def _list2paths(self, *args):
         paths = []
         for p in args:
             plugin._append_new_path(paths, p)
         return paths
 
+    def _set_path(self, *args):
+        path = os.pathsep.join(self._list2paths(*args))
+        osutils.set_or_unset_env('BZR_PLUGIN_PATH', path)
+
+    def check_path(self, expected_dirs, setting_dirs):
+        if setting_dirs:
+            self._set_path(*setting_dirs)
+        actual = plugin.get_standard_plugins_path()
+        self.assertEquals(self._list2paths(*expected_dirs), actual)
+
     def test_default(self):
-        self.assertEquals(self._list2path(self.user, self.core, self.site),
-                          plugin.get_standard_plugins_path())
+        self.check_path([self.user, self.core, self.site],
+                        None)
+
+    def test_adhoc_policy(self):
+        self.check_path([self.user, self.core, self.site],
+                        ['+user', '+core', '+site'])
+
+    def test_fallback_policy(self):
+        self.check_path([self.core, self.site, self.user],
+                        ['+core', '+site', '+user'])
+
+    def test_override_policy(self):
+        self.check_path([self.user, self.site, self.core],
+                        ['+user', '+site', '+core'])
+
+    def test_disable_user(self):
+        self.check_path([self.core, self.site], ['-user'])
+
+    def test_disable_user_twice(self):
+        # Ensures multiple removals don't left cruft
+        self.check_path([self.core, self.site], ['-user', '-user'])
+
+    def test_disable_overrides_disable(self):
+        self.check_path([self.core, self.site], ['-user', '+user'])
+
+    def test_disable_core(self):
+        self.check_path([self.user, self.site], ['-core'])
+
+    def test_disable_site(self):
+        self.check_path([self.user, self.core], ['-site'])
+
+    def test_override_site(self):
+        self.check_path([self.core, 'mysite', self.user],
+                        ['+core', 'mysite', '-site', '+user'])
+        self.check_path([self.user, self.core, 'mysite'],
+                        ['mysite', '-site'])
+
+    def test_override_core(self):
+        self.check_path(['mycore', self.site, self.user],
+                        ['mycore', '-core', '+site', '+user'])
+        self.check_path([self.user, self.site, 'mycore'],
+                        ['mycore', '-core'])
+
+    def test_my_plugin_only(self):
+        self.check_path(['myplugin'], ['myplugin', '-user', '-core', '-site'])
+
+    def test_my_plugin_first(self):
+        self.check_path(['myplugin', self.core, self.site, self.user],
+                        ['myplugin', '+core', '+site', '+user'])
 



More information about the bazaar-commits mailing list