Skip to content

Commit 02eb6e7

Browse files
authored
πŸ› Inject build_tags to variant filter strings (#1531)
Instead of passing Sphinx tags directly into the context variable scope for filter strings, a new variable `build_tags` is injected which is a `set[str]`. This avoids namespace clutter and also `NameError`s when checking for tags. For now, this is only available for variants. Need to discuss whether to apply this to all filter strings.
1 parent 0e858ca commit 02eb6e7

File tree

8 files changed

+17
-18
lines changed

8 files changed

+17
-18
lines changed

β€Ždocs/configuration.rstβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2226,7 +2226,7 @@ For example, in ``conf.py``:
22262226
.. code-block:: python
22272227
22282228
needs_variants = {
2229-
"var_a": "'var_a' in sphinx_tags" # filter_string
2229+
"var_a": "'var_a' in build_tags" # filter_string
22302230
"var_b": "assignee == 'me'"
22312231
}
22322232

β€Ždocs/directives/need.rstβ€Ž

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,14 @@ Rules for specifying variant definitions
5151
* When evaluating a variant definition, we use data from the current need object,
5252
`Sphinx-Tags <https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-t>`_,
5353
and :ref:`needs_filter_data` as the context for filtering.
54+
Sphinx tags are injected under the name ``build_tags`` as a set of strings.
5455
* You can set a *need option* to multiple variant definitions by separating each definition with either
55-
the ``,`` symbol, like ``var_a:open, ['name' in tags]:assigned``. |br|
56+
the ``,`` symbol, like ``var_a:open, ['name' in tags]:assigned``.|br|
5657
With multiple variant definitions, we set the first matching variant as the *need option's* value.
5758
* When you set a *need option* to multiple variant definitions, you can specify the last definition as
5859
a default "variant-free" option which we can use if no variant definition matches. |br|
59-
Example; In this multi-variant definitions, ``[status in tags]:added, var_a:changed, unknown``, *unknown* will be used
60-
if none of the other variant definitions are True.
60+
Example; In this multi-variant definitions, ``[status in tags]:added, var_a:changed, unknown``,
61+
*unknown* will be used if none of the other variant definitions are True.
6162
* If you prefer your variant definitions to use rules instead of keys, then you should put your filter string
6263
inside square brackets like this: ``['name' in tags]:assigned``.
6364
* For multi-variant definitions, you can mix both rule and variant-named options like this:
@@ -82,7 +83,7 @@ For example, in your ``conf.py``:
8283
.. code-block:: python
8384
8485
needs_variants = {
85-
"var_a": "'var_a' in sphinx_tags" # filter_string
86+
"var_a": "'var_a' in build_tags" # filter_string, check for Sphinx tags
8687
"var_b": "assignee == 'me'"
8788
}
8889
@@ -95,7 +96,7 @@ In your ``.rst`` file:
9596
:status: <<var_a:open, var_b:closed, unknown>>
9697
9798
From the above example, if a *need option* has variants defined, then we get the filter string
98-
from our ``needs_variants`` configuration and evaluate it.
99+
from the ``needs_variants`` configuration and evaluate it.
99100
If a variant definition is true, then we set the *need option* to the value of the variant definition.
100101

101102
Use Case 2
@@ -139,7 +140,7 @@ In your ``.rst`` file:
139140
140141
.. req:: Example
141142
:id: VA_003
142-
:status: <<[tag_a and tag_b]:open, closed>>
143+
:status: <<['tag_a' in build_tags and 'tag_b' in build_tags]:open, closed>>
143144
144145
From the above example, if a tag is defined, the plugin can access it in the filter context when handling variants.
145146
If a variant definition is true, then we set the *need option* to the value of the variant definition.

β€Žsphinx_needs/functions/functions.pyβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ def resolve_functions(
314314
var_context: dict[str, Any] = {
315315
**need,
316316
**needs_config.filter_data,
317-
**dict.fromkeys(app.builder.tags, True),
317+
"build_tags": set(app.builder.tags),
318318
}
319319
if (
320320
var_return := _get_variant(

β€Žtests/__snapshots__/test_variants.ambrβ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
'sections': list([
1515
'Empty Variant Options Handling Test',
1616
]),
17-
'status': '<<[tag_a]:open, unknown>>',
17+
'status': 'open',
1818
'title': 'Empty Variant Options',
1919
'type': 'spec',
2020
'type_name': 'Specification',
@@ -75,6 +75,7 @@
7575
'sections': list([
7676
'Variant Handling Test',
7777
]),
78+
'status': 'unknown',
7879
'title': 'Unknown Variant',
7980
'type': 'spec',
8081
'type_name': 'Specification',

β€Žtests/doc_test/variant_doc/index.rstβ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Variant Handling Test
77

88
.. spec:: Tags Example
99
:id: VA_003
10-
:status: <<[tag_a and tag_b]:tags_implemented, closed>>
10+
:status: <<[all(x in build_tags for x in ['tag_a', 'tag_b'])]:tags_implemented, closed>>
1111

1212
.. story:: Test story
1313
:id: ST_001
@@ -24,11 +24,11 @@ Variant Handling Test
2424

2525
.. spec:: Variant Specification
2626
:id: SPEC_003
27-
:status: <<[tag_a]:open, unknown>>
27+
:status: <<['tag_a' in build_tags]:open, unknown>>
2828

2929
.. spec:: Unknown Variant
3030
:id: SPEC_004
31-
:status: <<[tag_c]:open, unknown>>
31+
:status: <<['tag_c' in build_tags]:open, unknown>>
3232

3333
.. needtable::
3434
:filter: status in ("open", "close", "progress")

β€Žtests/doc_test/variant_options/conf.pyβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
},
3939
]
4040
needs_variants = {"change_author": "assignee == 'Randy Duodu'"}
41-
needs_variant_options = []
41+
needs_variant_options = ["status"]
4242
needs_filter_data = {"assignee": "Randy Duodu"}
4343
needs_extra_options = [
4444
"my_extra_option",

β€Žtests/doc_test/variant_options/index.rstβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Empty Variant Options Handling Test
33

44
.. spec:: Empty Variant Options
55
:id: EMPTY_VAR_003
6-
:status: <<[tag_a]:open, unknown>>
6+
:status: <<['tag_a' in build_tags]:open, unknown>>
77

88
.. toctree::
99
:maxdepth: 2

β€Žtests/test_variants.pyβ€Ž

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,7 @@ def test_variant_options_html(test_app, snapshot):
6565
app.build()
6666

6767
warnings = strip_colors(app._warning.getvalue()).splitlines()
68-
# print(warnings)
69-
assert warnings == [
70-
f"{Path(str(app.srcdir)) / 'index.rst'}:29: WARNING: Error while resolving dynamic values for field 'status', of need 'SPEC_004': name 'tag_c' is not defined [needs.dynamic_function]"
71-
]
68+
assert warnings == []
7269

7370
needs = json.loads(Path(app.outdir, "needs.json").read_text())
7471
assert needs == snapshot(

0 commit comments

Comments
Β (0)