Request: enable needuml to modify needs
Abstract
For every element used in needuml/needarch we want to add a link to the need itself to every image it's used in. A generated "used_in_image" option. The current approach is to inject a custom uml-function (like e.g. ref), which will modify the need element when used.
However modifications to the need do not take effect, as they simply happen too late in the workflow.
Approach in Detail:
- I'm injecting an "uml-function", I'm calling it "element". Approach: #1206
- In plantuml I'm using it like:
participant {{element('demo1_A')}}(I have a workaround for getting all needs into the function via storing the app into a global variable; see also #1207) - That "element" uml-function simply modifies the referenced need:
need["used_in_image"] = current_document(full code below)
Problem in Detail:
- uml is processed within
process_creator - needs become "read only" after
process_need_nodes, specificallyformat_need_nodesSee https://github.com/useblocks/sphinx-needs/blob/f3745ffd8ab9d3c3ed079554b746d0d53162fe18/sphinx_needs/needs.py#L291-L292
Possible solution:
- There is no reason, why
format_need_nodesneeds to called byprocess_need_nodes. It could be called later afterprocess_creator. Looks like it was there to avoid redundantfindallcalls, but it's not redundant (anymore). - However, it's not that trivial as
format_need_nodesevaluates the "hide" option. Not doing so before needpie etc could change the diagrams.
Not addressed here in this issue:
- How do get the current document within the uml-function
- How to add anchor tags to uml-images
Code just for reference:
current_app: sphinx.application.Sphinx | None = None
def get_needs() -> dict[str, dict[str, Any]]:
assert current_app
assert current_app.env
# old way of accessing needs:
assert current_app.env.needs_all_needs
assert isinstance(current_app.env.needs_all_needs, dict)
return current_app.env.needs_all_needs
def uml_element(need: dict | str):
if isinstance(need, str):
needs = get_needs()
need = needs[need]
# FIXME: can we access current document through app? and potentially current need?
current_document = need["docname"]
# Modifying needs has no effect at this point in time !!
needs[need_id]["used_in_image"] += current_document + ".html;"
link = sphinx_needs.diagrams_common.calculate_link(
current_app, need, current_document
)
title = need["title"]
need_id = need["id"]
return f'"[[{link} {title}]]" as {need_id}'
def setup(app: sphinx.application.Sphinx):
global current_app # noqa: PLW0603
current_app = app
Correction: maybe the change is simple after all while preserving current behavior.
Currently when elements have the :hide: option, they do appear in e.g. needtable and they can be referenced from needuml.
May be also relevant for the S-Core project: https://github.com/eclipse-score/score/issues/658