Skip to content

Commit e01b3ad

Browse files
⚠️ Migrate needs_extra_links to needs_links (#1649)
This PR introduces a new dict-based `needs_links` configuration and deprecates the list-based `needs_extra_links`. The change follows the plan in <#1646> and uses the same migration pattern as `needs_extra_options` → `needs_fields` (commit fc41bf2). ## Motivation - Consistent API design with `needs_fields` (dict-based config) - Enables a `description` field for link types (output in schema/needs.json) - Cleaner configuration syntax ## Changes ### New Configuration Format ```python # New (needs_links) needs_links = { "blocks": { "description": "Blocking relationship between needs", "incoming": "is blocked by", "outgoing": "blocks", }, } # Deprecated (needs_extra_links) needs_extra_links = [ { "option": "blocks", "incoming": "is blocked by", "outgoing": "blocks", }, ] ``` ## Backward Compatibility - `needs_extra_links` continues to work but emits a deprecation warning - Internal processing converts both formats to the same representation - Error messages reference the correct config option based on source ## New Features - **`description` field**: Link types can now include a description that appears in the JSON schema output - **Dict-based syntax**: Link name is the key, making configuration cleaner --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 384f269 commit e01b3ad

59 files changed

Lines changed: 1341 additions & 1317 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ Schema
6565
:members: FieldStringSchemaType, FieldBooleanSchemaType,
6666
FieldIntegerSchemaType, FieldNumberSchemaType,
6767
FieldMultiValueSchemaType,
68-
ExtraLinkSchemaType, ExtraLinkItemSchemaType
68+
LinkSchemaType, LinkItemSchemaType

docs/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ Changelog
1818

1919
Ensure that file paths originating from a :ref:`needs_from_toml` file are relative to that file, rather than the :file:`conf.py` file
2020

21+
- ✨ Add new ``needs_links`` configuration (dict-based) as replacement for ``needs_extra_links`` (list-based)
22+
23+
The new :ref:`needs_links` configuration uses a dictionary mapping link name to configuration,
24+
removing the redundant ``option`` key required in :ref:`needs_extra_links`.
25+
Also adds support for a ``description`` field for link types.
26+
The old ``needs_extra_links`` configuration is now deprecated but remains supported for backward compatibility.
27+
2128
.. _`release:6.2.0`:
2229

2330
6.2.0

docs/configuration.rst

Lines changed: 122 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ For ``predicates``, the match expression is a string, using Python syntax, that
339339
- ``is_external`` (``bool``)
340340
- ``is_import`` (``bool``)
341341
- :ref:`needs_fields`
342-
- :ref:`needs_extra_links` (``tuple[str, ...]``)
342+
- :ref:`needs_links` (``tuple[str, ...]``)
343343
- :ref:`needs_filter_data`
344344

345345
For example:
@@ -360,58 +360,58 @@ For example:
360360
},
361361
}
362362
363-
.. _`needs_extra_links`:
363+
.. _`needs_links`:
364364

365-
needs_extra_links
366-
~~~~~~~~~~~~~~~~~
365+
needs_links
366+
~~~~~~~~~~~
367367

368-
.. versionadded:: 0.3.11
368+
.. versionadded:: 7.0.0
369369

370-
Allows the definition of additional link types.
370+
Allows the definition of additional link types as a dictionary mapping link name to configuration.
371371

372-
Each configured link should define:
372+
Each configured link can define:
373373

374-
- ``option``: The name of the option. Example "blocks".
374+
- ``description`` (optional): A description of the link type.
375375
- ``predicates`` (optional): A list of ``(match expression, value)`` tuples.
376376
If specified, these will be evaluated in order for any need that does not explicitly set the field, with the first match setting the field value.
377377
- ``default`` (optional): A default value for the field.
378378
If specified, this value will be used for any need that does not explicitly set the field and does not match any predicates.
379379
- ``parse_variants``: If set to ``True``, the field will support :ref:`variant options <needs_variant_support>`.
380380
Default: ``False``.
381-
- ``incoming`` (optional): Incoming text, to use for incoming links. E.g. "is blocked by".
382-
- ``outgoing`` (optional): Outgoing text, to use for outgoing links. E.g. "blocks".
381+
- ``incoming`` (optional): Incoming text, to use for incoming links. E.g. "is blocked by". Default: "<name> incoming".
382+
- ``outgoing`` (optional): Outgoing text, to use for outgoing links. E.g. "blocks". Default: "<name>".
383383
- ``copy`` (optional): True/False. If True, the links will be copied also to the common link-list (link type ``links``).
384-
Default: True
384+
Default: False.
385385
- ``allow_dead_links`` (optional): True/False. If True, dead links are allowed and do not throw a warning.
386386
See :ref:`allow_dead_links` for details. Default: False.
387387
- ``style`` (optional): A plantuml style description, e.g. "#FFCC00". Used for :ref:`needflow`. See :ref:`links_style`.
388388
- ``style_part`` (optional): Same as ``style``, but get used if link is connected to a :ref:`need_part`.
389389
See :ref:`links_style`.
390+
- ``style_start`` (optional): See :ref:`needflow_style_start`.
391+
- ``style_end`` (optional): See :ref:`needflow_style_start`.
390392

