Skip to content

Commit

Permalink
Move label generating code to one place.
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfontein committed Apr 6, 2024
1 parent 5ef98a4 commit 8709d51
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

.. Anchors

.. _ansible_collections.@{plugin_name}@_@{plugin_type}@:
.. _@{ rst_plugin_ref(plugin_name, plugin_type) }@:

.. Title

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

.. Anchors

.. _ansible_collections.@{plugin_name}@_@{plugin_type}@:
.. _@{ rst_plugin_ref(plugin_name, plugin_type) }@:

.. Title

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

.. Anchors

.. _ansible_collections.@{plugin_name}@_@{plugin_type}@:
.. _@{ rst_plugin_ref(plugin_name, plugin_type) }@:

.. Title

Expand Down
4 changes: 2 additions & 2 deletions src/antsibull_docs/data/docsite/ansible-docsite/plugin.rst.j2
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

.. Anchors

.. _ansible_collections.@{plugin_name}@_@{plugin_type}@:
.. _@{ rst_plugin_ref(plugin_name, plugin_type) }@:

.. Anchors: short name for ansible.builtin

Expand Down Expand Up @@ -84,7 +84,7 @@
To install it, use: @{ collection | collection_install | rst_code }@.
{% if doc['requirements'] %}
You need further requirements to be able to use this {% if plugin_type == 'module' %}module{% else %}@{ plugin_type }@ plugin{% endif %},
see :ref:`Requirements <ansible_collections.@{plugin_name}@_@{plugin_type}@_requirements>` for details.
see :ref:`Requirements <@{ rst_requirements_ref(plugin_name, plugin_type) }@>` for details.
{% endif %}

To use it in a playbook, specify: :code:`@{plugin_name}@`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

.. Anchors

.. _ansible_collections.@{plugin_name}@_@{plugin_type}@:
.. _@{ rst_plugin_ref(plugin_name, plugin_type) }@:

.. Title

Expand Down
5 changes: 4 additions & 1 deletion src/antsibull_docs/jinja2/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from jinja2 import BaseLoader, Environment, FileSystemLoader, PackageLoader

