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