Rev 2764: (robertc) Show the version of plugins in the output of bzr plugins. (Robert Collins, #125421) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Wed Aug 29 06:17:00 BST 2007
At file:///home/pqm/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 2764
revision-id: pqm at pqm.ubuntu.com-20070829051658-yvj0n3mvso1v8uz3
parent: pqm at pqm.ubuntu.com-20070829001914-yd1js1ms7eg7g38g
parent: robertc at robertcollins.net-20070829044331-w6g2kahg2kaa9u9j
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Wed 2007-08-29 06:16:58 +0100
message:
(robertc) Show the version of plugins in the output of bzr plugins. (Robert Collins, #125421)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/benchmarks/__init__.py __init__.py-20060516064526-eb0d37c78e86065d
bzrlib/builtins.py builtins.py-20050830033751-fc01482b9ca23183
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/test_plugins.py plugins.py-20050622075746-32002b55e5e943e9
------------------------------------------------------------
revno: 2762.2.3
merged: robertc at robertcollins.net-20070829044331-w6g2kahg2kaa9u9j
parent: robertc at robertcollins.net-20070829015037-5ol4iw1qje4ajdga
committer: Robert Collins <robertc at robertcollins.net>
branch nick: plugin-versions
timestamp: Wed 2007-08-29 14:43:31 +1000
message:
Missed the benchmark suite as something to adjust for the new API.
------------------------------------------------------------
revno: 2762.2.2
merged: robertc at robertcollins.net-20070829015037-5ol4iw1qje4ajdga
parent: robertc at robertcollins.net-20070829011653-lb22o8no67g4y7yp
committer: Robert Collins <robertc at robertcollins.net>
branch nick: plugin-versions
timestamp: Wed 2007-08-29 11:50:37 +1000
message:
Review feedback.
------------------------------------------------------------
revno: 2762.2.1
merged: robertc at robertcollins.net-20070829011653-lb22o8no67g4y7yp
parent: pqm at pqm.ubuntu.com-20070828155202-pcq659o80mx4f4p3
committer: Robert Collins <robertc at robertcollins.net>
branch nick: plugin-versions
timestamp: Wed 2007-08-29 11:16:53 +1000
message:
* ``bzr plugins`` now lists the version number for each plugin in square
brackets after the path. (Robert Collins, #125421)
* ``bzrlib.plugin.all_plugins`` has been deprecated in favour of
``bzrlib.plugin.plugins()`` which returns PlugIn objects that provide
useful functionality for determining the path of a plugin, its tests, and
its version information. (Robert Collins)
=== modified file 'NEWS'
--- a/NEWS 2007-08-28 23:43:50 +0000
+++ b/NEWS 2007-08-29 05:16:58 +0000
@@ -23,6 +23,9 @@
BUG FIXES:
+ * ``bzr plugins`` now lists the version number for each plugin in square
+ brackets after the path. (Robert Collins, #125421)
+
* Suppress warning "integer argument expected, got float" from Paramiko,
which sometimes caused false test failures. (Martin Pool)
@@ -100,6 +103,11 @@
INTERNALS:
+ * ``bzrlib.plugin.all_plugins`` has been deprecated in favour of
+ ``bzrlib.plugin.plugins()`` which returns PlugIn objects that provide
+ useful functionality for determining the path of a plugin, its tests, and
+ its version information. (Robert Collins)
+
* New trace function ``mutter_callsite`` will print out a subset of the
stack to the log, which can be useful for gathering debug details.
(Robert Collins)
=== modified file 'bzrlib/benchmarks/__init__.py'
--- a/bzrlib/benchmarks/__init__.py 2007-07-18 20:42:38 +0000
+++ b/bzrlib/benchmarks/__init__.py 2007-08-29 04:43:31 +0000
@@ -18,8 +18,8 @@
from bzrlib import (
bzrdir,
- plugin,
)
+from bzrlib import plugin as _mod_plugin
import bzrlib.branch
from bzrlib.tests.TestUtil import TestLoader
from bzrlib.tests.blackbox import ExternalBase
@@ -197,8 +197,8 @@
suite = TestLoader().loadTestsFromModuleNames(testmod_names)
# Load any benchmarks from plugins
- for name, module in plugin.all_plugins().items():
- if getattr(module, 'bench_suite', None) is not None:
- suite.addTest(module.bench_suite())
+ for name, plugin in _mod_plugin.plugins().items():
+ if getattr(plugin.module, 'bench_suite', None) is not None:
+ suite.addTest(plugin.module.bench_suite())
return suite
=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py 2007-08-25 12:54:38 +0000
+++ b/bzrlib/builtins.py 2007-08-29 01:16:53 +0000
@@ -3235,15 +3235,9 @@
def run(self):
import bzrlib.plugin
from inspect import getdoc
- for name, plugin in bzrlib.plugin.all_plugins().items():
- if getattr(plugin, '__path__', None) is not None:
- print plugin.__path__[0]
- elif getattr(plugin, '__file__', None) is not None:
- print plugin.__file__
- else:
- print repr(plugin)
-
- d = getdoc(plugin)
+ for name, plugin in bzrlib.plugin.plugins().items():
+ print plugin.path(), "[%s]" % plugin.__version__
+ d = getdoc(plugin.module)
if d:
print '\t', d.split('\n')[0]
=== modified file 'bzrlib/plugin.py'
--- a/bzrlib/plugin.py 2007-08-28 04:34:10 +0000
+++ b/bzrlib/plugin.py 2007-08-29 01:50:37 +0000
@@ -42,10 +42,11 @@
from bzrlib import (
config,
osutils,
- plugins,
)
+from bzrlib import plugins as _mod_plugins
""")
+from bzrlib.symbol_versioning import deprecated_function, zero_ninetyone
from bzrlib.trace import mutter, warning, log_exception_quietly
@@ -60,13 +61,10 @@
return DEFAULT_PLUGIN_PATH
+ at deprecated_function(zero_ninetyone)
def all_plugins():
"""Return a dictionary of the plugins."""
- result = {}
- for name, plugin in plugins.__dict__.items():
- if isinstance(plugin, types.ModuleType):
- result[name] = plugin
- return result
+ return dict((name, plugin.module) for name, plugin in plugins().items())
def disable_plugins():
@@ -90,8 +88,8 @@
# it tries to import modules.
path = map(_strip_trailing_sep, path)
# search the plugin path before the bzrlib installed dir
- path.append(os.path.dirname(plugins.__file__))
- plugins.__path__ = path
+ path.append(os.path.dirname(_mod_plugins.__file__))
+ _mod_plugins.__path__ = path
return path
@@ -133,7 +131,7 @@
# this function, and since it sets plugins.__path__, it should set it to
# something that will be valid for Python to use (in case people try to
# run "import bzrlib.plugins.PLUGINNAME" after calling this function).
- plugins.__path__ = map(_strip_trailing_sep, dirs)
+ _mod_plugins.__path__ = map(_strip_trailing_sep, dirs)
for d in dirs:
if not d:
continue
@@ -179,7 +177,7 @@
break
else:
continue
- if getattr(plugins, f, None):
+ if getattr(_mod_plugins, f, None):
mutter('Plugin name %s already loaded', f)
else:
# mutter('add plugin name %s', f)
@@ -263,7 +261,7 @@
if not plugin_name:
continue
- if getattr(plugins, plugin_name, None):
+ if getattr(_mod_plugins, plugin_name, None):
mutter('Plugin name %s already loaded', plugin_name)
continue
@@ -279,6 +277,18 @@
log_exception_quietly()
+def plugins():
+ """Return a dictionary of the plugins.
+
+ Each item in the dictionary is a PlugIn object.
+ """
+ result = {}
+ for name, plugin in _mod_plugins.__dict__.items():
+ if isinstance(plugin, types.ModuleType):
+ result[name] = PlugIn(name, plugin)
+ return result
+
+
class PluginsHelpIndex(object):
"""A help index that returns help topics for plugins."""
@@ -345,3 +355,57 @@
def get_help_topic(self):
"""Return the modules help topic - its __name__ after bzrlib.plugins.."""
return self.module.__name__[len('bzrlib.plugins.'):]
+
+
+class PlugIn(object):
+ """The bzrlib representation of a plugin.
+
+ The PlugIn object provides a way to manipulate a given plugin module.
+ """
+
+ def __init__(self, name, module):
+ """Construct a plugin for module."""
+ self.name = name
+ self.module = module
+
+ def path(self):
+ """Get the path that this plugin was loaded from."""
+ if getattr(self.module, '__path__', None) is not None:
+ return os.path.abspath(self.module.__path__[0])
+ elif getattr(self.module, '__file__', None) is not None:
+ return os.path.abspath(self.module.__file__)
+ else:
+ return repr(self.module)
+
+ def __str__(self):
+ return "<%s.%s object at %s, name=%s, module=%s>" % (
+ self.__class__.__module__, self.__class__.__name__, id(self),
+ self.name, self.module)
+
+ __repr__ = __str__
+
+ def test_suite(self):
+ """Return the plugin's test suite."""
+ if getattr(self.module, 'test_suite', None) is not None:
+ return self.module.test_suite()
+ else:
+ return None
+
+ def version_info(self):
+ """Return the plugin's version_tuple or None if unknown."""
+ version_info = getattr(self.module, 'version_info', None)
+ if version_info is not None and len(version_info) == 3:
+ version_info = tuple(version_info) + ('final', 0)
+ return version_info
+
+ def _get__version__(self):
+ version_info = self.version_info()
+ if version_info is None:
+ return "unknown"
+ if version_info[3] == 'final':
+ version_string = '%d.%d.%d' % version_info[:3]
+ else:
+ version_string = '%d.%d.%d%s%d' % version_info
+ return version_string
+
+ __version__ = property(_get__version__)
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2007-08-28 07:52:00 +0000
+++ b/bzrlib/tests/__init__.py 2007-08-29 01:16:53 +0000
@@ -2496,22 +2496,22 @@
except ValueError, e:
print '**failed to get doctest for: %s\n%s' %(m,e)
raise
- for name, plugin in bzrlib.plugin.all_plugins().items():
- if getattr(plugin, 'test_suite', None) is not None:
- default_encoding = sys.getdefaultencoding()
- try:
- plugin_suite = plugin.test_suite()
- except ImportError, e:
- bzrlib.trace.warning(
- 'Unable to test plugin "%s": %s', name, e)
- else:
+ default_encoding = sys.getdefaultencoding()
+ for name, plugin in bzrlib.plugin.plugins().items():
+ try:
+ plugin_suite = plugin.test_suite()
+ except ImportError, e:
+ bzrlib.trace.warning(
+ 'Unable to test plugin "%s": %s', name, e)
+ else:
+ if plugin_suite is not None:
suite.addTest(plugin_suite)
- if default_encoding != sys.getdefaultencoding():
- bzrlib.trace.warning(
- 'Plugin "%s" tried to reset default encoding to: %s', name,
- sys.getdefaultencoding())
- reload(sys)
- sys.setdefaultencoding(default_encoding)
+ if default_encoding != sys.getdefaultencoding():
+ bzrlib.trace.warning(
+ 'Plugin "%s" tried to reset default encoding to: %s', name,
+ sys.getdefaultencoding())
+ reload(sys)
+ sys.setdefaultencoding(default_encoding)
return suite
=== modified file 'bzrlib/tests/test_plugins.py'
--- a/bzrlib/tests/test_plugins.py 2007-08-28 04:34:10 +0000
+++ b/bzrlib/tests/test_plugins.py 2007-08-29 01:16:53 +0000
@@ -30,6 +30,7 @@
import bzrlib.plugins
import bzrlib.commands
import bzrlib.help
+from bzrlib.symbol_versioning import zero_ninetyone
from bzrlib.tests import TestCase, TestCaseInTempDir
from bzrlib.osutils import pathjoin, abspath
@@ -88,6 +89,8 @@
finally:
# remove the plugin 'plugin'
del self.activeattributes[tempattribute]
+ if 'bzrlib.plugins.plugin' in sys.modules:
+ del sys.modules['bzrlib.plugins.plugin']
if getattr(bzrlib.plugins, 'plugin', None):
del bzrlib.plugins.plugin
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
@@ -137,9 +140,12 @@
finally:
# remove the plugin 'plugin'
del self.activeattributes[tempattribute]
- if getattr(bzrlib.plugins, 'plugin', None):
- del bzrlib.plugins.plugin
- self.failIf(getattr(bzrlib.plugins, 'plugin', None))
+ if getattr(bzrlib.plugins, 'pluginone', None):
+ del bzrlib.plugins.pluginone
+ if getattr(bzrlib.plugins, 'plugintwo', None):
+ del bzrlib.plugins.plugintwo
+ self.failIf(getattr(bzrlib.plugins, 'pluginone', None))
+ self.failIf(getattr(bzrlib.plugins, 'plugintwo', None))
def test_plugins_can_load_from_directory_with_trailing_slash(self):
# This test tests that a plugin can load from a directory when the
@@ -188,10 +194,11 @@
print >> file('plugin.py', 'w'), ""
try:
bzrlib.plugin.load_from_path(['.'])
- self.failUnless('plugin' in bzrlib.plugin.all_plugins())
+ all_plugins = self.applyDeprecated(zero_ninetyone,
+ bzrlib.plugin.all_plugins)
+ self.failUnless('plugin' in all_plugins)
self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
- self.assertEqual(bzrlib.plugin.all_plugins()['plugin'],
- bzrlib.plugins.plugin)
+ self.assertEqual(all_plugins['plugin'], bzrlib.plugins.plugin)
finally:
# remove the plugin 'plugin'
if 'bzrlib.plugins.plugin' in sys.modules:
@@ -201,6 +208,85 @@
self.failIf(getattr(bzrlib.plugins, 'plugin', None))
+class TestPlugins(TestCaseInTempDir):
+
+ def setup_plugin(self, source=""):
+ # This test tests a new plugin appears in bzrlib.plugin.plugins().
+ # check the plugin is not loaded already
+ self.failIf(getattr(bzrlib.plugins, 'plugin', None))
+ # write a plugin that _cannot_ fail to load.
+ print >> file('plugin.py', 'w'), source
+ self.addCleanup(self.teardown_plugin)
+ bzrlib.plugin.load_from_path(['.'])
+
+ def teardown_plugin(self):
+ # remove the plugin 'plugin'
+ if 'bzrlib.plugins.plugin' in sys.modules:
+ del sys.modules['bzrlib.plugins.plugin']
+ if getattr(bzrlib.plugins, 'plugin', None):
+ del bzrlib.plugins.plugin
+ self.failIf(getattr(bzrlib.plugins, 'plugin', None))
+
+ def test_plugin_appears_in_plugins(self):
+ self.setup_plugin()
+ self.failUnless('plugin' in bzrlib.plugin.plugins())
+ self.failUnless(getattr(bzrlib.plugins, 'plugin', None))
+ plugins = bzrlib.plugin.plugins()
+ plugin = plugins['plugin']
+ self.assertIsInstance(plugin, bzrlib.plugin.PlugIn)
+ self.assertEqual(bzrlib.plugins.plugin, plugin.module)
+
+ def test_trivial_plugin_get_path(self):
+ self.setup_plugin()
+ plugins = bzrlib.plugin.plugins()
+ plugin = plugins['plugin']
+ plugin_path = self.test_dir + '/plugin.py'
+ self.assertEqual(plugin_path, plugin.path())
+
+ def test_no_test_suite_gives_None_for_test_suite(self):
+ self.setup_plugin()
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual(None, plugin.test_suite())
+
+ def test_test_suite_gives_test_suite_result(self):
+ source = """def test_suite(): return 'foo'"""
+ self.setup_plugin(source)
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual('foo', plugin.test_suite())
+
+ def test_no_version_info(self):
+ self.setup_plugin()
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual(None, plugin.version_info())
+
+ def test_with_version_info(self):
+ self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual((1, 2, 3, 'dev', 4), plugin.version_info())
+
+ def test_short_version_info_gets_padded(self):
+ # the gtk plugin has version_info = (1,2,3) rather than the 5-tuple.
+ # so we adapt it
+ self.setup_plugin("version_info = (1, 2, 3)")
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual((1, 2, 3, 'final', 0), plugin.version_info())
+
+ def test_no_version_info___version__(self):
+ self.setup_plugin()
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual("unknown", plugin.__version__)
+
+ def test___version__with_version_info(self):
+ self.setup_plugin("version_info = (1, 2, 3, 'dev', 4)")
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual("1.2.3dev4", plugin.__version__)
+
+ def test_final__version__with_version_info(self):
+ self.setup_plugin("version_info = (1, 2, 3, 'final', 4)")
+ plugin = bzrlib.plugin.plugins()['plugin']
+ self.assertEqual("1.2.3", plugin.__version__)
+
+
class TestPluginHelp(TestCaseInTempDir):
def split_help_commands(self):
More information about the bazaar-commits
mailing list