from ..markup.rstify import rst_code, rst_escape
from ..rst_labels import get_plugin_ref, get_requirements_ref
from ..utils.collection_name_transformer import CollectionNameTransformer
from . import FilenameGenerator, OutputFormat
from .filters import (
Expand All @@ -38,7 +39,7 @@

def reference_plugin_rst(plugin_name: str, plugin_type: str) -> str:
fqcn = f"{plugin_name}"
return f"\\ :ref:`{rst_escape(fqcn)} <ansible_collections.{fqcn}_{plugin_type}>`\\ "
return f"\\ :ref:`{rst_escape(fqcn)} <{get_plugin_ref(fqcn, plugin_type)}>`\\ "


def reference_plugin_rst_simplified(plugin_name: str, plugin_type: str) -> str:
Expand Down Expand Up @@ -139,6 +140,8 @@ def doc_environment(

env.globals["reference_plugin_rst"] = make_reference_plugin_rst(output_format)
env.globals["referable_envvars"] = referable_envvars
env.globals["rst_plugin_ref"] = get_plugin_ref
env.globals["rst_requirements_ref"] = get_requirements_ref
env.filters["rst_ify"] = make_rst_ify(output_format)
env.filters["html_ify"] = html_ify
env.filters["fmt"] = rst_fmt
Expand Down
74 changes: 74 additions & 0 deletions src/antsibull_docs/rst_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Author: Felix Fontein <[email protected]>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or
# https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2023, Ansible Project
"""
Label helpers.
"""

from __future__ import annotations

from antsibull_docs.utils.rst import massage_rst_label


def get_plugin_ref(plugin_fqcn: str, plugin_type: str) -> str:
return f"ansible_collections.{plugin_fqcn}_{plugin_type}"


def get_attribute_ref(
plugin_fqcn: str,
plugin_type: str,
role_entrypoint: str | None,
attribute: str,
) -> str:
ref = massage_rst_label(attribute)
ep = (
f"{role_entrypoint}__"
if role_entrypoint is not None and plugin_type == "role"
else ""
)
return f"{get_plugin_ref(plugin_fqcn, plugin_type)}__attribute-{ep}{ref}"


def get_option_ref(
plugin_fqcn: str,
plugin_type: str,
role_entrypoint: str | None,
option: list[str],
) -> str:
ref = "/".join(massage_rst_label(part) for part in option)
ep = (
f"{role_entrypoint}__"
if role_entrypoint is not None and plugin_type == "role"
else ""
)
return f"{get_plugin_ref(plugin_fqcn, plugin_type)}__parameter-{ep}{ref}"


def get_return_value_ref(
plugin_fqcn: str,
plugin_type: str,
role_entrypoint: str | None,
return_value: list[str],
) -> str:
ref = "/".join(massage_rst_label(part) for part in return_value)
ep = (
f"{role_entrypoint}__"
if role_entrypoint is not None and plugin_type == "role"
else ""
)
return f"{get_plugin_ref(plugin_fqcn, plugin_type)}__return-{ep}{ref}"


def get_requirements_ref(
plugin_fqcn: str,
plugin_type: str,
role_entrypoint: str | None = None,
) -> str:
ep = (
f"-{role_entrypoint}"
if role_entrypoint is not None and plugin_type == "role"
else ""
)
return f"{get_plugin_ref(plugin_fqcn, plugin_type)}_requirements{ep}"
4 changes: 4 additions & 0 deletions src/sphinx_antsibull_ext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from .assets import setup_assets
from .directives import setup_directives
from .domains import setup_domains
from .nodes import setup_nodes
from .roles import setup_roles

Expand All @@ -40,6 +41,9 @@ def setup(app):
# Add directives
setup_directives(app)

# Add domains
setup_domains(app)

return {
"parallel_read_safe": True,
"parallel_write_safe": True,
Expand Down
80 changes: 16 additions & 64 deletions src/sphinx_antsibull_ext/directives.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,21 @@
from urllib.parse import quote as _urllib_quote

from docutils import nodes
from docutils.nodes import Element
from sphinx import addnodes, domains
from sphinx.builders import Builder
from sphinx import addnodes
from sphinx.domains.std import StandardDomain
from sphinx.environment import BuildEnvironment
from sphinx.locale import _
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_id

from antsibull_docs.utils.rst import massage_rst_label
from antsibull_docs.rst_labels import (
get_attribute_ref,
get_option_ref,
get_requirements_ref,
get_return_value_ref,
)

from .directive_helper import YAMLDirective
from .domains import AnsibleDomain
from .nodes import ansible_attribute, ansible_option, ansible_return_value, link_button
from .schemas.ansible_links import AnsibleLinks
from .schemas.ansible_plugin import (
Expand Down Expand Up @@ -93,51 +95,6 @@ def _run(self, content_str: str, content: AnsibleLinks) -> list[nodes.Node]:
return [node]


class AnsibleDomain(domains.Domain):
name = "ansible"

object_types: dict[str, domains.ObjType] = {
"plugin": domains.ObjType(_("plugin"), "plugin", searchprio=-1),
"role_entrypoint": domains.ObjType(
_("role entrypoint"), "role_entrypoint", searchprio=-1
),
}

@property
def objects(self) -> dict[tuple[str, str], tuple[str, str]]:
return self.data.setdefault(
"objects", {}
) # (objtype, name) -> docname, labelid

def note_object(
self, objtype: str, name: str, labelid: str, location: t.Any = None
) -> None:
if (objtype, name) in self.objects:
docname = self.objects[objtype, name][0]
logger.warning(
f"Duplicate {objtype} description of {name}, other instance in {docname}",
location=location,
)
self.objects[objtype, name] = (self.env.docname, labelid)

def merge_domaindata(self, docnames: list[str], otherdata: dict) -> None:
"""Merge in data regarding *docnames* from a different domaindata
inventory (coming from a subprocess in parallel builds).
"""

def resolve_any_xref(
self,
env: BuildEnvironment,
fromdocname: str,
builder: Builder,
target: str,
node: addnodes.pending_xref,
contnode: Element,
) -> list[tuple[str, Element]]:
"""Resolve the pending_xref *node* with the given *target*."""
return []


class _Plugin(YAMLDirective[AnsiblePlugin]):
schema = AnsiblePlugin

Expand Down Expand Up @@ -241,16 +198,12 @@ def _run(
title = titles[0]
self.state.document.note_explicit_target(title)
std = t.cast(StandardDomain, self.env.get_domain("std"))
rst_id = (
f"ansible_collections.{content.fqcn}_{content.plugin_type}_requirements"
rst_id = get_requirements_ref(
content.fqcn, content.plugin_type, content.role_entrypoint
)
plugin_name = _plugin_name(content.fqcn, content.plugin_type)
ref_title = f"Requirements of the {plugin_name}"
if content.role_entrypoint is not None and content.plugin_type == "role":
rst_id = (
f"ansible_collections.{content.fqcn}_role"
f"-{content.role_entrypoint}_requirements"
)
ref_title = f"{ref_title}, {content.role_entrypoint} entrypoint"
std.note_hyperlink_target(
rst_id,
Expand All @@ -270,9 +223,8 @@ class _Attribute(YAMLDirective[AnsibleAttribute]):

def _run(self, content_str: str, content: AnsibleAttribute) -> list[nodes.Node]:
html_id = f"attribute-{_percent_encode(content.name)}"
rst_id = (
f"ansible_collections.{content.fqcn}_{content.plugin_type}"
f"__attribute-{content.name}"
rst_id = get_attribute_ref(
content.fqcn, content.plugin_type, content.role_entrypoint, content.name
)
node = ansible_attribute(
"", content.name, classes=["ansible-option-title"], ids=[html_id]
Expand Down Expand Up @@ -309,17 +261,16 @@ def _compile_ids(
role_entrypoint: str | None,
full_keys: list[list[str]],
prefix_type: str,
get_ref: t.Callable[[str, str, str | None, list[str]], str],
) -> tuple[dict[str, tuple[str, str, str]], list[str]]:
rst_id_prefix = f"ansible_collections.{fqcn}_{plugin_type}__{prefix_type}-"
html_id_prefix = f"{prefix_type}-"
if role_entrypoint is not None:
rst_id_prefix += f"{role_entrypoint}__"
html_id_prefix += f"{role_entrypoint}--"
rst_ids = {}
html_ids = []
for full_key in full_keys:
html_id = html_id_prefix + "/".join([_percent_encode(k) for k in full_key])
rst_id = rst_id_prefix + "/".join([massage_rst_label(k) for k in full_key])
rst_id = get_ref(fqcn, plugin_type, role_entrypoint, full_key)
html_ids.append(html_id)
rst_ids[rst_id] = (html_id, ".".join(full_key), ".".join(full_key[1:]))
return rst_ids, _make_unique(html_ids)
Expand All @@ -335,6 +286,7 @@ def _run(self, content_str: str, content: AnsibleOption) -> list[nodes.Node]:
content.role_entrypoint,
content.full_keys,
"parameter",
get_option_ref,
)
node = ansible_option(
"",
Expand Down Expand Up @@ -392,6 +344,7 @@ def _run(self, content_str: str, content: AnsibleReturnValue) -> list[nodes.Node
content.role_entrypoint,
content.full_keys,
"return",
get_return_value_ref,
)
node = ansible_return_value(
"",
Expand Down Expand Up @@ -446,6 +399,5 @@ def setup_directives(app):
"""
Setup directives for a Sphinx app object.
"""
app.add_domain(AnsibleDomain)
for name, directive in DIRECTIVES.items():
app.add_directive(name, directive)
Loading

0 comments on commit 8709d51

Please sign in to comment.