From 166a0e312aebc6247207c7abf6a49e6b28066b57 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Wed, 28 Feb 2024 10:48:55 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20Add=20better=20typing=20for=20`e?= =?UTF-8?q?xtra=5Flinks`=20config=20variable=20(#1131)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To detail all possible dict keys --- sphinx_needs/config.py | 37 ++++++++++++++++++++++------- sphinx_needs/directives/needflow.py | 20 +++++++--------- sphinx_needs/needs.py | 4 ++-- sphinx_needs/roles/need_outgoing.py | 2 +- sphinx_needs/utils.py | 4 ++-- 5 files changed, 41 insertions(+), 26 deletions(-) diff --git a/sphinx_needs/config.py b/sphinx_needs/config.py index df26d2fe8..e401afcc1 100644 --- a/sphinx_needs/config.py +++ b/sphinx_needs/config.py @@ -10,6 +10,7 @@ if TYPE_CHECKING: from sphinx.util.logging import SphinxLoggerAdapter + from typing_extensions import Required from sphinx_needs.data import NeedsInfoType @@ -115,6 +116,31 @@ class ExternalSource(TypedDict, total=False): """ +class LinkOptionsType(TypedDict, total=False): + """Options for links between needs""" + + option: Required[str] + """The name of the link option""" + incoming: str + """The incoming link title""" + outgoing: str + """The outgoing link title""" + copy: bool + """Copy to common links data. Default: True""" + color: str + """Used for needflow. Default: #000000""" + style: str + """Used for needflow. Default: solid""" + style_part: str + """Used for needflow. Default: '[dotted]'""" + style_start: str + """Used for needflow. Default: '-'""" + style_end: str + """Used for needflow. Default: '->'""" + allow_dead_links: bool + """If True, add a 'forbidden' class to dead links""" + + @dataclass class NeedsSphinxConfig: """A wrapper around the Sphinx configuration, @@ -291,17 +317,10 @@ def __setattr__(self, name: str, value: Any) -> None: default="→\xa0", metadata={"rebuild": "html", "types": (str,)} ) """Prefix for need_part output in tables""" - extra_links: list[dict[str, Any]] = field( + extra_links: list[LinkOptionsType] = field( default_factory=list, metadata={"rebuild": "html", "types": ()} ) - """List of additional links, which can be used by setting related option - Values needed for each new link: - * option (will also be the option name) - * incoming - * copy_link (copy to common links data. Default: True) - * color (used for needflow. Default: #000000) - Example: [{"name": "blocks, "incoming": "is blocked by", "copy_link": True, "color": "#ffcc00"}] - """ + """List of additional link types between needs""" report_dead_links: bool = field( default=True, metadata={"rebuild": "html", "types": (bool,)} ) diff --git a/sphinx_needs/directives/needflow.py b/sphinx_needs/directives/needflow.py index 95856bcc2..897ea2de6 100644 --- a/sphinx_needs/directives/needflow.py +++ b/sphinx_needs/directives/needflow.py @@ -398,10 +398,8 @@ def process_needflow( else: comment = "" - if link_type.get("style_part"): - link_style = "[{style}]".format( - style=link_type["style_part"] - ) + if _style_part := link_type.get("style_part"): + link_style = f"[{_style_part}]" else: link_style = "[dotted]" else: @@ -414,10 +412,8 @@ def process_needflow( else: comment = "" - if link_type.get("style"): - link_style = "[{style}]".format( - style=link_type["style"] - ) + if _style := link_type.get("style"): + link_style = f"[{_style}]" else: link_style = "" @@ -429,13 +425,13 @@ def process_needflow( ]: continue - if link_type.get("style_start"): - style_start = link_type["style_start"] + if _style_start := link_type.get("style_start"): + style_start = _style_start else: style_start = "-" - if link_type.get("style_end"): - style_end = link_type["style_end"] + if _style_end := link_type.get("style_end"): + style_end = _style_end else: style_end = "->" diff --git a/sphinx_needs/needs.py b/sphinx_needs/needs.py index 9b802e5e4..1930e3c34 100644 --- a/sphinx_needs/needs.py +++ b/sphinx_needs/needs.py @@ -19,7 +19,7 @@ build_needs_json, build_needumls_pumls, ) -from sphinx_needs.config import NEEDS_CONFIG, NeedsSphinxConfig +from sphinx_needs.config import NEEDS_CONFIG, LinkOptionsType, NeedsSphinxConfig from sphinx_needs.data import SphinxNeedsData, merge_data from sphinx_needs.defaults import ( LAYOUTS, @@ -518,7 +518,7 @@ def prepare_env(app: Sphinx, env: BuildEnvironment, _docname: str) -> None: # The default link name. Must exist in all configurations. Therefore we set it here # for the user. - common_links = [] + common_links: list[LinkOptionsType] = [] link_types = needs_config.extra_links basic_link_type_found = False parent_needs_link_type_found = False diff --git a/sphinx_needs/roles/need_outgoing.py b/sphinx_needs/roles/need_outgoing.py index c6391129d..ea20ba809 100644 --- a/sphinx_needs/roles/need_outgoing.py +++ b/sphinx_needs/roles/need_outgoing.py @@ -122,7 +122,7 @@ def process_need_outgoing( # add a CSS class for disallowed unknown links # note a warning is already emitted when validating the needs list # so we don't need to do it here - if not link_lookup.get(link_type, {}).get("allow_dead_links", False): + if not link_lookup.get(link_type, {}).get("allow_dead_links", False): # type: ignore dead_link_para.attributes["classes"].append("forbidden") # If we have several links, we add an empty text between them diff --git a/sphinx_needs/utils.py b/sphinx_needs/utils.py index 8887a3243..b2d507eea 100644 --- a/sphinx_needs/utils.py +++ b/sphinx_needs/utils.py @@ -14,7 +14,7 @@ from jinja2 import Environment, Template from sphinx.application import BuildEnvironment, Sphinx -from sphinx_needs.config import NeedsSphinxConfig +from sphinx_needs.config import LinkOptionsType, NeedsSphinxConfig from sphinx_needs.data import NeedsInfoType, SphinxNeedsData from sphinx_needs.defaults import NEEDS_PROFILING from sphinx_needs.logging import get_logger @@ -279,7 +279,7 @@ def rstjinja(app: Sphinx, docname: str, source: list[str]) -> None: def import_prefix_link_edit( - needs: dict[str, Any], id_prefix: str, needs_extra_links: list[dict[str, Any]] + needs: dict[str, Any], id_prefix: str, needs_extra_links: list[LinkOptionsType] ) -> None: """ Changes existing links to support given prefix.