Rev 2457: Return plugin module docstrings for 'bzr help plugin'. in file:///home/robertc/source/baz/help-contexts/
Robert Collins
robertc at robertcollins.net
Fri Apr 20 06:30:50 BST 2007
At file:///home/robertc/source/baz/help-contexts/
------------------------------------------------------------
revno: 2457
revision-id: robertc at robertcollins.net-20070420053047-j3je771lfsqwg4e9
parent: robertc at robertcollins.net-20070420043609-tuwv7tm97mmhh82p
committer: Robert Collins <robertc at robertcollins.net>
branch nick: help-contexts
timestamp: Fri 2007-04-20 15:30:47 +1000
message:
Return plugin module docstrings for 'bzr help plugin'.
modified:
bzrlib/help_topics.py help_topics.py-20060920210027-rnim90q9e0bwxvy4-1
bzrlib/plugin.py plugin.py-20050622060424-829b654519533d69
bzrlib/tests/test_plugins.py plugins.py-20050622075746-32002b55e5e943e9
=== modified file 'bzrlib/help_topics.py'
--- a/bzrlib/help_topics.py 2007-04-20 04:08:31 +0000
+++ b/bzrlib/help_topics.py 2007-04-20 05:30:47 +0000
@@ -286,6 +286,9 @@
cross-referenced.
"""
result = topic_registry.get_detail(self.topic)
+ # there is code duplicated here and in bzrlib/plugin.py's
+ # matching Topic code. This should probably be factored in
+ # to a helper function and a common base class.
if additional_see_also is not None:
see_also = sorted(set(additional_see_also))
else:
=== modified file 'bzrlib/plugin.py'
--- a/bzrlib/plugin.py 2007-04-20 04:36:09 +0000
+++ b/bzrlib/plugin.py 2007-04-20 05:30:47 +0000
@@ -276,4 +276,58 @@
self.prefix = 'plugins/'
def get_topics(self, topic):
- return []
+ """Search for topic in the loaded plugins.
+
+ This will not trigger loading of new plugins.
+
+ :param topic: A topic to search for.
+ :return: A list which is either empty or contains a single
+ RegisteredTopic entry.
+ """
+ if not topic:
+ return []
+ if topic.startswith(self.prefix):
+ topic = topic[len(self.prefix):]
+ plugin_module_name = 'bzrlib.plugins.%s' % topic
+ try:
+ module = sys.modules[plugin_module_name]
+ except KeyError:
+ return []
+ else:
+ return [ModuleHelpTopic(module)]
+
+
+class ModuleHelpTopic(object):
+ """A help topic which returns the docstring for a module."""
+
+ def __init__(self, module):
+ """Constructor.
+
+ :param module: The module for which help should be generated.
+ """
+ self.module = module
+
+ def get_help_text(self, additional_see_also=None):
+ """Return a string with the help for this topic.
+
+ :param additional_see_also: Additional help topics to be
+ cross-referenced.
+ """
+ if not self.module.__doc__:
+ result = "Plugin '%s' has no docstring.\n" % self.module.__name__
+ else:
+ result = self.module.__doc__
+ if result[-1] != '\n':
+ result += '\n'
+ # there is code duplicated here and in bzrlib/help_topic.py's
+ # matching Topic code. This should probably be factored in
+ # to a helper function and a common base class.
+ if additional_see_also is not None:
+ see_also = sorted(set(additional_see_also))
+ else:
+ see_also = None
+ if see_also:
+ result += 'See also: '
+ result += ', '.join(see_also)
+ result += '\n'
+ return result
=== modified file 'bzrlib/tests/test_plugins.py'
--- a/bzrlib/tests/test_plugins.py 2007-04-20 01:57:10 +0000
+++ b/bzrlib/tests/test_plugins.py 2007-04-20 05:30:47 +0000
@@ -25,6 +25,7 @@
import sys
import zipfile
+from bzrlib import plugin, tests
import bzrlib.plugin
import bzrlib.plugins
import bzrlib.commands
@@ -236,3 +237,96 @@
self.assertEqual(expected_path, bzrlib.plugins.__path__)
finally:
bzrlib.plugins.__path__ = old_path
+
+
+class TestHelpIndex(tests.TestCase):
+ """Tests for the PluginsHelpIndex class."""
+
+ def test_default_constructable(self):
+ index = plugin.PluginsHelpIndex()
+
+ def test_get_topics_None(self):
+ """Searching for None returns an empty list."""
+ index = plugin.PluginsHelpIndex()
+ self.assertEqual([], index.get_topics(None))
+
+ def test_get_topics_launchpad(self):
+ """Searching for 'launchpad' returns the launchpad plugin docstring."""
+ index = plugin.PluginsHelpIndex()
+ # if bzr was run with '--no-plugins' we need to manually load the
+ # reference plugin. Its shipped with bzr, and loading at this point
+ # won't add additional tests to run.
+ import bzrlib.plugins.launchpad
+ topics = index.get_topics('launchpad')
+ self.assertEqual(1, len(topics))
+ self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
+ self.assertEqual(bzrlib.plugins.launchpad, topics[0].module)
+
+ def test_get_topics_no_topic(self):
+ """Searching for something that is not a plugin returns []."""
+ # test this by using a name that cannot be a plugin - its not
+ # a valid python identifier.
+ index = plugin.PluginsHelpIndex()
+ self.assertEqual([], index.get_topics('nothing by this name'))
+
+ def test_prefix(self):
+ """PluginsHelpIndex has a prefix of 'plugins/'."""
+ index = plugin.PluginsHelpIndex()
+ self.assertEqual('plugins/', index.prefix)
+
+ def test_get_topic_with_prefix(self):
+ """Searching for plugins/launchpad returns launchpad module help."""
+ index = plugin.PluginsHelpIndex()
+ # if bzr was run with '--no-plugins' we need to manually load the
+ # reference plugin. Its shipped with bzr, and loading at this point
+ # won't add additional tests to run.
+ import bzrlib.plugins.launchpad
+ topics = index.get_topics('plugins/launchpad')
+ self.assertEqual(1, len(topics))
+ self.assertIsInstance(topics[0], plugin.ModuleHelpTopic)
+ self.assertEqual(bzrlib.plugins.launchpad, topics[0].module)
+
+
+class FakeModule(object):
+ """A fake module to test with."""
+
+ def __init__(self, doc, name):
+ self.__doc__ = doc
+ self.__name__ = name
+
+
+class TestModuleHelpTopic(tests.TestCase):
+ """Tests for the ModuleHelpTopic class."""
+
+ def test_contruct(self):
+ """Construction takes the module to document."""
+ mod = FakeModule('foo', 'foo')
+ topic = plugin.ModuleHelpTopic(mod)
+ self.assertEqual(mod, topic.module)
+
+ def test_get_help_text_None(self):
+ """A ModuleHelpTopic returns the docstring for get_help_text."""
+ mod = FakeModule(None, 'demo')
+ topic = plugin.ModuleHelpTopic(mod)
+ self.assertEqual("Plugin 'demo' has no docstring.\n",
+ topic.get_help_text())
+
+ def test_get_help_text_no_carriage_return(self):
+ """ModuleHelpTopic.get_help_text adds a \n if needed."""
+ mod = FakeModule('one line of help', 'demo')
+ topic = plugin.ModuleHelpTopic(mod)
+ self.assertEqual("one line of help\n",
+ topic.get_help_text())
+
+ def test_get_help_text_carriage_return(self):
+ """ModuleHelpTopic.get_help_text adds a \n if needed."""
+ mod = FakeModule('two lines of help\nand more\n', 'demo')
+ topic = plugin.ModuleHelpTopic(mod)
+ self.assertEqual("two lines of help\nand more\n",
+ topic.get_help_text())
+
+ def test_get_help_text_with_additional_see_also(self):
+ mod = FakeModule('two lines of help\nand more', 'demo')
+ topic = plugin.ModuleHelpTopic(mod)
+ self.assertEqual("two lines of help\nand more\nSee also: bar, foo\n",
+ topic.get_help_text(['foo', 'bar']))
More information about the bazaar-commits
mailing list