Dynamic functions

Sphinx-Needs provides a mechanism to set dynamic data for need-options during generation. This is realised by giving an author the possibility to set a function call to a predefined function, which calculates the final result/value for the option.

This can be useful, if for instance the status of a requirement depends on linked test cases and their status. Or if specific data shall be requested from an external server like JIRA.

Example

.. req:: my test requirement
   :id: df_1
   :status: open

   This need has the id **[[copy("id")]]** and status **[[copy("status")]]**.
Requirement: my test requirement df_1
status: open

This need has id df_1 and status open.

Built-in functions

The following functions are available in all sphinx-needs installations.

Note

The parameters app, need and needs of the following functions are set automatically.

test

test(app, need, needs, *args, **kwargs)

Test function for dynamic functions in sphinx needs.

Collects every given args and kwargs and returns a single string, which contains their values/keys.

.. req:: test requirement

    [[test('arg_1', [1,2,3], my_keyword='awesome')]]
Requirement: test requirement R_A6A4E

Test output of need R_A6A4E. args: ('arg_1', [1, 2, 3]). kwargs: {'my_keyword': 'awesome'}

Returns:single test string

copy

copy(app, need, needs, option, need_id=None)

Copies the value of one need option to another

.. req:: copy-example
   :id: copy_1
   :tags: tag_1, tag_2, tag_3
   :status: open

.. spec:: copy-example implementation
   :id: copy_2
   :status: [[copy("status", "copy_1")]]
   :links: copy_1
   :comment: [[copy("id")]]

   Copies status of ``copy_1`` to own status.
   Sets also a comment, which copies the id of own need.

.. test:: test of specification and requirement
   :id: copy_3
   :links: copy_2; [[copy('links', 'copy_2')]]
   :tags: [[copy('tags', 'copy_1')]]

   Set own link to ``copy_2`` and also copies all links from it.

   Also copies all tags from copy_1.
Requirement: copy-example copy_1
status: open
tags: tag_1 tag_2 tag_3
Specification: copy-example implementation copy_2
status: open
comment: copy_2

Copies status of copy_1 to own status. Sets also a comment, which copies the id of own need.

Test Case: test of specification and requirement copy_3
tags: tag_1 tag_2 tag_3

Set own link to copy_2 and also copies all links from it.

Also copies all tags from copy_1.

Parameters:
  • option – Name of the option to copy
  • need_id – id of the need, which contains the source option. If None, current need is taken
Returns:

string of copied need option

check_linked_values

check_linked_values(app, need, needs, result, search_option, search_value, filter_string=None, one_hit=False)

Returns a specific value, if for all linked needs a given option has a given value.

The linked needs can be filtered by using the filter option.

If one_hit is set to True, only one linked need must have a positive match for the searched value.

Examples

Needs used as input data

.. req:: Input A
   :id: clv_A
   :status: in progress

.. req:: Input B
   :id: clv_B
   :status: in progress

.. spec:: Input C
   :id: clv_C
   :status: closed
Requirement: Input A clv_A
status: in progress
Requirement: Input B clv_B
status: in progress
Specification: Input C clv_C
status: closed

Example 1: Positive check

Status gets set to progress.

.. spec:: result 1: Positive check
   :links: clv_A, clv_B
   :status: [[check_linked_values('progress', 'status', 'in progress' )]]
Specification: result 1: Positive check clv_1
status: progress

Example 2: Negative check

Status gets not set to progress, because status of linked need clv_C does not match “in progress”.

.. spec:: result 2: Negative check
   :links: clv_A, clv_B, clv_C
   :status: [[check_linked_values('progress', 'status', 'in progress' )]]
Specification: result 2: Negative check clv_2

Example 3: Positive check thanks of used filter

status gets set to progress, because linked need clv_C is not part of the filter.

.. spec:: result 3: Positive check thanks of used filter
   :links: clv_A, clv_B, clv_C
   :status: [[check_linked_values('progress', 'status', 'in progress', 'type == "req" ' )]]
Specification: result 3: Positive check thanks of used filter clv_3
status: progress

Example 4: Positive check thanks of one_hit option

