diff options
Diffstat (limited to 'bin/ansible-doc')
-rwxr-xr-x | bin/ansible-doc | 85 |
1 files changed, 10 insertions, 75 deletions
diff --git a/bin/ansible-doc b/bin/ansible-doc index 4a5c8928..9f560bcb 100755 --- a/bin/ansible-doc +++ b/bin/ansible-doc @@ -26,7 +26,7 @@ from ansible import context from ansible.cli.arguments import option_helpers as opt_help from ansible.collections.list import list_collection_dirs from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleParserError, AnsiblePluginNotFound -from ansible.module_utils.common.text.converters import to_native, to_text +from ansible.module_utils._text import to_native, to_text from ansible.module_utils.common.collections import is_sequence from ansible.module_utils.common.json import json_dump from ansible.module_utils.common.yaml import yaml_dump @@ -163,8 +163,8 @@ class RoleMixin(object): might be fully qualified with the collection name (e.g., community.general.roleA) or not (e.g., roleA). - :param collection_filter: A list of strings containing the FQCN of a collection which will - be used to limit results. This filter will take precedence over the name_filters. + :param collection_filter: A string containing the FQCN of a collection which will be + used to limit results. This filter will take precedence over the name_filters. :returns: A set of tuples consisting of: role name, collection name, collection path """ @@ -362,23 +362,12 @@ class DocCLI(CLI, RoleMixin): _ITALIC = re.compile(r"\bI\(([^)]+)\)") _BOLD = re.compile(r"\bB\(([^)]+)\)") _MODULE = re.compile(r"\bM\(([^)]+)\)") - _PLUGIN = re.compile(r"\bP\(([^#)]+)#([a-z]+)\)") _LINK = re.compile(r"\bL\(([^)]+), *([^)]+)\)") _URL = re.compile(r"\bU\(([^)]+)\)") _REF = re.compile(r"\bR\(([^)]+), *([^)]+)\)") _CONST = re.compile(r"\bC\(([^)]+)\)") - _SEM_PARAMETER_STRING = r"\(((?:[^\\)]+|\\.)+)\)" - _SEM_OPTION_NAME = re.compile(r"\bO" + _SEM_PARAMETER_STRING) - _SEM_OPTION_VALUE = re.compile(r"\bV" + _SEM_PARAMETER_STRING) - _SEM_ENV_VARIABLE = re.compile(r"\bE" + _SEM_PARAMETER_STRING) - _SEM_RET_VALUE = re.compile(r"\bRV" + _SEM_PARAMETER_STRING) _RULER = re.compile(r"\bHORIZONTALLINE\b") - # helper for unescaping - _UNESCAPE = re.compile(r"\\(.)") - _FQCN_TYPE_PREFIX_RE = re.compile(r'^([^.]+\.[^.]+\.[^#]+)#([a-z]+):(.*)$') - _IGNORE_MARKER = 'ignore:' - # rst specific _RST_NOTE = re.compile(r".. note::") _RST_SEEALSO = re.compile(r".. seealso::") @@ -390,40 +379,6 @@ class DocCLI(CLI, RoleMixin): super(DocCLI, self).__init__(args) self.plugin_list = set() - @staticmethod - def _tty_ify_sem_simle(matcher): - text = DocCLI._UNESCAPE.sub(r'\1', matcher.group(1)) - return f"`{text}'" - - @staticmethod - def _tty_ify_sem_complex(matcher): - text = DocCLI._UNESCAPE.sub(r'\1', matcher.group(1)) - value = None - if '=' in text: - text, value = text.split('=', 1) - m = DocCLI._FQCN_TYPE_PREFIX_RE.match(text) - if m: - plugin_fqcn = m.group(1) - plugin_type = m.group(2) - text = m.group(3) - elif text.startswith(DocCLI._IGNORE_MARKER): - text = text[len(DocCLI._IGNORE_MARKER):] - plugin_fqcn = plugin_type = '' - else: - plugin_fqcn = plugin_type = '' - entrypoint = None - if ':' in text: - entrypoint, text = text.split(':', 1) - if value is not None: - text = f"{text}={value}" - if plugin_fqcn and plugin_type: - plugin_suffix = '' if plugin_type in ('role', 'module', 'playbook') else ' plugin' - plugin = f"{plugin_type}{plugin_suffix} {plugin_fqcn}" - if plugin_type == 'role' and entrypoint is not None: - plugin = f"{plugin}, {entrypoint} entrypoint" - return f"`{text}' (of {plugin})" - return f"`{text}'" - @classmethod def find_plugins(cls, path, internal, plugin_type, coll_filter=None): display.deprecated("find_plugins method as it is incomplete/incorrect. use ansible.plugins.list functions instead.", version='2.17') @@ -438,13 +393,8 @@ class DocCLI(CLI, RoleMixin): t = cls._MODULE.sub("[" + r"\1" + "]", t) # M(word) => [word] t = cls._URL.sub(r"\1", t) # U(word) => word t = cls._LINK.sub(r"\1 <\2>", t) # L(word, url) => word <url> - t = cls._PLUGIN.sub("[" + r"\1" + "]", t) # P(word#type) => [word] t = cls._REF.sub(r"\1", t) # R(word, sphinx-ref) => word t = cls._CONST.sub(r"`\1'", t) # C(word) => `word' - t = cls._SEM_OPTION_NAME.sub(cls._tty_ify_sem_complex, t) # O(expr) - t = cls._SEM_OPTION_VALUE.sub(cls._tty_ify_sem_simle, t) # V(expr) - t = cls._SEM_ENV_VARIABLE.sub(cls._tty_ify_sem_simle, t) # E(expr) - t = cls._SEM_RET_VALUE.sub(cls._tty_ify_sem_complex, t) # RV(expr) t = cls._RULER.sub("\n{0}\n".format("-" * 13), t) # HORIZONTALLINE => ------- # remove rst @@ -545,9 +495,7 @@ class DocCLI(CLI, RoleMixin): desc = desc[:linelimit] + '...' pbreak = plugin.split('.') - # TODO: add mark for deprecated collection plugins - if pbreak[-1].startswith('_') and plugin.startswith(('ansible.builtin.', 'ansible.legacy.')): - # Handle deprecated ansible.builtin plugins + if pbreak[-1].startswith('_'): # Handle deprecated # TODO: add mark for deprecated collection plugins pbreak[-1] = pbreak[-1][1:] plugin = '.'.join(pbreak) deprecated.append("%-*s %-*.*s" % (displace, plugin, linelimit, len(desc), desc)) @@ -678,11 +626,12 @@ class DocCLI(CLI, RoleMixin): def _get_collection_filter(self): coll_filter = None - if len(context.CLIARGS['args']) >= 1: - coll_filter = context.CLIARGS['args'] - for coll_name in coll_filter: - if not AnsibleCollectionRef.is_valid_collection_name(coll_name): - raise AnsibleError('Invalid collection name (must be of the form namespace.collection): {0}'.format(coll_name)) + if len(context.CLIARGS['args']) == 1: + coll_filter = context.CLIARGS['args'][0] + if not AnsibleCollectionRef.is_valid_collection_name(coll_filter): + raise AnsibleError('Invalid collection name (must be of the form namespace.collection): {0}'.format(coll_filter)) + elif len(context.CLIARGS['args']) > 1: + raise AnsibleOptionsError("Only a single collection filter is supported.") return coll_filter @@ -1302,20 +1251,6 @@ class DocCLI(CLI, RoleMixin): relative_url = 'collections/%s_module.html' % item['module'].replace('.', '/', 2) text.append(textwrap.fill(DocCLI.tty_ify(get_versioned_doclink(relative_url)), limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent)) - elif 'plugin' in item and 'plugin_type' in item: - plugin_suffix = ' plugin' if item['plugin_type'] not in ('module', 'role') else '' - text.append(textwrap.fill(DocCLI.tty_ify('%s%s %s' % (item['plugin_type'].title(), plugin_suffix, item['plugin'])), - limit - 6, initial_indent=opt_indent[:-2] + "* ", subsequent_indent=opt_indent)) - description = item.get('description') - if description is None and item['plugin'].startswith('ansible.builtin.'): - description = 'The official documentation on the %s %s%s.' % (item['plugin'], item['plugin_type'], plugin_suffix) - if description is not None: - text.append(textwrap.fill(DocCLI.tty_ify(description), - limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent + ' ')) - if item['plugin'].startswith('ansible.builtin.'): - relative_url = 'collections/%s_%s.html' % (item['plugin'].replace('.', '/', 2), item['plugin_type']) - text.append(textwrap.fill(DocCLI.tty_ify(get_versioned_doclink(relative_url)), - limit - 6, initial_indent=opt_indent + ' ', subsequent_indent=opt_indent)) elif 'name' in item and 'link' in item and 'description' in item: text.append(textwrap.fill(DocCLI.tty_ify(item['name']), limit - 6, initial_indent=opt_indent[:-2] + "* ", subsequent_indent=opt_indent)) |