needuml¶
needuml
behaves exactly like the uml
directive from the Sphinx extension
Sphinxcontrib-PlantUML.
So it allows to define PlantUML diagrams.
But gives you access to need object data by supporting Jinja statements, which allows you to use loops, if-clauses, and it injects data from need-objects.
Example
.. needuml::
{{uml('FEATURE_NEEDUML1')}}
{{uml('COMP_NEEDUML2')}}
.. feature:: NeedUml example need
:id: FEATURE_NEEDUML1
:tags: needuml
:status: draft
Example Need for NeedUml.
.. comp:: NeedUml example need 2
:id: COMP_NEEDUML2
:tags: needuml
:status: draft
Second example Need for NeedUml.
.. needuml::
{{flow('COMP_NEEDUML2')}} {
card implement
card {{needs['COMP_NEEDUML2'].status}}
}
Result
Example Need for NeedUml. |
Second example Need for NeedUml.
|
Options¶
extra¶
Allows to inject additional key-value pairs into the needuml
rendering.
:extra:
must be a comma-separated list, containing key:value pairs.
Example
.. needuml::
:extra: name:Roberto,work:RocketLab
card "{{name}}" as a
card "{{work}}" as b
a -> b
Result
Note
:extra:
values are only available in the current PlantUML code.
It is not available in code loaded via uml(id).
So we suggest to use them only in non-embedded needuml directives.
In an embedded needuml, you can store the information in the options
of the need and access them with needflow like in
needuml introduction.
config¶
Allows to preconfigure PlantUML and set certain layout options.
For details please take a look into needflow config.
debug¶
If :debug:
is set, a debug-output of the generated PlantUML code gets added after the generated image.
Helpful to identify reasons why a PlantUML build may have thrown errors.
Example
.. needuml::
:debug:
node "RocketLab" {
card "Peter"
}
Result
@startuml node "RocketLab" { card "Peter" } @enduml
key¶
Allows to store multiple needuml
inside a need under arch
under the given key, e.g. need["arch"]["key_name"]
.
If no option key given, then the first needuml
will be stored in the need under arch
under diagram
, need["arch"]["diagram"]
.
Option :key:
value can’t be empty, and can’t be diagram
.
Example
.. comp:: Component Y
:id: COMP_002
.. needuml::
:key: sequence
Alice -> Bob: Hi Bob
Bob --> Alice: Hi Alice
.. needuml::
:key: class
class System_A as A {
todo
open
}
.. needuml::
B -> C: Hi
C -> B: Hi there
Result
|
save¶
Specifies the file path to store generated Plantuml-code of current needuml
. This given file path can be relative path
or file name, e.g. needuml_group_A/my_needuml.puml
or my_needuml.puml
.
The file will be created and written during each build by using builder needumls or other builder like html with configuration option needs_build_needumls configured.
If given file path already exists, it will be overwritten.
Example
.. int:: Test needuml save
:id: INT_001
.. needuml::
:save: needuml_group_A/my_needuml.puml
Alice -> Bob: Hi Bob
Bob --> Alice: Hi Alice
In this example, if builder needumls is used, the plantuml-code will be exported to file at outdir of current builder, e.g. _build/needumls/needuml_group_A/my_needuml.puml.
Result
|
Jinja context¶
When using Jinja statements, the following objects and functions are available.
needs¶
A Python dictionary containing all Needs. The need_id
is used as key.
Example
.. needuml::
node "{{needs["FEATURE_NEEDUML1"].title}}"
Result
flow(id)¶
Loads a Sphinx-Need object as PlantUML object. We use the same layout used for needflow.
This functions represents each Need the same way.
Changed in version 1.0.3: In the past the returned plantuml representation string ends with a newline. Now it is up to the author of the Jinja template to write the newline, which is normally anyway the case. E.g. see the following example, where the two flow() are separated by a newlone. With this approach it is possible to write plantuml code following flow(). E.g. see even the following example, with text following {{flow(“COMP_001”)}}.
Example
.. needuml::
{{flow("FEATURE_NEEDUML1")}}
{{flow("COMP_001")}} {
card manuall_written
}
Result
filter(filter_string)¶
Finds a list of Sphinx-Need objects that pass the given filter string.
Example
.. needuml::
{% for need in filter("type == 'int' and status != 'open'") %}
node "{{need.title}}"
{% endfor %}
Result
ref(id, option, text)¶
Allows to create an hyperlink to a Sphinx-Need object in a PlantUML schema. The text associated to the hyperlink is either defined by option (in this case, Sphinx-Need picks the text of the field specified by option), or by the free text text.
Example
.. needuml::
Alice -> Bob: {{ref("FEATURE_1", option="title")}}
Bob -> Alice: {{ref("FEATURE_2", text="A completely free text")}}
Result
uml(id)¶
Loads a Sphinx-Need object as PlantUML object or reuses the stored PlantUML code inside the Sphinx-Need object.
If diagram code is available in the need data under arch
, the stored PlantUML diagram gets imported.
Please read Diagram support for details.
Example
.. needuml::
allowmixing
{{uml("COMP_001")}}
{{uml("FEATURE_NEEDUML1")}}
Result
Key argument¶
uml() supports key
argument to define which PlantUML code to load from the Sphinx-Need object.
key
value by default is diagram
. If no key argument given, then the PlantUML code is loaded from diagram
under arch
inside the need object.
Example
.. comp:: Z
:id: COMP_Z
.. needuml::
{{uml('COMP_002', 'sequence')}}
Result
|
Additional keyword arguments¶
uml() supports additional keyword parameters which are then available in the loaded PlantUML code.
Example
.. comp:: Variant A or B
:id: COMP_A_B
.. needuml::
{% if variant == "A" %}
class "A" as cl
{% elif variant == "B" %}
class "B" as cl {
attribute_x
function_x()
}
{% else %}
class "Unknown" as cl
{% endif %}
By default **Unknown** is shown, as no variant was set.
Result
By default Unknown is shown, as no variant was set. |
Passing variant="A"
parameter to the uml() function, we get the following:
Example
.. needuml::
:debug:
{{uml("COMP_A_B", variant="A")}}
Result
@startuml class "A" as cl @enduml
Passing variant="B"
parameter to the uml() function, we get the following:
Example
.. needuml::
:debug:
{{uml("COMP_A_B", variant="B")}}
Result
@startuml class "B" as cl { attribute_x function_x() } @enduml
Chaining diagrams¶
PlantUML Need objects uses the needuml
directive internally to define their diagrams.
All features are available and uml()
can be used multiple time on different levels of a planned architecture.
|
|
|
And finally a needuml
to make use of the Sphinx-Need system object:
.. int:: Interface A
:id: INT_A
.. needuml::
circle "Int A" as int
.. comp:: Component X
:id: COMP_X
.. needuml::
allowmixing
{{uml("INT_A")}}
class "Class A" as cl_a
class "Class B" as cl_b
cl_a o-- cl_b
cl_a --> int
.. sys:: System RocketScience
:id: SYS_ROCKET
.. needuml::
allowmixing
node "RocketScience" {
{{uml("COMP_X")}}
card "Service Y" as service
int --> service
}
And finally a ``needuml`` to make use of the Sphinx-Need system object:
.. needuml::
allowmixing
{{uml("SYS_ROCKET")}}
actor "A friend" as me #ff5555
me --> rocket: doing
NeedUml Examples¶
Example
.. needuml::
allowmixing
class "Sphinx-Needs" as sn {
requirements
specifications
test_cases
customize()
automate()
export()
}
{% set ids = ["FEATURE_1", "FEATURE_5", "FEATURE_7"]%}
{% for need in needs.values() %}
{% if need.id in ids %}
card "{{need['title']}}" as need_{{loop.index}} #ffcc00
need_{{loop.index}} --> sn
{% endif %}
{% endfor %}
card "and much more..." as much #ffcc00
much -> sn
Result
Example
.. comp:: Component X
:id: COMP_001
.. needuml::
class "Class X" as class_x {
attribute_1
attribute_2
function_1()
function_2()
function_3()
}
class "Class Y" as class_y {
attribute_1
function_1()
}
class_x o-- class_y
Result
|