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