From 0281b6c000d4734d5e93cbec2331ffd287c3eb9f Mon Sep 17 00:00:00 2001 From: Andrey Kurilin Date: Tue, 6 Nov 2018 15:03:44 +0200 Subject: [PATCH] [docs] Check docstrings of plugin bases We are using docstings of plugin bases while publishing docs, so it is important to ensure that all of them provides valid rst Change-Id: I0bee6942c3058d6c936c5ccdbf798b3960e63242 --- rally/task/context.py | 1 + rally/task/exporter.py | 6 ++++-- rally/task/types.py | 1 + tests/unit/doc/test_docstrings.py | 36 +++++++++++++++++++++++++------ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/rally/task/context.py b/rally/task/context.py index 680f17b18f..768cfbed11 100644 --- a/rally/task/context.py +++ b/rally/task/context.py @@ -172,6 +172,7 @@ class BaseContext(plugin.Plugin, functional.FunctionalMixin, @validation.add_default("jsonschema") @plugin.base() class Context(BaseContext, validation.ValidatablePluginMixin): + """The base class for task contexts.""" def __init__(self, ctx): super(Context, self).__init__(ctx) self.task = self.context.get("task", {}) diff --git a/rally/task/exporter.py b/rally/task/exporter.py index e89aebca85..240c969ceb 100755 --- a/rally/task/exporter.py +++ b/rally/task/exporter.py @@ -64,10 +64,12 @@ class TaskExporter(plugin.Plugin, validation.ValidatablePluginMixin): different formats and send them to the different systems. To discover available plugins, call - ``rally plugin list --plugin-base TaskExporter``. + + rally plugin list --plugin-base TaskExporter. To export results of a task, call - ``rally task export --uuid --type --to `` + + rally task export --uuid --type --to """ diff --git a/rally/task/types.py b/rally/task/types.py index 2342572e1d..5a9239b78c 100644 --- a/rally/task/types.py +++ b/rally/task/types.py @@ -93,6 +93,7 @@ def preprocess(name, context, args): @plugin.base() @six.add_metaclass(abc.ABCMeta) class ResourceType(plugin.Plugin): + """A helper plugin for pre-processing input data of resources.""" def __init__(self, context, cache=None): self._context = context diff --git a/tests/unit/doc/test_docstrings.py b/tests/unit/doc/test_docstrings.py index e97f6b4150..6082e7e21b 100644 --- a/tests/unit/doc/test_docstrings.py +++ b/tests/unit/doc/test_docstrings.py @@ -63,9 +63,8 @@ class DocstringsTestCase(test.TestCase): # the list with plugins names which use rst definitions in their docstrings _HAS_VALID_DEFINITIONS = [] - def _validate_rst(self, plugin_name, text, msg_buffer): - parsed_docstring = _parse_rst(text) - for item in parsed_docstring: + def _iterate_parsed_rst(self, plugin_name, items, msg_buffer): + for item in items: if (isinstance(item, nodes.definition_list) and plugin_name not in self._HAS_VALID_DEFINITIONS): msg_buffer.append("Plugin %s has a docstring with invalid " @@ -76,6 +75,9 @@ class DocstringsTestCase(test.TestCase): msg_buffer.append( "A warning is caught while parsing docstring of '%s' " "plugin: %s" % (plugin_name, item.astext())) + elif item.children: + self._iterate_parsed_rst(plugin_name, item.children, + msg_buffer) def _check_docstrings(self, msg_buffer): for plg_cls in plugin.Plugin.get_all(): @@ -99,9 +101,10 @@ class DocstringsTestCase(test.TestCase): # "definitions" means that there is an issue with intends or # missed empty line before the list title and list items. if doc_info["description"]: - self._validate_rst(plg_cls.get_name(), - doc_info["description"], - msg_buffer) + parsed_docstring = _parse_rst(doc_info["description"]) + self._iterate_parsed_rst(plg_cls.get_name(), + parsed_docstring, + msg_buffer) def _check_described_params(self, msg_buffer): for plg_cls in plugin.Plugin.get_all(): @@ -123,3 +126,24 @@ class DocstringsTestCase(test.TestCase): self._check_described_params(msg_buffer) if msg_buffer: self.fail("\n%s" % "\n===============\n".join(msg_buffer)) + + def test_plugin_bases_have_docstrigs(self): + plugin_bases = set() + msg_buffer = [] + for plg_cls in plugin.Plugin.get_all(allow_hidden=True): + plugin_bases.add(plg_cls._get_base()) + for base in plugin_bases: + name = "%s.%s" % (base.__module__, base.__name__) + try: + docstring = base._get_doc() + except Exception: + docstring = base.__doc__ + + print(name) + parsed_docstring = _parse_rst(docstring) + self._iterate_parsed_rst(name, + parsed_docstring, + msg_buffer) + + if msg_buffer: + self.fail("\n%s" % "\n===============\n".join(msg_buffer))