Skip to content

Commit

Permalink
✨ Allow configuring description of extra option (#1338)
Browse files Browse the repository at this point in the history
This commit allows for using a dict to define a `needs_extra_options` item, that can have both a `name` and (optional) `description` key, e.g.:

```python
needs_extra_options = [
    "introduced",
    {"name": "impacts", "description": "What is the impact of this need?"},
]
```

This also allows for future addition of more optional keys
  • Loading branch information
chrisjsewell authored Oct 28, 2024
1 parent 43a43b8 commit 7a3e9ef
Show file tree
Hide file tree
Showing 6 changed files with 593 additions and 20 deletions.
22 changes: 20 additions & 2 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ For example:
{directive="spec", title="Specification", prefix="S_", color="#FEDCD2", style="node"},
]
To specify a different `table path <https://toml.io/en/v1.0.0#table>`__ to read from in the toml file, use the ``needs_from_toml_table`` option.
To specify a different `root table path <https://toml.io/en/v1.0.0#table>`__ to read from in the toml file, use the ``needs_from_toml_table`` option.
For example to read from a ``[tool.needs]`` table:

.. code-block:: python
needs_from_toml_table = ["tool", "needs"]
needs_from_toml_table = ["tool"]
.. caution:: Any configuration specifying relative paths in the toml file will be resolved relative to the directory containing the :file:`conf.py` file.

Expand Down Expand Up @@ -256,6 +256,24 @@ And use it like:
.. needlist::
:filter: "filter_me" in another_option

.. versionadded:: 4.1.0

Values in the list can also be dictionaries, with keys:

* ``name``: The name of the option (required).
* ``description``: A description of the option (optional).
This will be output in the schema of the :ref:`needs.json <needs_builder_format>`,
and can be used by other tools.

For example:

.. code-block:: python
needs_extra_options = [
"my_extra_option",
{"name": "my_other_option", "description": "This is a description of the option"}
]
.. _needs_global_options:

needs_global_options
Expand Down
14 changes: 11 additions & 3 deletions sphinx_needs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,14 @@ class NeedType(TypedDict):
"""The default node style to use in diagrams (default: "node")."""


class NeedExtraOption(TypedDict):
"""Defines an extra option for needs"""

name: str
description: NotRequired[str]
"""A description of the option."""


@dataclass
class NeedsSphinxConfig:
"""A wrapper around the Sphinx configuration,
Expand Down Expand Up @@ -313,9 +321,9 @@ def get_default(cls, name: str) -> Any:
"""Path to a TOML file to load configuration from."""

from_toml_table: list[str] = field(
default_factory=lambda: ["needs"], metadata={"rebuild": "env", "types": (list,)}
default_factory=list, metadata={"rebuild": "env", "types": (list,)}
)
"""Path to the table in the toml file to load configuration from."""
"""Path to the root table in the toml file to load configuration from."""

types: list[NeedType] = field(
default_factory=lambda: [
Expand Down Expand Up @@ -407,7 +415,7 @@ def get_default(cls, name: str) -> Any:
default=30, metadata={"rebuild": "html", "types": (int,)}
)
"""Maximum length of the title in the need role output."""
_extra_options: list[str] = field(
_extra_options: list[str | NeedExtraOption] = field(
default_factory=list, metadata={"rebuild": "html", "types": (list,)}
)
"""List of extra options for needs, that get added as directive options and need fields."""
Expand Down
37 changes: 31 additions & 6 deletions sphinx_needs/needs.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def load_config_from_toml(app: Sphinx, config: Config) -> None:
try:
with toml_file.open("rb") as f:
toml_data = tomllib.load(f)
for key in toml_path:
for key in (*toml_path, "needs"):
toml_data = toml_data[key]
assert isinstance(toml_data, dict), "Data must be a dict"
except Exception as e:
Expand All @@ -411,15 +411,40 @@ def load_config(app: Sphinx, *_args: Any) -> None:
needs_config = NeedsSphinxConfig(app.config)

if isinstance(needs_config._extra_options, dict):
LOGGER.info(
log_warning(
LOGGER,
'Config option "needs_extra_options" supports list and dict. However new default type since '
"Sphinx-Needs 0.7.2 is list. Please see docs for details."
"Sphinx-Needs 0.7.2 is list. Please see docs for details.",
"config",
None,
)

for option in needs_config._extra_options:
_NEEDS_CONFIG.add_extra_option(
option, "Added by needs_extra_options config", override=True
)
description = "Added by needs_extra_options config"
if isinstance(option, str):
name = option
elif isinstance(option, dict):
try:
name = option["name"]
except KeyError:
log_warning(
LOGGER,
f"extra_option is a dict, but does not contain a 'name' key: {option}",
"config",
None,
)
continue
description = option.get("description", description)
else:
log_warning(
LOGGER,
f"extra_option is not a string or dict: {option}",
"config",
None,
)
continue

_NEEDS_CONFIG.add_extra_option(name, description, override=True)

# ensure options for ``needgantt`` functionality are added to the extra options
for option in (needs_config.duration_option, needs_config.completion_option):
Expand Down
Loading

0 comments on commit 7a3e9ef

Please sign in to comment.