Skip to content

Commit

Permalink
exclude needs under only directive if required (useblocks#1103)
Browse files Browse the repository at this point in the history
  • Loading branch information
David-Le-Nir committed Feb 9, 2024
1 parent 73b961e commit 6f788ef
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
13 changes: 13 additions & 0 deletions sphinx_needs/directives/need.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ def analyse_need_locations(app: Sphinx, doctree: nodes.document) -> None:
if need_node.get("hidden"):
hidden_needs.append(need_node)

if need_node_excluded_by_only_directive(env, need_node):
hidden_needs.append(need_node)

# now we have gathered all the information we need,
# we can remove the hidden needs from the doctree
for need_node in hidden_needs:
Expand All @@ -356,6 +359,16 @@ def previous_sibling(node: nodes.Node) -> Optional[nodes.Node]:
return node.parent[i - 1] if i > 0 else None # type: ignore


def need_node_excluded_by_only_directive(env: BuildEnvironment, node: nodes.Node) -> bool:
"""Return True if the node is under an "only" directive that shall be excluded given to the current tags"""
if hasattr(node.parent, "tagname") and node.parent.tagname == "only":
# note that we only check for a direct parent,
# maybe we should look recursively until we reach the root of the document
only_tags = node.parent.attributes.get("expr", "")
return env.app.builder.tags.eval_condition(only_tags)
return False


@profile("NEEDS_POST_PROCESS")
@measure_time("need_post_process")
def post_process_needs_data(app: Sphinx) -> None:
Expand Down
4 changes: 4 additions & 0 deletions tests/doc_test/doc_directive_only/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
extensions = ["sphinx_needs"]

# also build the needs.json as some needs shall be hidden in it too
needs_build_json = True
29 changes: 29 additions & 0 deletions tests/doc_test/doc_directive_only/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Only directive Test
=====================

.. only:: tag_a

.. req:: req_001

I shall not appear if not running tag_a

.. only:: tag_b

.. req:: req_002

I shall not appear if not running tag_b

.. only:: tag_a or tag_b

.. req:: req_003

I shall not appear if not running either tag_a or tag_b


.. req:: req_004

I shall always appear


.. needtable::
types: req
70 changes: 70 additions & 0 deletions tests/test_directive_only_exclusion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import json
from pathlib import Path

import pytest


@pytest.mark.parametrize(
"test_app",
[
{"buildername": "html", "srcdir": "doc_test/doc_directive_only", "tags": ["tag_a"]},
],
indirect=True,
)
def test_need_excluded_under_only_a(test_app):
app = test_app
app.build()
html = Path(app.outdir, "index.html").read_text()
needs_list = json.loads(Path(app.outdir, "needs.json").read_text())

assert "req_001" in html
assert "req_002" not in html
assert "req_003" in html
assert "req_004" in html

assert "req_001" in needs_list
assert "req_002" not in needs_list
assert "req_003" in needs_list
assert "req_004" in needs_list


@pytest.mark.parametrize(
"test_app",
[
{"buildername": "html", "srcdir": "doc_test/doc_directive_only", "tags": ["tag_a"]},
],
indirect=True,
)
def test_need_excluded_under_only_b(test_app):
app = test_app
app.build()
html = Path(app.outdir, "index.html").read_text()
needs_list = json.loads(Path(app.outdir, "needs.json").read_text())

assert "req_001" not in html
assert "req_002" in html
assert "req_003" in html
assert "req_004" in html

assert "req_001" not in needs_list
assert "req_002" in needs_list
assert "req_003" in needs_list
assert "req_004" in needs_list


@pytest.mark.parametrize("test_app", [{"buildername": "html", "srcdir": "doc_test/doc_directive_only"}], indirect=True)
def test_need_excluded_under_only_no_tag(test_app):
app = test_app
app.build()
html = Path(app.outdir, "index.html").read_text()
needs_list = json.loads(Path(app.outdir, "needs.json").read_text())

assert "req_001" not in html
assert "req_002" not in html
assert "req_003" not in html
assert "req_004" in html

assert "req_001" not in needs_list
assert "req_002" not in needs_list
assert "req_003" not in needs_list
assert "req_004" in needs_list

0 comments on commit 6f788ef

Please sign in to comment.