391393
Configuration example:
392394

393395
.. code-block:: python
394396
395-
needs_extra_links = [
396-
{
397-
"option": "checks",
398-
},
399-
{
400-
"option": "triggers",
401-
"predicates": [
402-
('"urgent" in tags', ["ID999", "ID998"]),
403-
],
404-
"default": ["ID123"],
405-
"incoming": "is triggered by",
406-
"outgoing": "triggers",
407-
"copy": False,
408-
"allow_dead_links": True,
409-
"style": "#00AA00",
410-
"style_part": "#00AA00",
411-
"style_start": "-",
412-
"style_end": "--o",
413-
}
414-
]
397+
needs_links = {
398+
"checks": {},
399+
"triggers": {
400+
"description": "Links to needs that are triggered by this need",
401+
"predicates": [
402+
('"urgent" in tags', ["ID999", "ID998"]),
403+
],
404+
"default": ["ID123"],
405+
"incoming": "is triggered by",
406+
"outgoing": "triggers",
407+
"copy": False,
408+
"allow_dead_links": True,
409+
"style": "#00AA00",
410+
"style_part": "#00AA00",
411+
"style_start": "-",
412+
"style_end": "--o",
413+
},
414+
}
415415
416416
The above example configuration allows the following usage:
417417

@@ -425,8 +425,8 @@ The above example configuration allows the following usage:
425425
:checks: EXTRA_REQ_001, DEAD_LINK_NOT_ALLOWED
426426
:triggers: DEAD_LINK
427427

428-
Link types with option-name **links** and **parent_needs** are added by default.
429-
You are free to overwrite the default config by defining your own type with option name **links** or **parent_needs**.
428+
Link types with name **links** and **parent_needs** are added by default.
429+
You are free to overwrite the default config by defining your own type with name **links** or **parent_needs**.
430430
This type will be used as default configuration for all links.
431431

432432
Default values
@@ -447,26 +447,25 @@ For ``predicates``, the match expression is a string, using Python syntax, that
447447
- ``is_external`` (``bool``)
448448
- ``is_import`` (``bool``)
449449
- :ref:`needs_fields`
450-
- :ref:`needs_extra_links` (``tuple[str, ...]``)
450+
- :ref:`needs_links` (``tuple[str, ...]``)
451451
- :ref:`needs_filter_data`
452452

453453
For example:
454454

455455
.. code-block:: python
456456
457-
needs_extra_links = [
458-
{
459-
"option": "custom_link",
460-
"predicates": [
461-
# if status is "done", set to ["ID123"]
462-
("status == 'done'", ["ID123"]),
463-
# else if status is "ongoing", set to a dynamic value
464-
("status == 'ongoing'", '[[copy("yyy")]]'),
465-
],
466-
# the base default is a dynamic value
467-
"default": '[[copy("xxx")]]',
468-
},
469-
]
457+
needs_links = {
458+
"custom_link": {
459+
"predicates": [
460+
# if status is "done", set to ["ID123"]
461+
("status == 'done'", ["ID123"]),
462+
# else if status is "ongoing", set to a dynamic value
463+
("status == 'ongoing'", '[[copy("yyy")]]'),
464+
],
465+
# the base default is a dynamic value
466+
"default": '[[copy("xxx")]]',
467+
},
468+
}
470469
471470
.. _`allow_dead_links`:
472471

@@ -547,18 +546,17 @@ Use ``style_start`` and ``style_end`` like this:
547546

