Skip to content

Commit cf76b34

Browse files
authored
Merge pull request #6 from felixfontein/tests-filters
Support test and filter plugins
2 parents 0df8781 + b8522de commit cf76b34

File tree

21 files changed

+516
-32
lines changed

21 files changed

+516
-32
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
minor_changes:
2+
- "Support test and filter plugins when ansible-core 2.14+ is used. This works with the current ``devel`` branch of ansible-core (https://github.com/ansible-community/antsibull-docs/pull/6)."
3+
- "Support parameter type ``any``, and show ``raw`` as ``any`` (https://github.com/ansible-community/antsibull-docs/pull/6)."
4+
- "More robust handling of parsing errors when ansible-doc was unable to extract documentation (https://github.com/ansible-community/antsibull-docs/pull/6)."
5+
- "If lookup plugins have an option called ``_terms``, it is now shown in its own section ``Terms``, and not in the regular ``Parameters`` section (https://github.com/ansible-community/antsibull-docs/pull/6)."
6+
- "If lookup plugins have a single return value starting with ``_``, that return value is now labelled ``Return value`` (https://github.com/ansible-community/antsibull-docs/pull/6)."

src/antsibull_docs/cli/doc_commands/stable.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ def normalize_plugin_info(plugin_type: str,
136136
# If you wonder why this code isn't showing up in code coverage: that's because it's executed
137137
# in a subprocess. See normalize_all_plugin_info below.
138138

139+
if 'error' in plugin_info:
140+
return ({}, [plugin_info['error']])
141+
139142
errors = []
140143
if plugin_type == 'role':
141144
try:
@@ -251,10 +254,12 @@ def get_plugin_contents(plugin_info: t.Mapping[str, t.Mapping[str, t.Any]],
251254
namespace, collection, short_name = get_fqcn_parts(plugin_name)
252255
if plugin_type == 'role':
253256
desc = ''
254-
if 'main' in plugin_desc['entry_points']:
255-
desc = plugin_desc['entry_points']['main']['short_description']
257+
if 'entry_points' in plugin_desc and 'main' in plugin_desc['entry_points']:
258+
desc = plugin_desc['entry_points']['main'].get('short_description') or ''
259+
elif 'doc' in plugin_desc:
260+
desc = plugin_desc['doc'].get('short_description') or ''
256261
else:
257-
desc = plugin_desc['doc']['short_description']
262+
desc = ''
258263
plugin_contents[plugin_type]['.'.join((namespace, collection))][short_name] = desc
259264

260265
return plugin_contents

src/antsibull_docs/constants.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
DOCUMENTABLE_PLUGINS: FrozenSet[str] = frozenset(('become', 'cache', 'callback', 'cliconf',
1717
'connection', 'httpapi', 'inventory', 'lookup',
1818
'netconf', 'shell', 'vars', 'module',
19-
'strategy', 'role',))
19+
'strategy', 'role', 'filter', 'test'))
2020

2121

2222
DOCUMENTABLE_PLUGINS_MIN_VERSION: Dict[str, str] = {
23+
'filter': '2.14.0',
2324
'role': '2.11.0',
25+
'test': '2.14.0',
2426
}

