summaryrefslogtreecommitdiff
path: root/bin/ansible-doc
diff options
context:
space:
mode:
Diffstat (limited to 'bin/ansible-doc')
-rwxr-xr-xbin/ansible-doc85
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))