Skip to content

Commit

Permalink
Document custom Jinja template filters (teemtee#2769)
Browse files Browse the repository at this point in the history
Includes a small refactoring of man page building to overcome rst2man
handling of `:ref:` directives.
  • Loading branch information
happz authored and The-Mule committed Oct 14, 2024
1 parent 4df549f commit cb32fe1
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 27 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

/tmp/
docs/code/autodocs/*.rst
docs/code/template-filters.rst
docs/plugins/discover.rst
docs/plugins/execute.rst
docs/plugins/finish.rst
Expand Down
11 changes: 8 additions & 3 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .

.PHONY: help generate-plugins plugins/*.rst generate-stories generate-autodocs clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
.PHONY: help generate-plugins plugins/*.rst generate-stories generate-template-filters generate-autodocs clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext

clean:
rm -rf $(BUILDDIR) stories spec code/autodocs/*.rst
rm -rf $(BUILDDIR) stories spec code/autodocs/*.rst code/template-filters.rst

##
## Building documentation
Expand Down Expand Up @@ -55,7 +55,7 @@ TEMPLATESDIR = templates

PLUGINS_TEMPLATE := $(TEMPLATESDIR)/plugins.rst.j2

generate: spec stories generate-lint-checks generate-plugins generate-stories generate-autodocs ## Refresh all generated documentation sources
generate: spec stories generate-lint-checks generate-template-filters generate-plugins generate-stories generate-autodocs ## Refresh all generated documentation sources

spec:
mkdir -p spec
Expand All @@ -66,6 +66,9 @@ stories:
spec/lint.rst: $(SCRIPTSDIR)/generate-lint-checks.py $(TEMPLATESDIR)/lint-checks.rst.j2 $(TMTDIR)/base.py
$(SCRIPTSDIR)/generate-lint-checks.py $(TEMPLATESDIR)/lint-checks.rst.j2 $@

code/template-filters.rst: $(SCRIPTSDIR)/generate-template-filters.py $(TEMPLATESDIR)/template-filters.rst.j2 $(TMTDIR)/utils.py
$(SCRIPTSDIR)/generate-template-filters.py $(TEMPLATESDIR)/template-filters.rst.j2 $@

plugins/discover.rst: $(SCRIPTSDIR)/generate-plugins.py $(PLUGINS_TEMPLATE) $(TMTDIR)/steps/discover/*.py
$(SCRIPTSDIR)/generate-plugins.py discover $(PLUGINS_TEMPLATE) $@

Expand All @@ -89,6 +92,8 @@ plugins/test-checks.rst: $(SCRIPTSDIR)/generate-plugins.py $(PLUGINS_TEMPLATE) $

generate-lint-checks: spec spec/lint.rst ## Generate documentation sources for lint checks

generate-template-filters: code/template-filters.rst ## Generate documentation sources for Jinja2 template filters

generate-stories: stories $(TEMPLATESDIR)/story.rst.j2 ## Generate documentation sources for stories
$(SCRIPTSDIR)/generate-stories.py $(TEMPLATESDIR)/story.rst.j2

Expand Down
1 change: 1 addition & 0 deletions docs/code/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ the documentation generated from sources linked below.
:maxdepth: 2

Class Overview <classes>
Template Filters <template-filters>
Plugin Introduction <plugin-introduction>
tmt <autodocs/tmt>

Expand Down
28 changes: 28 additions & 0 deletions docs/scripts/generate-template-filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env python3

import sys
import textwrap

from tmt.utils import TEMPLATE_FILTERS, Path, render_template_file

HELP = textwrap.dedent("""
Usage: generate-template-filters.py <TEMPLATE-PATH> <OUTPUT-PATH>
Generate docs for all known Jinja2 template filters.
""").strip()


def main() -> None:
if len(sys.argv) != 3:
print(HELP)

sys.exit(1)

template_filepath = Path(sys.argv[1])
output_filepath = Path(sys.argv[2])

output_filepath.write_text(render_template_file(template_filepath, TEMPLATES=TEMPLATE_FILTERS))


if __name__ == '__main__':
main()
6 changes: 3 additions & 3 deletions docs/templates/plugins.rst.j2
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

{% for PLUGIN_ID, PLUGIN, PLUGIN_DATA_CLASS in PLUGINS() %}

.. _plugins/{{ STEP }}/{{ PLUGIN_ID | strip }}:
.. _plugins/{{ STEP }}/{{ PLUGIN_ID | trim }}:

{{ PLUGIN_ID }}
{{ '-' * (PLUGIN_ID | length)}}
Expand All @@ -25,7 +25,7 @@
formatting is often suboptional.

{% if PLUGIN.__doc__ %}
{{ PLUGIN.__doc__ | dedent | strip }}
{{ PLUGIN.__doc__ | dedent | trim }}
{% endif %}

Configuration
Expand All @@ -42,7 +42,7 @@ Configuration
{{ option }}:
{% endif %}
{% if metadata.help %}
{{ metadata.help | strip | indent(4, first=true) }}
{{ metadata.help | trim | indent(4, first=true) }}
{% endif %}
{% if metadata.has_default %}
{% set actual_default = metadata.materialized_default %}
Expand Down
10 changes: 5 additions & 5 deletions docs/templates/story.rst.j2
Original file line number Diff line number Diff line change
Expand Up @@ -121,27 +121,27 @@
{% endmacro %}

{% if INCLUDE_TITLE %}
{% set depth = STORY.name | findall('/') | length - 1 %}
{% set depth = STORY.name | regex_findall('/') | length - 1 %}
{% set title_underline = '=~^:-><'[depth] %}
{% if STORY.title and STORY.title != STORY.node.parent.get('title') %}
{% set title = STORY.title %}
{% else %}
{% set title = STORY.name | regex_replace('.*/', '') %}
{% endif %}

.. _{{ STORY.name | strip }}:
.. _{{ STORY.name | trim }}:

{{ title | strip }}
{{ title | trim }}
{{ title_underline * title | length }}
{% endif %}

{# Summary, story and description #}
{% if STORY.summary and STORY.summary != STORY.node.parent.get('summary') %}
{{ STORY.summary | strip }}
{{ STORY.summary | trim }}
{% endif %}

{% if STORY.story != STORY.node.parent.get('story') %}
*{{ STORY.story | strip }}*
*{{ STORY.story | trim }}*
{% endif %}

{# Insert note about unimplemented feature (leaf nodes only) #}
Expand Down
34 changes: 34 additions & 0 deletions docs/templates/template-filters.rst.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{#
This template is rendered by conf.py & Sphinx when building documentation.
The reST comment below should land in the rendered file, to discourage people
from editing it instead of this template.
#}

..
Please, do not edit this file, is is rendered from template-filters.rst.j2,
and all your changes would be overwritten.

Template filters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When it comes to creating text documents, like
:ref:`custom_templates` or exporting tests, plans
and stories into ReST or Markdown, tmt relies on the well-known
`Jinja`__ package. All Jinja templating features are supported, and, on
top of `filters`__ shipped with Jinja, tmt adds several custom ones.

__ https://palletsprojects.com/p/jinja/
__ https://jinja.palletsprojects.com/en/3.1.x/templates/#filters

{% for filter_name in TEMPLATES.keys() | sort %}
{% set filter_callable = TEMPLATES[filter_name] %}

{{ filter_name }}
{{ '-' * (filter_name | length)}}

{% if filter_callable.__doc__ %}
{{ filter_callable.__doc__ | dedent | trim }}
{% endif %}

{% endfor %}
10 changes: 5 additions & 5 deletions tmt/export/templates/default-story.rst.j2
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@
{% endmacro %}

{% if INCLUDE_TITLE %}
{% set depth = STORY.name | findall('/') | length - 1 %}
{% set depth = STORY.name | regex_findall('/') | length - 1 %}
{% set title_underline = '=~^:-><'[depth] %}
{% if STORY.title and STORY.title != STORY.node.parent.get('title') %}
{% set title = STORY.title %}
{% else %}
{% set title = STORY.name | regex_replace('.*/', '') %}
{% endif %}

.. _{{ STORY.name | strip }}:
.. _{{ STORY.name | trim }}:

{{ title | strip }}
{{ title | trim }}
{{ title_underline * title | length }}
{% endif %}

{# Summary, story and description #}
{% if STORY.summary and STORY.summary != STORY.node.parent.get('summary') %}
{{ STORY.summary | strip }}
{{ STORY.summary | trim }}
{% endif %}

{% if STORY.story != STORY.node.parent.get('story') %}
*{{ STORY.story | strip }}*
*{{ STORY.story | trim }}*
{% endif %}

{# Insert note about unimplemented feature (leaf nodes only) #}
Expand Down
Loading

0 comments on commit cb32fe1

Please sign in to comment.