src/antsibull_docs/data/docsite/macros/parameters.rst.j2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
* - Parameter
1313
- Comments
14-
{% for key, value in elements | dictsort recursive %}
14+
{% for key, value in elements recursive %}
1515
{# parameter name with required and/or introduced label #}
1616

1717
* - .. raw:: html
@@ -186,7 +186,7 @@
186186
</thead>
187187
<tbody>
188188
{% set row_class = cycler('even', 'odd') %}
189-
{% for key, value in elements | dictsort recursive %}
189+
{% for key, value in elements recursive %}
190190
{# parameter name with required and/or introduced label #}
191191
<tr class="row-@{ row_class.next() }@">
192192
<td>{% for i in range(1, loop.depth) %}<div class="ansible-option-indent"></div>{% endfor %}<div class="ansible-option-cell">

src/antsibull_docs/data/docsite/macros/returnvalues.rst.j2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
* - Key
1010
- Description
11-
{% for key, value in elements | dictsort recursive %}
11+
{% for key, value in elements recursive %}
1212
{# return value name #}
1313

1414
* - .. raw:: html
@@ -114,7 +114,7 @@
114114
</thead>
115115
<tbody>
116116
{% set row_class = cycler('even', 'odd') %}
117-
{% for key, value in elements | dictsort recursive %}
117+
{% for key, value in elements recursive %}
118118
{# return value name #}
119119
<tr class="row-@{ row_class.next() }@">
120120
<td>{% for i in range(1, loop.depth) %}<div class="ansible-option-indent"></div>{% endfor %}<div class="ansible-option-cell">

src/antsibull_docs/data/docsite/plugin.rst.j2

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -162,17 +162,90 @@ The below requirements are needed on the local controller node that executes thi
162162

163163
{% endif %}
164164

165+
{% set options_to_skip = [] %}
166+
167+
{% if doc['options']['_terms'] and plugin_type in ['lookup'] %}
168+
{% set options_to_skip = options_to_skip + ['_terms'] %}
169+
170+
.. Terms
171+
172+
Terms
173+
-----
174+
175+
{% if use_html_blobs %}
176+
@{ parameters_html([['Terms', doc['options']['_terms']]], suboption_key='suboptions') }@
177+
{% else %}
178+
@{ parameters_rst([['Terms', doc['options']['_terms']]], suboption_key='suboptions') }@
179+
{% endif %}
180+
181+
{% endif %}
182+
183+
{% if doc['options']['_input'] and plugin_type in ['filter', 'test'] %}
184+
{% set options_to_skip = options_to_skip + ['_input'] %}
185+
186+
.. Input
187+
188+
Input
189+
-----
190+
191+
{% if plugin_type == 'filter' %}
192+
This describes the input of the filter, the value before ``| @{plugin_name}@``.
193+
{% else %}
194+
This describes the input of the test, the value before ``is @{plugin_name}@`` or ``is not @{plugin_name}@``.
195+
{% endif %}
196+
197+
{% if use_html_blobs %}
198+
@{ parameters_html([['Input', doc['options']['_input']]], suboption_key='suboptions') }@
199+
{% else %}
200+
@{ parameters_rst([['Input', doc['options']['_input']]], suboption_key='suboptions') }@
201+
{% endif %}
202+
203+
{% endif %}
204+
205+
{% if doc['positional'] and plugin_type in ['lookup', 'filter', 'test'] %}
206+
{% set options_to_skip = options_to_skip + doc['positional'] %}
207+
208+
.. Positional
209+
210+
Positional parameters
211+
---------------------
212+
213+
{% if plugin_type == 'filter' %}
214+
This describes positional parameters of the filter. These are the values ``positional1``, ``positional2`` and so on in the following example: ``input | @{plugin_name}@(positional1, positional2, ...)``.
215+
{% elif plugin_type == 'test' %}
216+
This describes positional parameters of the test. These are the values ``positional1``, ``positional2`` and so on in the following examples: ``input is @{plugin_name}@(positional1, positional2, ...)`` and ``input is not @{plugin_name}@(positional1, positional2, ...)``.
217+
{% endif %}
218+
219+
{% if use_html_blobs %}
220+
@{ parameters_html(doc['options'] | extract_options_from_list(doc['positional']), suboption_key='suboptions') }@
221+
{% else %}
222+
@{ parameters_rst(doc['options'] | extract_options_from_list(doc['positional']), suboption_key='suboptions') }@
223+
{% endif %}
224+
225+
{% endif %}
226+
165227
.. Options
166228

167-
{% if doc['options'] -%}
229+
{% if doc['options'] | remove_options_from_list(options_to_skip) -%}
168230

231+
{% if plugin_type in ['filter', 'test'] %}
232+
Keyword parameters
233+
------------------
234+
{% else %}
169235
Parameters
170236
----------
237+
{% endif %}
238+
239+
{% if plugin_type == 'filter' %}
240+
This describes keyword parameters of the filter. These are the values ``key1=value1``, ``key2=value2`` and so on in the following example: ``input | @{plugin_name}@(key1=value1, key2=value2, ...)``.
241+
{% elif plugin_type == 'test' %}
242+
This describes keyword parameters of the test. These are the values ``key1=value1``, ``key2=value2`` and so on in the following examples: ``input is @{plugin_name}@(key1=value1, key2=value2, ...)`` and ``input is not @{plugin_name}@(key1=value1, key2=value2, ...)``.
243+
{% endif %}
171244

172245
{% if use_html_blobs %}
173-
@{ parameters_html(doc['options'], suboption_key='suboptions') }@
246+
@{ parameters_html(doc['options'] | remove_options_from_list(options_to_skip) | dictsort, suboption_key='suboptions') }@
174247
{% else %}
175-
@{ parameters_rst(doc['options'], suboption_key='suboptions') }@
248+
@{ parameters_rst(doc['options'] | remove_options_from_list(options_to_skip) | dictsort, suboption_key='suboptions') }@
176249
{% endif %}
177250
{% endif %}
178251

@@ -235,7 +308,7 @@ Examples
235308

236309
{% endif %}
237310

238-
{% if 'ansible_facts' in returndocs %}
311+
{% if 'ansible_facts' in returndocs and plugin_type == 'module' %}
239312
{% set returnfacts = returndocs['ansible_facts']['contains'] %}
240313
{% set _x = returndocs.pop('ansible_facts', None) %}
241314
{% endif %}
@@ -248,23 +321,37 @@ Returned Facts
248321
Facts returned by this module are added/updated in the ``hostvars`` host facts and can be referenced by name just like any other host fact. They do not need to be registered in order to use them.
249322

250323
{% if use_html_blobs %}
251-
@{ return_docs_html(returnfacts) }@
324+
@{ return_docs_html(returnfacts | dictsort) }@
252325
{% else %}
253-
@{ return_docs_rst(returnfacts) }@
326+
@{ return_docs_rst(returnfacts | dictsort) }@
254327
{% endif %}
255328
{% endif %}
256329

257330
.. Return values
258331

259332
{% if returndocs -%}
333+
{% if plugin_type not in ['lookup', 'filter', 'test'] %}
334+
{# This only makes sense for plugins which can return more than one value. #}
260335
Return Values
261336
-------------
262337
Common return values are documented :ref:`here <common_return_values>`, the following are the fields unique to this @{ plugin_type }@:
338+
{% else %}
339+
Return Value
340+
------------
341+
{% endif %}
263342

264-
{% if use_html_blobs %}
265-
@{ return_docs_html(returndocs) }@
343+
{% if plugin_type in ['lookup', 'filter', 'test'] and returndocs | length == 1 and (returndocs | first).startswith('_') %}
344+
{% if use_html_blobs %}
345+
@{ return_docs_html([['Return value', returndocs.values() | first]]) }@
346+
{% else %}
347+
@{ return_docs_rst([['Return value', returndocs.values() | first]]) }@
348+
{% endif %}
266349
{% else %}
267-
@{ return_docs_rst(returndocs) }@
350+
{% if use_html_blobs %}
351+
@{ return_docs_html(returndocs | dictsort) }@
352+
{% else %}
353+
@{ return_docs_rst(returndocs | dictsort) }@
354+
{% endif %}
268355
{% endif %}
269356
{% endif %}
270357

src/antsibull_docs/data/docsite/role.rst.j2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ Parameters
128128
^^^^^^^^^^
129129

130130
{% if use_html_blobs %}
131-
@{ parameters_html(ep_doc['options'], suboption_key='options', parameter_html_prefix=entry_point ~ '--', parameter_rst_prefix=entry_point ~ '__') }@
131+
@{ parameters_html(ep_doc['options'] | dictsort, suboption_key='options', parameter_html_prefix=entry_point ~ '--', parameter_rst_prefix=entry_point ~ '__') }@
132132
{% else %}
133-
@{ parameters_rst(ep_doc['options'], suboption_key='options', parameter_html_prefix=entry_point ~ '--', parameter_rst_prefix=entry_point ~ '__') }@
133+
@{ parameters_rst(ep_doc['options'] | dictsort, suboption_key='options', parameter_html_prefix=entry_point ~ '--', parameter_rst_prefix=entry_point ~ '__') }@
134134
{% endif %}
135135
{% endif %}
136136

src/antsibull_docs/jinja2/environment.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from .filters import (
1111
do_max, documented_type, html_ify, rst_ify, rst_escape, rst_fmt, rst_xline, move_first,
12-
massage_author_name,
12+
massage_author_name, extract_options_from_list, remove_options_from_list,
1313
)
1414
from .tests import still_relevant, test_list
1515

@@ -70,6 +70,8 @@ def doc_environment(template_location):
7070
env.filters['documented_type'] = documented_type
7171
env.filters['move_first'] = move_first
7272
env.filters['massage_author_name'] = massage_author_name
73+
env.filters['extract_options_from_list'] = extract_options_from_list
74+
env.filters['remove_options_from_list'] = remove_options_from_list
7375
env.tests['list'] = test_list
7476
env.tests['still_relevant'] = still_relevant
7577

src/antsibull_docs/jinja2/filters.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,18 @@ def massage_author_name(value):
194194
value = _EMAIL_ADDRESS.sub('', value)
195195
value = value.replace('(!UNKNOWN)', '')
196196
return value
197+
198+
199+
def extract_options_from_list(options: t.Dict[str, t.Any],
200+
options_to_extract: t.List[str]) -> t.List[t.Tuple[str, t.Any]]:
201+
''' return list of tuples (option, option_data) with option from options_to_extract '''
202+
return [(option, options[option]) for option in options_to_extract if option in options]
203+
204+
205+
def remove_options_from_list(options: t.Dict[str, t.Any],
206+
options_to_remove: t.List[str]) -> t.Dict[str, t.Any]:
207+
''' return copy of dictionary with the options from options_to_remove removed '''
208+
result = options.copy()
209+
for option in options_to_remove:
210+
result.pop(option, None)
211+
return result

src/antsibull_docs/schemas/ansible_doc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313

1414

1515
warnings.warn('antsibull.schemas.ansible_doc is deprecated.'
16-
' Use antsibull.schemas.docs.ansible_doc instead.',
16+
' Use antsibull_docs.schemas.docs.ansible_doc instead.',
1717
DeprecationWarning, stacklevel=2)

0 commit comments

Comments
 (0)