548547
.. code-block:: python
549548
550-
needs_extra_links = [
551-
{
552-
"option": "tests",
553-
"incoming": "is tested by",
554-
"outgoing": "tests",
555-
"copy": False,
556-
"style_start": "<-",
557-
"style_end": "down-->",
558-
"style": "#00AA00",
559-
"style_part": "dotted,#00AA00",
560-
}
561-
]
549+
needs_links = {
550+
"tests": {
551+
"incoming": "is tested by",
552+
"outgoing": "tests",
553+
"copy": False,
554+
"style_start": "<-",
555+
"style_end": "down-->",
556+
"style": "#00AA00",
557+
"style_part": "dotted,#00AA00",
558+
},
559+
}
562560
563561
.. note::
564562

@@ -845,9 +843,9 @@ If you do not set ``needs_report_template``, the default template used is:
845843
{% endif %}
846844
{# Output for needs_types #}
847845
848-
{# Output for needs_extra_links #}
846+
{# Output for needs_links #}
849847
{% if links|length != 0 %}
850-
.. dropdown:: Need Extra Links
848+
.. dropdown:: Need Links
851849
:class: needs_report_table
852850
853851
.. list-table::
@@ -867,11 +865,11 @@ If you do not set ``needs_report_template``, the default template used is:
867865
- {{ link.get('allow_dead_links', False) | capitalize }}
868866
{% endfor %}
869867
{% endif %}
870-
{# Output for needs_extra_links #}
868+
{# Output for needs_links #}
871869
872870
{# Output for needs_fields #}
873871
{% if fields|length != 0 %}
874-
.. dropdown:: Need Extra Options
872+
.. dropdown:: Need Fields
875873
:class: needs_report_table
876874
877875
{% for field in fields %}
@@ -902,7 +900,7 @@ If you do not set ``needs_report_template``, the default template used is:
902900
The plugin provides the following variables which you can use in your custom Jinja template:
903901

904902
* types - list of :ref:`need types <needs_types>`
905-
* links - list of :ref:`needs_extra_links`
903+
* links - list of :ref:`needs_links`
906904
* fields - list of :ref:`needs_fields`
907905
* usage - a dictionary object containing information about the following:
908906
+ needs_amount -> total amount of need objects in the project
@@ -2368,7 +2366,7 @@ Default value::
23682366

23692367
[
23702368
"field_success",
2371-
"extra_link_success",
2369+
"link_success",
23722370
"select_success",
23732371
"select_fail",
23742372
"local_success",
@@ -2390,8 +2388,8 @@ Available scenarios that can be ignored:
23902388
- ``cfg_schema_error``: The user provided schema is invalid
23912389
- ``field_success``: Global field validation was successful
23922390
- ``field_fail``: Global field validation failed
2393-
- ``extra_link_success``: Global extra link validations was successful
2394-
- ``extra_link_fail``: Global extra link validation failed
2391+
- ``link_success``: Global extra link validations was successful
2392+
- ``link_fail``: Global extra link validation failed
23952393
- ``select_success``: Successful select validation
23962394
- ``select_fail``: Failed select validation
23972395
- ``local_success``: Successful local validation
@@ -2535,7 +2533,7 @@ needs_global_options
25352533

25362534
.. deprecated:: 7.0.0
25372535

2538-
Use :ref:`needs_fields` and :ref:`needs_extra_links` instead.
2536+
Use :ref:`needs_fields` and :ref:`needs_links` instead.
25392537

25402538
.. versionchanged:: 5.1.0
25412539

@@ -2584,7 +2582,7 @@ This configuration allows for global defaults to be set for all needs,
25842582
for any of the following fields:
25852583

25862584
- any :ref:`needs_fields` key
2587-
- any ``needs_extra_links`` field
2585+
- any :ref:`needs_links` field
25882586
- ``status``
25892587
- ``layout``
25902588
- ``style``
@@ -2615,7 +2613,7 @@ A match expression is a string, using Python syntax, that will be evaluated agai
26152613
- ``is_external`` (``bool``)
26162614
- ``is_import`` (``bool``)
26172615
- :ref:`needs_fields`
2618-
- :ref:`needs_extra_links` (``tuple[str, ...]``)
2616+
- :ref:`needs_links` (``tuple[str, ...]``)
26192617
- :ref:`needs_filter_data`
26202618

26212619
If no predicates match, the ``default`` value is used (if present).
@@ -2754,3 +2752,57 @@ Configuration example:
27542752
.. code-block:: python
27552753
27562754
needs_report_dead_links = False
2755+
2756+
.. _`needs_extra_links`:
2757+
2758+
needs_extra_links
2759+
~~~~~~~~~~~~~~~~~
2760+
2761+
.. deprecated:: 4.4.0
2762+
Use :ref:`needs_links` instead.
2763+
2764+
Allows the definition of additional link types as a list.
2765+
2766+
Each configured link should define:
2767+
2768+
- ``option``: The name of the option. Example "blocks".
2769+
- ``predicates`` (optional): A list of ``(match expression, value)`` tuples.
2770+
If specified, these will be evaluated in order for any need that does not explicitly set the field, with the first match setting the field value.
2771+
- ``default`` (optional): A default value for the field.
2772+
If specified, this value will be used for any need that does not explicitly set the field and does not match any predicates.
2773+
- ``parse_variants``: If set to ``True``, the field will support :ref:`variant options <needs_variant_support>`.
2774+
Default: ``False``.
2775+
- ``incoming`` (optional): Incoming text, to use for incoming links. E.g. "is blocked by".
2776+
- ``outgoing`` (optional): Outgoing text, to use for outgoing links. E.g. "blocks".
2777+
- ``copy`` (optional): True/False. If True, the links will be copied also to the common link-list (link type ``links``).
2778+
Default: True
2779+
- ``allow_dead_links`` (optional): True/False. If True, dead links are allowed and do not throw a warning.
2780+
See :ref:`allow_dead_links` for details. Default: False.
2781+
- ``style`` (optional): A plantuml style description, e.g. "#FFCC00". Used for :ref:`needflow`. See :ref:`links_style`.
2782+
- ``style_part`` (optional): Same as ``style``, but get used if link is connected to a :ref:`need_part`.
2783+
See :ref:`links_style`.
2784+
2785+
Configuration example:
2786+
2787+
.. code-block:: python
2788+
2789+
needs_extra_links = [
2790+
{
2791+
"option": "checks",
2792+
},
2793+
{
2794+
"option": "triggers",
2795+
"predicates": [
2796+
('"urgent" in tags', ["ID999", "ID998"]),
2797+
],
2798+
"default": ["ID123"],
2799+
"incoming": "is triggered by",
2800+
"outgoing": "triggers",
2801+
"copy": False,
2802+
"allow_dead_links": True,
2803+
"style": "#00AA00",
2804+
"style_part": "#00AA00",
2805+
"style_start": "-",
2806+
"style_end": "--o",
2807+
}
2808+
]

docs/directives/need.rst

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,30 +126,26 @@ You can easily set links to multiple needs by using **;** as a separator.
126126

127127
This sets a link to id ``REQ_LINK_1``.
128128

129-
.. _need_extra_links:
130-
131129
extra links
132130
+++++++++++
133131

134-
By using :ref:`needs_extra_links <needs_extra_links>`, you can use the configured link-types to set additional **need** options.
132+
By using :ref:`needs_links <needs_links>`, you can use the configured link-types to set additional **need** options.
135133

136134
.. code-block:: python
137135
138136
# conf.py
139-
needs_extra_links = [
140-
{
141-
"option": "blocks",
137+
needs_links = {
138+
"blocks": {
142139
"incoming": "is blocked by",
143140
"outgoing": "blocks"
144141
},
145-
{
146-
"option": "tests",
142+
"tests": {
147143
"incoming": "is tested by",
148144
"outgoing": "tests",
149145
"copy": False,
150146
"color": "#00AA00"
151147
}
152-
]
148+
}
153149
154150
.. need-example::
155151

docs/directives/needflow.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ show_link_names
201201
Adds the link type name beside connections.
202202

203203
You can configure it globally by setting :ref:`needs_flow_show_links` in **conf.py**.
204-
Setup data can be found in test case document ``tests/doc_test/doc_extra_links``.
204+
Setup data can be found in test case document ``tests/doc_test/doc_links``.
205205

206206
.. need-example::
207207

@@ -243,7 +243,7 @@ You can avoid this by not setting **"links**" in the ``link_type`` option.
243243

244244
You can set this option globally via the configuration option :ref:`needs_flow_link_types`.
245245

246-
See also :ref:`needs_extra_links` for more details about specific link types.
246+
See also :ref:`needs_links` for more details about specific link types.
247247

248248
.. need-example::
249249

0 commit comments

Comments
 (0)