Even clv_C has not the searched status, status gets anyway set to progress. That’s because one_hit is used so that only one linked need must have the searched value.

.. spec:: result 4: Positive check thanks of one_hit option
   :links: clv_A, clv_B, clv_C
   :status: [[check_linked_values('progress', 'status', 'in progress', one_hit=True )]]
Specification: result 4: Positive check thanks of one_hit option clv_4
status: progress

Result 5: Two checks and a joint status Two checks are performed and both are positive. So their results get joined.

.. spec:: result 5: Two checks and a joint status
   :links: clv_A, clv_B, clv_C
   :status: [[check_linked_values('progress', 'status', 'in progress', one_hit=True )]] [[check_linked_values('closed', 'status', 'closed', one_hit=True )]]
Specification: result 5: Two checks and a joint status clv_5
status: progress closed
Parameters:
  • result – value, which gets returned if all linked needs have parsed the checks
  • search_option – option name, which is used n linked needs for the search
  • search_value – value, which an option of a linked need must match
  • filter_string – Checks are only performed on linked needs, which pass the defined filter
  • one_hit – If True, only one linked need must have a positive check
Returns:

result, if all checks are positive

calc_sum

calc_sum(app, need, needs, option, filter=None, links_only=False)

Sums the values of a given option in filtered needs up to single number.

Useful e.g. for calculating the amount of needed hours for implementation of all linked specification needs.

Input data

Specification: Do this sum_input_1
hours: 7
Specification: Do that sum_input_2
hours: 15
Specification: Do too much sum_input_3
hours: 110

Example 2

.. req:: Result 1
   :amount: [[calc_sum("hours")]]
Requirement: Result 1 R_F7DEB
amount: 132.0

Example 2

.. req:: Result 2
   :amount: [[calc_sum("hours", "hours.isdigit() and float(hours) > 10")]]
Requirement: Result 2 R_96D5E
amount: 125.0

Example 3

.. req:: Result 3
   :links: sum_input_1; sum_input_3
   :amount: [[calc_sum("hours", links_only="True")]]
Requirement: Result 3 R_D0791
amount: 117.0

Example 4

.. req:: Result 4
   :links: sum_input_1; sum_input_3
   :amount: [[calc_sum("hours", "hours.isdigit() and float(hours) > 10", "True")]]
Requirement: Result 4 R_3C95C
amount: 110.0
Parameters:
  • option – Options, from which the numbers shall be taken
  • filter – Filter string, which all needs must passed to get their value added.
  • links_only – If “True”, only linked needs are taken into account.
Returns:

A float number

Develop own functions

Registration

Every dynamic function must be registered by using configuration parameter needs_functions inside your conf.py file:

needs_functions == [my_own_function]

def my_own_function(app, need, needs):
    return "Awesome"

Reference function

def test(app, need, needs, *args, **kwargs):
    """
    :param app: sphinx app
    :param need: current need
    :param needs: dictionary of all needs. Key is the need id
    :return: str,int,float or list of elements of type str,int,float
    """
    # where the magic happens
    return "awesome"

Such a defined function can be called via:

.. req:: test requirement
   :status: [[test()]]

The parameters app, need and needs are set automatically. You are free to add other parameters, which are allowed to be of type str, int, float and list.

need structure

need = {
   'docname': str: document name,
   'lineno': int: linenumber,
   'links_back': list: list of incoming links (see restrictions),
   'target_node': node: sphinx target node for internal references,
   'type': str: short name of type,
   'type_name': str: long name of type,
   'type_prefix': str: name of type prefix,
   'type_color': str: type color,
   'type_style': str: type style,
   'status': str: status,
   'tags': list: list of tags,
   'id': str: id,
   'links': list: list of outgoing links,
   'title': str: trimmed title of need,
   'full_title': str: full title of string,
   'content': str: unparsed need content,
   'collapse': bool: true if meta data shall be collapsed,
   'hide': bool: true if complete need shall be hidden,
   'hide_tags': bool: if tags shall be hidden,
   'hide_status': bool: true if status shall be hidden,
}

Adding new keywords to need object will be treated as extra_option in need meta area.

Restrictions