diff --git a/lib/ansible/cli/doc.py b/lib/ansible/cli/doc.py index e7bc8485904..733dec68350 100644 --- a/lib/ansible/cli/doc.py +++ b/lib/ansible/cli/doc.py @@ -33,7 +33,7 @@ from ansible.module_utils.six import string_types from ansible.parsing.yaml.dumper import AnsibleDumper from ansible.plugins.loader import module_loader, action_loader, lookup_loader, callback_loader, cache_loader, \ vars_loader, connection_loader, strategy_loader, inventory_loader, shell_loader, fragment_loader -from ansible.utils.plugin_docs import BLACKLIST, get_docstring +from ansible.utils.plugin_docs import BLACKLIST, get_docstring, get_docstub try: from __main__ import display @@ -130,7 +130,7 @@ class DocCLI(CLI): for path in paths: self.plugin_list.update(self.find_plugins(path, plugin_type)) - self.pager(self.get_plugin_list_text(loader)) + self.pager(self.get_plugin_list_text(loader, doc_getter=get_docstub)) return 0 # process all plugins of type @@ -304,7 +304,7 @@ class DocCLI(CLI): return plugin_list - def get_plugin_list_text(self, loader): + def get_plugin_list_text(self, loader, doc_getter=get_docstring): columns = display.columns displace = max(len(x) for x in self.plugin_list) linelimit = columns - displace - 5 @@ -325,7 +325,7 @@ class DocCLI(CLI): doc = None try: - doc, plainexamples, returndocs, metadata = get_docstring(filename, fragment_loader) + doc, plainexamples, returndocs, metadata = doc_getter(filename, fragment_loader) except Exception: display.warning("%s has a documentation formatting error" % plugin) diff --git a/lib/ansible/parsing/plugin_docs.py b/lib/ansible/parsing/plugin_docs.py index 797e87f4402..eb77d3fa42b 100644 --- a/lib/ansible/parsing/plugin_docs.py +++ b/lib/ansible/parsing/plugin_docs.py @@ -80,3 +80,43 @@ def read_docstring(filename, verbose=True, ignore_errors=True): raise return data + + +def read_docstub(filename, verbose=True, ignore_errors=True): + """ + Quickly find short_description using string methods instead of node parsing. + This does not return a full set of documentation strings and is intended for + operations like ansible-doc -l. + """ + + data = { + 'doc': None, + 'plainexamples': None, + 'returndocs': None, + 'metadata': None + } + + try: + t_module_data = open(filename, 'r') + capturing = False + doc_stub = [] + + for line in t_module_data: + # start capturing the stub until indentation returns + if capturing and line[0] == ' ': + doc_stub.append(line) + elif capturing and line[0] != ' ': + break + if 'short_description:' in line: + capturing = True + doc_stub.append(line) + + data['doc'] = AnsibleLoader(r"".join(doc_stub), file_name=filename).get_single_data() + + except: + if verbose: + display.error("unable to parse %s" % filename) + if not ignore_errors: + raise + + return data diff --git a/lib/ansible/utils/plugin_docs.py b/lib/ansible/utils/plugin_docs.py index 206442a52da..475ebc88ad2 100644 --- a/lib/ansible/utils/plugin_docs.py +++ b/lib/ansible/utils/plugin_docs.py @@ -25,7 +25,7 @@ from collections import MutableMapping, MutableSet, MutableSequence from ansible.errors import AnsibleError, AnsibleAssertionError from ansible.module_utils.six import string_types from ansible.module_utils._text import to_native -from ansible.parsing.plugin_docs import read_docstring +from ansible.parsing.plugin_docs import read_docstring, read_docstub from ansible.parsing.yaml.loader import AnsibleLoader try: @@ -120,3 +120,16 @@ def get_docstring(filename, fragment_loader, verbose=False, ignore_errors=False) add_fragments(data['doc'], filename, fragment_loader=fragment_loader) return data['doc'], data['plainexamples'], data['returndocs'], data['metadata'] + + +def get_docstub(filename, fragment_loader, verbose=False, ignore_errors=False): + """ + When only short_description is needed, load a stub of the full DOCUMENTATION string to speed up operation. + """ + + data = read_docstub(filename, verbose=verbose, ignore_errors=ignore_errors) + + if data.get('doc', False): + add_fragments(data['doc'], filename, fragment_loader=fragment_loader) + + return data['doc'], data['plainexamples'], data['returndocs'], data['metadata']