Skip to content

Commit

Permalink
👌 Allow ref in neeuml to handle need parts (#1222)
Browse files Browse the repository at this point in the history
Co-authored-by: Chris Sewell <[email protected]>
  • Loading branch information
PhilipPartsch and chrisjsewell authored Oct 8, 2024
1 parent 4120c18 commit fa937f2
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 21 deletions.
32 changes: 22 additions & 10 deletions sphinx_needs/directives/needuml.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
from sphinx_needs.directives.needflow._plantuml import make_entity_name
from sphinx_needs.filter_common import filter_needs_view
from sphinx_needs.logging import log_warning
from sphinx_needs.utils import add_doc, logger
from sphinx_needs.roles.need_part import create_need_from_part
from sphinx_needs.roles.need_ref import value_to_string
from sphinx_needs.utils import add_doc, logger, split_need_id

if TYPE_CHECKING:
from sphinxcontrib.plantuml import plantuml
Expand Down Expand Up @@ -401,24 +403,34 @@ def flow(self, need_id: str) -> str:
def ref(
self, need_id: str, option: None | str = None, text: None | str = None
) -> str:
if need_id not in self.needs:
need_id_main, need_id_part = split_need_id(need_id)

if need_id_main not in self.needs:
raise NeedumlException(
f"Jinja function ref is called with undefined need_id: '{need_id}'."
f"Jinja function ref is called with undefined need_id: '{need_id_main}'."
)
if (option and text) and (not option and not text):
raise NeedumlException(
"Jinja function ref requires exactly one entry 'option' or 'text'"
)

need_info = self.needs[need_id]
link = calculate_link(self.app, need_info, self.fromdocname)
need_info = self.needs[need_id_main]

need_uml = "[[{link} {content}]]".format(
link=link,
content=need_info.get(option, "") if option else text,
)
if need_id_part:
if need_id_part not in need_info["parts"]:
raise NeedumlException(
f"Jinja function ref is called with undefined need_id part: '{need_id}'."
)
need_info = create_need_from_part(
need_info, need_info["parts"][need_id_part]
)

return need_uml
link = calculate_link(self.app, need_info, self.fromdocname)
link_text = (
value_to_string(need_info.get(option, "")) if option else str(text or "")
).strip()

return f"[[{link}{' ' if link_text else ''}{link_text}]]"

def filter(self, filter_string: str) -> list[NeedsInfoType]:
"""
Expand Down
23 changes: 14 additions & 9 deletions sphinx_needs/roles/need_ref.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import contextlib
from collections.abc import Iterable
from typing import Any

from docutils import nodes
from sphinx.application import Sphinx
Expand Down Expand Up @@ -38,19 +39,23 @@ def transform_need_to_dict(need: NeedsInfoType) -> dict[str, str]:
dict_need = {}

for element, value in need.items():
if isinstance(value, str):
# As string are iterable, we have to handle strings first.
dict_need[element] = value
elif isinstance(value, dict):
dict_need[element] = ";".join([str(i) for i in value.items()])
elif isinstance(value, (Iterable, list, tuple)):
dict_need[element] = ";".join([str(i) for i in value])
else:
dict_need[element] = str(value)
dict_need[element] = value_to_string(value)

return dict_need


def value_to_string(value: Any) -> str:
if isinstance(value, str):
# As string are iterable, we have to handle strings first.
return value
elif isinstance(value, dict):
return ";".join([str(i) for i in value.items()])
elif isinstance(value, (Iterable, list, tuple)):
return ";".join([str(i) for i in value])

return str(value)


def process_need_ref(
app: Sphinx,
doctree: nodes.document,
Expand Down
12 changes: 11 additions & 1 deletion tests/__snapshots__/test_needuml.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -1251,12 +1251,22 @@
'content': '''
DC -> Marvel: {{ref("ST_001", option="title")}}
Marvel --> DC: {{ref("ST_002", text="Different text to explain the story")}}

DC -> Marvel: {{ref("ST_001.np_id", option="id")}}
Marvel --> DC: {{ref("ST_001.np_id", option="content")}}

DC -> Marvel: {{ref("ST_001.np_id", text="Different text to explain the story 2")}}
''',
'content_calculated': '''
@startuml

DC -> Marvel: [[../index.html#ST_001 Test story]]
Marvel --> DC: [[../index.html#ST_002 Different text to explain the story]]

DC -> Marvel: [[../index.html#ST_001.np_id np_id]]
Marvel --> DC: [[../index.html#ST_001.np_id np_content]]

DC -> Marvel: [[../index.html#ST_001.np_id Different text to explain the story 2]]
@enduml

''',
Expand All @@ -1266,7 +1276,7 @@
}),
'is_arch': False,
'key': None,
'lineno': 17,
'lineno': 19,
'save': None,
'scale': '',
'target_id': 'needuml-index-0',
Expand Down
9 changes: 8 additions & 1 deletion tests/doc_test/doc_needuml_jinja_func_ref/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ TEST DOCUMENT NEEDUML JINJA FUNCTION REF

Some content

:np:`(np_id) np_content`

.. story:: Another story
:id: ST_002

Different conftent content
Different content content

.. int:: Test needuml jinja func ref
:id: INT_001
Expand All @@ -18,3 +20,8 @@ TEST DOCUMENT NEEDUML JINJA FUNCTION REF

DC -> Marvel: {{ref("ST_001", option="title")}}
Marvel --> DC: {{ref("ST_002", text="Different text to explain the story")}}

DC -> Marvel: {{ref("ST_001.np_id", option="id")}}
Marvel --> DC: {{ref("ST_001.np_id", option="content")}}

DC -> Marvel: {{ref("ST_001.np_id", text="Different text to explain the story 2")}}
8 changes: 8 additions & 0 deletions tests/test_needuml.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,14 @@ def test_needuml_jinja_func_ref(test_app, snapshot):
assert "Marvel: [[../index.html#ST_001 Test story]]" in html
assert "DC: [[../index.html#ST_002 Different text to explain the story]]" in html

assert "Marvel: [[../index.html#ST_001.np_id np_id]]" in html
assert "DC: [[../index.html#ST_001.np_id np_content]]" in html

assert (
"Marvel: [[../index.html#ST_001.np_id Different text to explain the story 2]]"
in html
)

srcdir = Path(app.srcdir)
out_dir = srcdir / "_build"

Expand Down

0 comments on commit fa937f2

Please sign in to comment.