needuml

neduml 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::

   class "{{needs['FEATURE_1'].title}}" {
     implement
     {{needs['FEATURE_1'].status}}
   }

Result

@startuml
allowmixing

class "Filtering needs" {
  implement
  None
}
@enduml

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

@startuml
allowmixing

card "Roberto" as a
card "RocketLab" as b
a -> b
@enduml

Note

:extra: values are only available in the current PlantUML code. It is not available in code loaded via uml(id).

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
allowmixing

node "RocketLab" {
   card "Peter"
}
@enduml

@startuml
allowmixing

node "RocketLab" {
   card "Peter"
}
@enduml

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_1"].title}}"

Result

@startuml
allowmixing

node "Filtering needs"
@enduml

need(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.

Example

.. needuml::

   {{need("COMP_001")}}
   {{need("FEATURE_1")}}

Result

@startuml
allowmixing

card "<size:12>Component</size>\n**Component X**\n<size:10>COMP_001</size>" as COMP_001 [[../directives/needuml.html#COMP_001]] #BFD8D2

node "<size:12>Feature</size>\n**Filtering needs**\n<size:10>FEATURE_1</size>" as FEATURE_1 [[../index.html#FEATURE_1]] #FFCC00

@enduml

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 diagram, the stored PlantUML diagram gets imported.

Please read Diagram support for details.

Example

.. needuml::

   {{uml("COMP_001")}}
   {{uml("FEATURE_1")}}

Result

@startuml
allowmixing

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
node "<size:12>Feature</size>\n**Filtering needs**\n<size:10>FEATURE_1</size>" as FEATURE_1 [[../index.html#FEATURE_1]] #FFCC00

@enduml

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

Component: Variant A or B COMP_A_B ../_images/arrow-right-circle.svg

@startuml
allowmixing


 class "Unknown" as cl

@enduml

By default Unknown is shown, as no variant was set.

Passing variant="A" parameter to the uml() function, we get the following:

Example

.. needuml::

   {{uml("COMP_A_B", variant="A")}}

Result

@startuml
allowmixing


 class "A" as cl

@enduml

Passing variant="B" parameter to the uml() function, we get the following:

Example

.. needuml::

   {{uml("COMP_A_B", variant="B")}}

Result

@startuml
allowmixing


 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.

Interface: Interface A INT_A ../_images/arrow-right-circle.svg

@startuml
allowmixing

circle "Int A" as int
@enduml

Component: Component X COMP_X ../_images/arrow-right-circle.svg

@startuml
allowmixing

circle "Int A" as int

class "Class A" as cl_a
class "Class B" as cl_b

cl_a o-- cl_b
cl_a --> int
@enduml

System: System RocketScience SYS_ROCKET ../_images/arrow-right-circle.svg

@startuml
allowmixing

node "RocketScience" as rocket {
    circle "Int A" as int

class "Class A" as cl_a
class "Class B" as cl_b

cl_a o-- cl_b
cl_a --> int
    card "Service Y" as service

    int --> service
}
@enduml

And finally a needuml to make use of the Sphinx-Need system object:

@startuml
allowmixing

node "RocketScience" as rocket {
    circle "Int A" as int

class "Class A" as cl_a
class "Class B" as cl_b

cl_a o-- cl_b
cl_a --> int
    card "Service Y" as service

    int --> service
}

actor "A friend" as me #ff5555

me --> rocket: doing
@enduml

.. int:: Interface A
   :id: INT_A

   .. needuml::

      circle "Int A" as int

.. comp:: Component X
   :id: COMP_X

   .. needuml::

      {{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::

      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::

   {{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

@startuml
allowmixing

allowmixing

class "Sphinx-Needs" as sn {
  requirements
  specifications
  test_cases
  customize()
  automate()
  export()
}



    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    
        card "Filtering needs" as need_128 #ffcc00
        need_128 --> sn
    

    

    

    

    
        card "Customizing everything" as need_132 #ffcc00
        need_132 --> sn
    

    

    
        card "Supports PlantUML for reusable Architecture elements" as need_134 #ffcc00
        need_134 --> sn
    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    

    


card "and much more..." as much #ffcc00
much -> sn
@enduml

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

Component: Component X COMP_001 ../_images/arrow-right-circle.svg

@startuml
allowmixing

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
@enduml