Configuration

All root configurations take place in your project’s conf.py file.

Activation

Add sphinx_needs to your extensions.

extensions = ["sphinx_needs",]

Available sphinx-needs options are then listed below, that can be added to your conf.py file.

Added in version 4.1.0: Configuration can also be specified via a toml file. See needs_from_toml for more details.

Build Warnings

sphinx-needs is designed to be durable and only except when absolutely necessary. Any non-fatal issues during the build are logged as Sphinx warnings.

If you wish to “fail-fast” during a build, see the –fail-on-warning command-line option (in sphinx 8.1 --exception-on-warning).

You can also use this in conjunction with the suppress_warnings configuration option, to suppress specific warnings.

Find below a list of all warnings, which can be suppressed:

  • needs.beta Beta feature, subject to change

  • needs.card_layout Invalid needs_card_layouts specification

  • needs.choose Error in processing choose/when/otherwise directive

  • needs.config Invalid configuration

  • needs.constraint Constraint violation

  • needs.create_need Creation of a need from directive failed

  • needs.delete_need Deletion of a need failed

  • needs.deprecated Deprecated feature

  • needs.derive_authored A derived field is set in a need or by a needextend; the value is ignored

  • needs.derive_cycle A dynamic function or variant is on a cycle of computed values; the field is not computed

  • needs.derive_dense A link type’s derive rule, or its link-valued dynamic functions, store more links than needs_derive_max_links_per_need per need of the project

  • needs.derive_invalid A derive rule of needs_fields or needs_links cannot be read, or a default is given beside it

  • needs.derive_scope A dynamic function, variant or needextend filter reads a value that cannot be computed before it

  • needs.derive_unique A derived copy with select = “unique” finds several needs that set the field; the lowest id is copied

  • needs.diagram_scale Failed to process diagram scale option

  • needs.directive Error in processing a need directive

  • needs.duplicate_id Duplicate need ID found when merging needs from parallel processes

  • needs.duplicate_part_id Duplicate part ID found when parsing need content

  • needs.dynamic_function Failed to load/execute dynamic function

  • needs.external_link_outgoing Unknown outgoing link in external need

  • needs.external_link_target_type A link of an external need points to a need of a type its link type’s target_types does not accept

  • needs.external_needs An external needs source cannot be read, or what it holds is reported

  • needs.filter_func Error loading needs filter function

  • needs.filter Error processing needs filter

  • needs.filter_type A filter’s c.is_a names no need type, so it selects no need

  • needs.github Error in processing GitHub service directive

  • needs.if Error in processing if directive

  • needs.import_doctype Imported need content declares a doctype the project cannot parse; parsed as the page’s markup

  • needs.import_need Failed to import a need

  • needs.json_load

  • needs.layout Error occurred during layout rendering of a need

  • needs.link_condition_failed Link condition not satisfied by targeted need

  • needs.link_condition_invalid Link condition has invalid filter syntax

  • needs.link_outgoing Unknown outgoing link in standard need

  • needs.link_ref Need could not be referenced

  • needs.link_target_type A link points to a need of a type its link type’s target_types does not accept

  • needs.link_text Reference text could not be generated

  • needs.load_external_need Failed to load an external need

  • needs.load_service_need Failed to load a service need

  • needs.max_items View truncated by a max_items limit

  • needs.mistyped_external_values Unexpected value types found in external need data

  • needs.mistyped_import_values Unexpected value types found in imported need data

  • needs.mpl Matplotlib required but not installed

  • needs.needextend Error processing needextend directive

  • needs.needextract Error processing needextract directive

  • needs.needflow Error processing needflow directive

  • needs.needgantt Error processing needgantt directive

  • needs.needimport Error processing needimport directive

  • needs.needreport Error processing needreport directive

  • needs.needsequence Error processing needsequence directive

  • needs.needuml Error processing needuml/needarch directive

  • needs.part Error processing need part

  • needs.string_link Invalid needs_string_links configuration

  • needs.title Error creating need title

  • needs.type_conflict A need type’s declaration of a field or link type cannot be applied to it; the declaration is ignored

  • needs.type_inherits A need type’s inherits names no need type, or is on a cycle; it is ignored and the type has no parent

  • needs.type_near_name A field or link type declared on need types alone has a name close to that of a declared field or link type; it is declared all the same

  • needs.type_widening A need type’s declaration of a field or link type widens the declaration it inherits; the declaration is ignored

  • needs.uml Error in processing of UML diagram

  • needs.undeclared_for_type A field or link type is set on a need of a need type that does not declare it; the value is ignored

  • needs.unknown_external_keys Unknown keys found in external need data

  • needs.unknown_import_keys Unknown keys found in imported need data

  • needs.variant Error processing variant in need field

  • needs.variant_data_location Variant data set in both [variants] and [needs]; the [needs] keys are ignored

  • needs.variants_unknown_key Unknown key in the [variants] table

  • needs.warnings Need warning check failed for one or more needs

Incremental build support

Sphinx does not use its incremental build feature, if you assign functions directly to Sphinx options. To avoid this, please use the Sphinx-Needs API to register functions directly.

This would allow Sphinx to perform incremental builds which are much faster as compared to full builds.

Example configuration

# conf.py

# Defining one or more functions in conf.py is fine
def my_custom_warning(need, log):
    # some checks
    return False

def my_dynamic_function(app, need, needs):
    return "some text"

# This assignment will deactivate incremental build support inside Sphinx
needs_warnings = {
   'my_warning_no_inc_build': my_custom_warning
}

# Better, register the function via Sphinx-Needs API
from sphinx_needs.api.configuration import add_warning, add_dynamic_function
def setup(app):
   add_warning(app, 'my_warning', my_custom_warning)
   add_dynamic_function(app, my_dynamic_function)

Hint

You are free to use e.g. needs_warnings and add_warning() together in a conf.py file. Sphinx-Needs creates internally a final list of elements defined by config-var and api-call.

However, you should not use the same id in a config-var and the related api-call, as this would create the related element twice.

Options

All configuration options starts with the prefix needs_ for Sphinx-Needs.

needs_from_toml

Added in version 4.1.0.

This configuration takes the (relative) path to a toml file which contains some or all of the needs configuration (configuration in the toml will override that in the conf.py).

needs_from_toml = "ubproject.toml"

Configuration in the toml can contain any of the options below, under a [needs] section, but with the needs_ prefix removed. For example:

[needs]
id_required = true
id_length = 3
types = [
   {directive="req", title="Requirement", prefix="R_", color="#BFD8D2", style="node"},
   {directive="spec", title="Specification", prefix="S_", color="#FEDCD2", style="node"},
]

The exception is needs_functions, because it holds Python callables, which a toml file cannot hold: a functions key in the toml is ignored, with a warning.

To specify a different root table path to read from in the toml file, use the needs_from_toml_table option. For example to read from a [tool.needs] table:

needs_from_toml_table = ["tool"]

A relative path given in the toml file for an option that names a file or folder sphinx-needs reads or writes — needs_file, needs_css, needs_template_folder, needs_variant_data_file, the json_path of needs_external_needs, needs_schema_definitions_from_json and needs_schema_debug_path — is resolved relative to the directory containing the toml file, not the one containing the conf.py file.

Variant data: the [variants] table

Added in version 9.0.0.

The variant data of needs_variant_data and needs_variant_data_file has a table of its own in the toml file, [variants], which other tools reading the same file share:

[variants]
data_file = "variants/base.json"  # a JSON file, relative to this file's directory
[variants.data]                   # deep-merged over the file: these values win
edition = "pro"

data is the inline table (needs_variant_data) and data_file the file (needs_variant_data_file); either may be given alone. Any other key in [variants] is ignored and reported as a needs.variants_unknown_key warning. A toml file may hold [variants] and no [needs] table at all: it is read, and even an empty [variants] stops the warning a toml file without a [needs] table otherwise gets.

The legacy location. Before [variants] existed, the same two values were read from the [needs] table, as variant_data and variant_data_file, and they still are. A build with -v says, for each key, when the data comes from there. A later release will deprecate the legacy location, so move the two keys when convenient:

# the legacy location
[needs]
variant_data_file = "variants/base.json"
[needs.variant_data]
edition = "pro"

# the same data in [variants]
[variants]
data_file = "variants/base.json"
[variants.data]
edition = "pro"

One location is read, whole. When [variants] holds data or data_file, both values come from [variants]: a variant_data or variant_data_file left in [needs] is ignored, with one needs.variant_data_location warning per key. A file from one table is never merged under an inline table from the other.

conf.py and -D, key by key. As for every other option, the toml overrides conf.py one key at a time: a needs_variant_data in conf.py still applies when the location read sets no inline table, and a needs_variant_data_file when it sets no file; the file is then loaded and the inline table merged over it, as usual.

-D needs_variant_data_file swaps the file, never the table. -D needs_variant_data_file=... replaces the data file of the location read, [variants] or [needs], without opening the toml’s own file, and that location’s inline table is still merged over it, so a project on the legacy location keeps its [needs.variant_data]. It never decides the location: the location, the refusals and the warnings are those of the toml as written, and with neither location declared the override file is the whole of the toml’s variant data (a conf.py needs_variant_data still merges over it, key by key as above). A relative path is resolved against the conf.py directory, and an empty value, -D needs_variant_data_file=, means no file: the toml’s file is replaced by none, also without being opened, and the location’s inline table is used without a file.

With needs_from_toml_table, the prefix applies to both tables: with needs_from_toml_table = ["tool"] they are [tool.needs] and [tool.variants], which is what lets the configuration live in a pyproject.toml, whose top level is reserved for other uses. A top-level [variants] is then someone else’s table, and is not read.

# pyproject.toml, with needs_from_toml = "pyproject.toml" and needs_from_toml_table = ["tool"]
[tool.needs]
id_required = true

[tool.variants.data]
edition = "pro"

A variants key that is not a table, an inline table that is not valid variant data, a data_file that is not one non-empty path, or a data file that is missing or does not hold valid variant data fails the build, naming the toml file and the table. Both warnings above can be suppressed on their own, see Build Warnings.

Note

ubCode reads [variants] from 0.37.0, and sphinx-mounts from 0.3.0. A project that is also checked by an earlier ubCode, or built with an earlier sphinx-mounts, keeps its variant data in [needs] until it moves to a release of that tool that reads [variants].

needs_include_needs

Set this option to False, if no needs should be documented inside the generated documentation.

Default: True

needs_include_needs = False

needs_id_length

This option defines the length of an automated generated ID (the length of the prefix does not count).

Default: 5

needs_id_length = 3

needs_types

The option allows the setup of own need types like bugs, user_stories and more.

By default it is set to:

needs_types = [dict(directive="req", title="Requirement", prefix="R_", color="#BFD8D2", style="node"),
               dict(directive="spec", title="Specification", prefix="S_", color="#FEDCD2", style="node"),
               dict(directive="impl", title="Implementation", prefix="I_", color="#DF744A", style="node"),
               dict(directive="test", title="Test Case", prefix="T_", color="#DCB239", style="node"),
               # Kept for backwards compatibility
               dict(directive="need", title="Need", prefix="N_", color="#9856a5", style="node")
           ]

needs_types is a list of dictionaries where each dictionary must contain the following items:

  • directive: Name of the directive. For instance, you can use “req” via .. req:: in documents

  • title: Title, used as human readable name in lists

  • prefix: A prefix for generated IDs, to easily identify that an ID belongs to a specific type. Can also be “”

  • color: A color as hex value. Used in diagrams and some days maybe in other representations as well. Can also be “”

  • style: A plantuml node type, like node, artifact, frame, storage or database. See plantuml documentation for more.

  • inherits, fields, links (optional): the fields and link types the type declares anew for its needs, see Fields per need type.

  • id_regex (optional): a regular expression the id of every need of the type matches, beside needs_id_regex (below).

A type’s id_regex is matched as needs_id_regex is, where it is: against the need’s local id (the whole id while ids carry no namespace), with Python’s re.match, so it is anchored at the start of the id and open at its end ("REQ_" accepts REQ_001 and refuses XREQ_001; end it with $ to anchor the end too), on an id given in the need or generated from the type’s prefix, and never on a need needimport imports or needs_external_needs loads. The id of a need matches needs_id_regex, its type’s id_regex, and that of every type its type inherits from (through inherits): a type narrows the ids of the type it inherits from, never widens them. A need whose id does not match is not created, as for needs_id_regex, one needs.create_need warning naming the pattern and the type that gives it:

Need could not be created: Given ID 'XYZ_S01' does not match the id_regex 'REQ_' of need type 'req', which need type 'safety_req' inherits

To report such ids and keep the needs instead, use a schema rule with a pattern on id. A pattern that is not a regular expression is one needs.type_conflict warning, and is ignored:

needs_types['req'] has an id_regex 'REQ_[' that is not a regular expression (unterminated character set at position 4); the key is ignored

A configured needs_types replaces the default types once one of its entries gives a title or a prefix. An entry naming a default type (req, spec, impl, test or need) with neither of the two is that type, narrowed: it takes the title, prefix, color and style it leaves out, and its own inherits, fields and links apply. A needs_types made only of such entries keeps every default type, in the order above, each narrowed by its entry, which is how a default type gets a field declaration or a rule of its own:

[needs.fields.linked]
schema = { type = "integer" }

# the default type req, counting its links; spec, impl, test and need are kept
[needs.types.req.fields.linked]
derive = { kind = "count", over = "links" }

Beside an entry giving a title or a prefix, the list given is the project’s need types, as without such entries: an entry naming a default type with neither is that default, filled, at its own position, and the other defaults do not exist. A bare entry is filled from the default type, never from another entry naming the same directive: in a list naming the directive twice, the later entry is used, as for any directive declared twice (and reported).

An entry naming a need type an extension adds (with add_need_type(), such as sphinx-test-reports’ testfile, testsuite and testcase) narrows that type, as one naming a default type does, with or without a title and a prefix: the keys the entry gives win, the title, prefix, color and style it leaves out are the extension’s, and its inherits, fields, links, back_links and id_regex apply to the type’s needs as on any type the project declares, a severity included. When the extension adds the type does not matter, even when that is after the configuration is read. The entry only narrows: its declaration of a field the extension declares starts from the extension’s, as a type’s declaration starts from the field’s own (Fields per need type), so one that would widen it – loosen a schema keyword, make it nullable where the extension does not – is a needs.type_widening warning, and one giving it another type a needs.type_conflict; that field’s entry is ignored, and the type keeps the extension’s declaration. A bare entry declares no type: beside it the default types are kept, as beside a bare entry naming a default type. An entry giving a title and a prefix declares the project’s types, as any such entry does:

# sphinx-test-reports' testcase, with a link type its needs alone carry
[needs.types.testcase.links.evidence_for]
derive = { kind = "links", join = { field = "case_name", equals = "case_name" }, where = "type == 'test'" }

# the project's own test needs give the case_name the join reads, a field the extension
# declares on its test cases alone: this entry declares it on test too
[needs.types.test.fields.case_name]

A bare entry naming no default type and no type an extension adds is ignored, with a needs.config warning given once the schema is built (no earlier: the extension may add its type late):

needs_types['epic'] has no 'title' and no 'prefix'; the entry is ignored: it names no need type an extension registers, and to attach a rule to a type the project does not declare, use `derive_by_type` on the field or link type

The need types of the configured GitHub services are not narrowed this way: an entry for one with a title and a prefix is the project’s own type, which replaces the service’s, and a bare one is ignored, with the warning above saying it names a GitHub service’s need type; derive_by_type gives such a type a rule.

Every one of these items is stored on, or decides, the needs of the type, so an incremental build after a change to needs_types re-reads every document, as one after a change to needs_fields does, and so does one after a change to a need type added by an extension (below), or after a built-in GitHub service is configured or removed in needs_services.

Changed in version 9.1.0: needs_types can also be a dictionary keyed by directive name, and is validated when the configuration is read. An entry naming a default type with neither title nor prefix narrows that type, and a needs_types made only of such entries keeps the default types.

Changed in version 9.2.0: An entry naming a need type an extension adds narrows that type (narrowing an extension’s type), rather than being ignored (an entry with neither title nor prefix) or stopping the build when the extension adds its type (one with both).

A change to needs_types re-reads every document. Before, the needs of the documents an incremental build did not re-read kept what the previous need types gave them, such as a derive rule that had been removed.

Instead of a list, needs_types can be a dictionary from each directive name to the other items of its type:

needs_types = {
    "req": {"title": "Requirement", "prefix": "R_", "color": "#BFD8D2", "style": "node"},
    "spec": {"title": "Specification", "prefix": "S_", "color": "#FEDCD2", "style": "node"},
}

In a needs_from_toml file, the list is an array of [[needs.types]] tables, and the dictionary one [needs.types.<directive>] table per type:

[needs.types.req]
title = "Requirement"
prefix = "R_"
color = "#BFD8D2"

[needs.types.spec]
title = "Specification"
prefix = "S_"
color = "#FEDCD2"

is the same as

[[needs.types]]
directive = "req"
title = "Requirement"
prefix = "R_"
color = "#BFD8D2"

[[needs.types]]
directive = "spec"
title = "Specification"
prefix = "S_"
color = "#FEDCD2"

The two shapes are equivalent, and the types keep the order they are given in both (the order of the legends, of needreport, and the default type of needservice); an entry of either shape may declare fields anew for its type (Fields per need type).

The need types added by extensions (with add_need_type()) and by the configured GitHub services are not part of the option’s value: they follow the configured types wherever the types are read, and get_need_types() lists them all. A configured type narrows one of its directive an extension adds (above), and replaces a service’s. An incremental build after a change to a type added by an extension re-reads every document, as one after a change to needs_types does, although the option’s value is unchanged.

The value is validated when the configuration is read. A value that is neither a list nor a dictionary stops the build with an error. Otherwise each problem is a needs.config warning, and the build goes on without what cannot be used:

  • an entry that is not a dictionary is ignored;

  • an entry that names no directive is ignored: in the list, a directive that is missing or not a non-empty string; in the dictionary, an empty key. A directive inside a dictionary entry that differs from its key is reported, and the key is used;

  • an entry whose title or prefix is missing or not a string is ignored: its type does not exist; but an entry giving neither that names a default type narrows that type (above), and one giving neither that names no default type narrows the type an extension adds under its name, or else declares nothing (it is then reported once the schema is built, above); either way, on its own it does not replace the default types;

  • a color or style that is not a string, an inherits that is not a non-empty string, and a fields or links that is not a dictionary, are ignored, and the type kept;

  • a key other than directive, title, prefix, color, style, inherits, fields and links is ignored, and the type kept;

  • a directive declared more than once in the list: the last entry is used, at its own position, and one warning names every entry that declares it.

prefix and color may be "".

Note

color can also be an empty string. This makes sense, if the PlantUMl configuration is mostly provided by using needs_flow_configs and the used colors shall not get overwritten by type specific values.

Warning

If a need type shall contain need_part / np and later be printed via needflow, the chosen PlantUML node type must support nested elements for this type.

Types who support nested elements are for instance: node, package, frame. Not supporting elements are for instance usecase, actor.

Please take a look into the PlantUML Manual for more details.

Fields per need type

Added in version 9.1.0.

A need type may declare fields and link types anew for its needs, in its entry:

  • fields: a dictionary from the name of a field – one of needs_fields, a field an extension or a service registers, or a core field such as status, or a name nothing else declares, a field of this type’s needs alone (below) – to the type’s declaration of it;

  • links: a dictionary from the name of a link type – one of needs_links, or links, or a name nothing else declares, a link type of this type’s needs alone – to the type’s declaration of it;

  • back_links: a dictionary from the name of a link type l to how many links of l point to a need of the type, its back links <l>_back (below);

  • inherits: the directive name of one other need type, whose declarations this type starts from; a filter’s c.is_a follows it (Filtering for a type and the types inheriting from it).

A declaration in fields may carry these keys, each as needs_fields takes it:

key

the type’s

description

description of the field

schema

schema of the field: only the keywords it changes, the others are kept

nullable

false where the field is nullable; never true where it is not

default

default value

predicates

(match expression, value) pairs, in place of the field’s (an empty list: none)

derive

rule computing the field on the type’s needs and on those of the types inheriting from it (below; derive_by_type is the spelling for a type no entry declares, Rules per need type)

severity

severity a need failing the declaration – its schema keywords, its nullable = false – is reported at: "violation" (the default), "warning" or "info" (below)

and a declaration in links these, as needs_links takes them:

key

the type’s

description

description of the link type

schema

schema of the link list (maxItems, minItems, …): only the keywords it changes

default

default links

predicates

(match expression, links) pairs, in place of the link type’s (an empty list: none)

derive

rule computing the links of the type’s needs and of those of the types inheriting from it (below; derive_by_type is the spelling for a type no entry declares, Rules per need type)

target_types

need types the links of the type’s needs may point to (a listed type or one inheriting from it): within those it inherits (the subtypes of a listed type included), never others (below)

severity

severity a need whose links fail the schema is reported at: "violation" (the default), "warning" or "info" (below)

incoming, outgoing

the labels of the links, on every need type: set by the root declaration of a link type declared on need types alone (below)

copy

whether the links are copied into links: likewise

allow_dead_links

whether a link to no need is allowed: likewise

summary

whether the link type is a summary (Summary link types): likewise

color, style, style_part, style_start, style_end

the links’ color, and their line styles in a needflow (see style / style_part): likewise

A link type’s incoming, outgoing, copy, allow_dead_links, summary, color and style* are the same on every need type: the first declaration of a link type declared on need types alone without a declaring ancestor sets them, and its other declarations may repeat them (below). On any other link type a declaration giving them, even with the link type’s own value, is one needs.config warning, those keys ignored and the rest of the declaration used:

needs_types['spec'].links['blocks'] sets 'incoming' and 'copy', which a need type gives only a link type declared on need types alone; 'blocks' keeps its own on every need type and the keys are ignored

Anything else in a declaration – a parse_variants, parse_dynamic_functions or parse_conditions, a derive_by_type – is fixed for every need type: it is reported as a needs.config warning and ignored. A derive is the field’s (or link type’s) derive_by_type entry for the type, and for each type inheriting from it that gives no derive of its own, with what a derive_by_type entry brings: a field needs_fields declares is then derived on every need type, closed to authors there too, and a need of a type without a rule holds what Rules per need type says. Beside a derive_by_type entry for the same type, it is one needs.config warning, and the derive_by_type entry is used for that type alone: the types inheriting from it, without a rule of their own, still read the entry’s rule:

needs_types['story'].fields['total'] sets 'derive', and needs_fields['total'].derive_by_type['story'] another rule for the same type; the need type's rule is ignored for it (the need types inheriting from it still read it)

The needs.derive_invalid warnings of such a rule name the entry it came from (needs_types['task'].fields['total'].derive: ...).

[needs.fields.asil]
nullable = true
schema = { type = "string", enum = ["QM", "A", "B", "C", "D"] }

[needs.types.req]
title = "Requirement"
prefix = "R_"

[needs.types.req.fields.asil]
description = "The ASIL a requirement is developed to"
nullable = false
default = "QM"

[needs.types.safety_req]
title = "Safety requirement"
prefix = "SR_"
inherits = "req"

[needs.types.safety_req.fields.asil]
schema = { enum = ["A", "B", "C", "D"] }
default = "A"

[needs.types.safety_req.links.links]
schema = { maxItems = 3 }

Here a req must have an asil (QM unless it says), a safety_req one of A to D (A unless it says), and a safety_req links to three needs at most; the needs of every other type read asil and links as declared for all. In conf.py, the same entries are needs_types = {"safety_req": {"title": ..., "inherits": "req", "fields": {"asil": {...}}}, ...}, and in the list shape dict(directive="safety_req", title=..., inherits="req", fields={"asil": {...}}). In a TOML file of the list shape, a [needs.types.fields.asil] table after the [[needs.types]] tables belongs to the last of them.

For a walkthrough with diagrams, see Modeling need types.

Narrowing. A type’s declaration of a field starts from the field’s own declaration, takes the declarations of its ancestors from the root down, then its own; a key it leaves out, and a schema keyword, is kept from the declaration before it. Each declaration must narrow the one before it, so that a need of the type is valid wherever a need of its parent, or of any type, is: a schema keyword only becomes stricter (an enum a subset, a minimum higher, a maxItems lower, …), none is dropped, nullable only changes from true to false, and a default – the type’s own, or the one it keeps – is valid against the narrowed schema (so an enum that leaves out the field’s default needs a default inside it). The empty value of its type ([], "", 0, 0.0, false), kept from the field’s global declaration – the empty list of a link type and of tags among them – is no default, as None is not one: a minItems (minLength, minimum, const) needs no default, and makes a need of the type without a value fail validation. An ancestor that sets default = [] itself sets a default, which a child’s minItems must admit. A link type’s target_types narrows too. A declaration accepts each type it lists and every type inheriting from one of them, and it may accept only types that the declaration before it accepts. Say hw_test inherits test, and test gives verifies the target types ["req"]. Then hw_test may give ["safety_req"], because a safety_req inherits req and so is accepted already. It may not give ["spec"] or ["req", "spec"]: a spec is not accepted for a test, so that widens. A declaration that gives no target_types, or names no need type in it, keeps the target types before it; where no declaration before it gives any, the links may point to any type. A severity may be raised, never lowered below one a declaration before it gives (info is below warning, below violation); where none gives one, a declaration is free to give any (Child 'severity' 'info' is lower than parent 'severity' 'warning'.). A declaration that widens is ignored as a whole, its other keys included, and the type keeps the declaration before it; each reason is one needs.type_widening warning, such as:

needs_types['spec'].fields['x'] widens the field: Child 'enum' values ['A', 'B', 'C'] are not a subset of parent 'enum' values ['A', 'B'].

naming the parent where the declaration before it is the parent’s (... widens the field as need type 'req' declares it: ...).

inherits. A type has one parent, given before or after it in needs_types, or added by an extension or a service. A type with no declaration of its own of a field reads its parent’s. An inherits naming no need type, or on a cycle, is ignored, and the type stays, without a parent; each is one needs.type_inherits warning, every type on a cycle reported:

Need type 'a' inherits 'b' on a cycle (a -> b -> a); its inherits is ignored.
Need type 'e' inherits 'nope', which is not a need type; its inherits is ignored.

Fields declared on need types alone. A fields entry naming a field that nothing else declares – no needs_fields entry, no core field, no link type, no field an extension or a service registers, nor a link type’s back links, <l>_back – declares a field of the types that declare it: by their own entry or an ancestor’s, and an entry that changes nothing ([needs.types.spec.fields.x] with no key) declares the field as it is. Every type that declares it agrees on its type, its items’ type, and whether it is derived; each is free in the rest. The first declaration of a type none of whose ancestors declares the field – in the order the types are resolved (a parent before its children; the members of a broken inherits cycle in the walk’s order, up from the first type given that is on the cycle or inherits into it, the last reached first: a inheriting b inheriting a, a given first, resolves b, then a; with c inheriting a given before both, the walk starts at c, and resolves b, then a, then c) – that gives a schema type sets them, so the order of needs_types decides which of two such declarations is refused; the first declaration of an array field gives its items’ type too (schema = { type = "array", items = { type = "string" } }). Such a declaration that gives no type (or no items’ type) takes the agreed one, a child narrows its parent’s as for any field, and a field no such declaration gives a type is refused on every entry, and does not exist. A declaration of another type, or derived where the field is not (or the other way round), is one needs.type_conflict warning:

needs_types['spec'].fields['x'] cannot be declared with type 'string' (items None): its type is 'integer' (items None) on every need type, as need type 'req' declares it; the entry is ignored

and the entry is ignored, and does not declare the field, so a child’s entry under it is a declaration of its own (refused too if its type or derivation is not the agreed one; an empty one takes the agreed type); an entry that cannot be used for another reason – it widens, or its default cannot be used – declares its field all the same, as it was. A field so declared whose name is close to that of a core field an author sets, a registered field or a link type (difflib.get_close_matches, cutoff 0.8) is likely misspelt, and is one needs.type_near_name warning, declared all the same (A misspelt field name):

needs_types['req'].fields['asl'] declares a field of need types 'req' alone; did you mean 'asil'?

The field is declared once for all, nullable and without a default, which each declaring type narrows: one that declares it not nullable, with no default, requires it on its own needs alone. On a need of a type that does not declare it, the field holds None, a derived one too. A value set for it in a need is ignored, as one needs.undeclared_for_type warning:

Field 'x' is not declared on need type 'spec' and cannot be set in need 'S_001'; the value '4' is ignored

and a need imported by needimport or from needs_external_needs drops it with the same warning, a derived one too (on a type that declares a derived field, its value from outside is kept, as data); a value equal to the one the need then holds – None, which a needs.json carries for every field – is dropped silently. A needextend setting, appending to or deleting it is refused on the needs of the type, one needs.needextend warning for each needextend, need type and option:

Option 'x' does not support extend operations on need type 'spec'; it does not extend 3 needs (S_001, S_002, S_003).

The field is a field of the project: its value enters the fingerprint of a need where it is not None, on a declaring need (its type’s default too), never on a need of another type. The needs.json carries it on every need, null on the needs of the other types, and its schema once, nullable, with no default, and the description Declared by need types 'req', 'spec', which names the declarations without a declaring ancestor that are not refused, not the types declaring it by inheritance. A derive makes it derived on every type that declares it (a child inheriting its parent’s rule), and a derived one takes no enum.

Fields an extension declares on need types alone. An extension declares a field on its own need types alone with add_field(name, description, types=[...]), as sphinx-test-reports declares case_name on its test cases. The field is then declared as one the types’ entries declare, absent on every other type in the same way (None, and a value set there one needs.undeclared_for_type warning), but its declaration is the extension’s: its schema, nullable and default, which a declaring type’s entry narrows, as for any field. A need type of the project that carries the field names it in its entry, which declares it there too (an empty entry declares it as the extension does):

[needs.types.test.fields.case_name]

A needs_fields entry of the same name is the field instead, on every need type, as for any field an extension registers. A need type types names that nothing declares by the time the schema is built is one needs.config warning, the field declared on the others:

Field 'points' (from add_field) is declared on need types 'story' and 'epic' alone, but 'epic' is no need type; the field is declared on the others

The needs.json schema carries the extension’s declaration, its description included, nullable where the extension’s is not: the needs of the other types hold null.

Link types declared on need types alone. A links entry naming a link type that nothing else declares – no needs_links or needs_extra_links entry, not links or parent_needs, no field, one declared on need types alone included, nor a link type’s back links, <l>_back – declares a link type of the types that declare it, as a fields entry declares a field: by their own entry or an ancestor’s, an empty entry included. Its back links are named <name>_back on every need, so one whose back links would have the name of a field or a link type is refused on every entry, one needs.type_conflict warning each, and does not exist:

needs_types['spec'].links['x'] declares 'x', whose back links would be 'x_back', which is a field; the entry is ignored

Every type that declares it agrees on its shape: whether it is derived, and the keys a needs_links entry gives a link type for every need type – incoming, outgoing, copy, allow_dead_links, summary, color, style, style_part, style_start and style_end. The first declaration of a type none of whose ancestors declares it, in the order the types are resolved (as for a field), sets them, an empty one too: the keys it gives, the defaults of a needs_links entry for the others (incoming is "<name> incoming", outgoing the name, copy and allow_dead_links are false, and summary is false, or true where a copy or collect computes the link type: a derived one, in the derive of a declaration not refused for another key), and derived if it gives a derive. Beside such a copy or collect, summary = false is refused in any declaration, the first included (needs.derive_invalid): the key is ignored and the declaration used, as on a needs_links entry. Every other declaration may repeat a value, and no more: one that gives another value – of a key the first declaration leaves out too – or is derived where the link type is not (or the other way round), is one needs.type_conflict warning:

needs_types['b'].links['rel'] cannot be declared with incoming 'related from': its incoming is 'rel incoming' on every need type, as need type 'a' declares it; the entry is ignored

and the entry is ignored: one of a type without a declaring ancestor does not declare the link type (a child’s entry under it is a declaration of its own), a child’s still declares it, through its parent. A name close to that of a field or link type declared elsewhere is one needs.type_near_name warning, as for a field (needs_types['req'].links['verifes'] declares a link type of need types 'req' alone; did you mean 'verifies'?). On a need of a type that does not declare it, the link type holds [], no links – where a field holds None: a list of links is never None, a needs.json carries every link type on every need, and an empty one is no links. A link set for it in a need is ignored, as one needs.undeclared_for_type warning:

Link type 'verifies' is not declared on need type 'spec' and cannot be set in need 'S_001'; the value 'R_001' is ignored

a need imported by needimport or from needs_external_needs drops its links with the same warning, a derived link type’s too (silently where they are []; on a declaring type a derived link type’s are kept, as data), and a needextend is refused on the needs of the type, one needs.needextend warning for each needextend, need type and option:

Option 'verifies' does not support extend operations on need type 'spec'; it does not extend 1 need (S_001).

Its back links, <name>_back, are on every need, as for any link type. target_types is not part of its shape: each root declaration (one of a type without a declaring ancestor) gives its own (a test may verify a req while a review verifies a spec), and the types inheriting from it narrow that one. With copy the links of the declaring needs are copied into links, and a need of another type copies none; copy beside a derive is reported as on a needs_links entry (needs.derive_invalid), and nothing is copied. copy = true is deprecated here as on a needs_links entry, one needs.deprecated warning per declaration writing it (needs_types['req'].links['verifies'] sets 'copy = true', ...): a union declared the same way replaces it. A derived one is derived on every type that declares it (a child inheriting its parent’s rule), and holds [] on the others. These link types come after the needs_links and needs_extra_links ones, in the order their first declarations are resolved: in a need’s links, a needflow legend, a needreport. The needs.json declares each once, with the description Declared by need types 'req', 'test', naming the declarations without a declaring ancestor that are not refused. A name one type declares under fields and another under links, neither declared otherwise, is a field when a declaration of a type without a declaring ancestor gives it a schema type, and the links entries are refused, as below; otherwise the fields entries are refused, and the links entries declare the link type.

What cannot be declared. A declaration that cannot be applied is ignored as a whole, as one needs.type_conflict warning, such as:

needs_types['spec'].links['x'] declares 'x', which is a field, not a link type; the entry is ignored

when it names no field of its table (a link type or a link type’s back links (links_back) under fields, a field or a link type’s back links under links, an empty name, or under fields a name no need type gives a schema type, above), changes the field’s type, which is the same on every need type (... cannot be declared with type 'integer' (items None): its type is 'string' (items None) on every need type; the entry is ignored), or carries a schema, default or predicates that cannot be used (a value of another type, a default of title, which takes none). A link type’s back links are computed on every need, so an entry naming them, in either table, declares nothing, and the back links are computed as without it; how many there must be is a back_links entry (below):

needs_types['spec'].links['links_back'] declares 'links_back', which is a link type's back links, whose count a need type declares under 'back_links' (needs_types['spec'].back_links['links']); the entry is ignored

Incoming links. A back_links entry, [needs.types.<t>.back_links.<l>], declares how many links of the link type l point to a need of the type, its back links <l>_back: schema = { minItems = 1 } says “every <t> is the target of at least one l link”, maxItems = 1 “of one at most”. l is any link type, one <t> declares or not (the links come from needs of other types); an entry naming no link type is one needs.type_conflict warning, and is ignored, naming the link type it is close to, if any (needs_types['req'].back_links['implemnts'] counts the back links of 'implemnts', which is not a link type; the entry is ignored; did you mean 'implements'?). It takes a description, a schema of minItems and maxItems alone (each a non-negative integer) and a severity; any other key, or another schema keyword, is one needs.type_conflict warning, and the entry is ignored as a whole:

needs_types['req'].back_links['satisfies'] sets 'default', but a need type declares only the description, schema (minItems, maxItems) and severity of a link type's back links ('satisfies_back'); the entry is ignored
needs_types['req'].back_links['satisfies'] gives the schema 'uniqueItems', but the schema of a link type's back links ('satisfies_back') takes only 'minItems' and 'maxItems'; the entry is ignored

The count is the length of the need’s <l>_back: every link of l to it, whatever the type of the need it comes from, a link that need’s target_types refuses included – as minItems counts the outgoing links. “At least one test” among sources of several types takes a schema rule (Incoming link validation (network_back)). It holds for the declaring type and every type inheriting from it, which may narrow it as any declaration (a minItems not lower, a maxItems not higher, a severity not lower; needs.type_widening otherwise). It is checked by the schema validation once every link is final, and a need failing it is a link_fail of the field <l>_back at that need, at the entry’s severity (violation by default):

ERROR: Need 'REQ_1' has schema violations:
  Severity:       violation
  Field:          satisfies_back
  Need path:      REQ_1
  Schema path:    links > schema > properties > satisfies_back > minItems
  Schema message: [] has less than 1 item [sn_schema_violation.link_fail]

So needs_schema_validation_enabled = False switches it off. A need from needs_external_needs is not counted: its own project’s links to it are not loaded here, so its count would be partial; a need needimport imports is this project’s, and is. A link to a part of the need (<id>.<part>) counts for the need, and so does a link to a part the need lacks: that link is a dead link where it is written (needs.link_outgoing), and still one of the need’s back links. The needs.json writes nothing new: the back links are in it as before.

A name belongs to one declaration, and the back links of a link type l claim l_back. Where two declarations claim one name, the back links of links and parent_needs win over any other declaration, a global one (needs_fields, needs_links and the others, an extension’s or a service’s) wins over a need type’s, and between two global ones a name declared outright wins over back links, so the link type whose back links collide is refused (needs_links), and a link type that is itself refused claims no name: of x, x_back and x_back_back, x_back is refused and x kept; between two link types need types declare alone, back links win: of x and x_back, the entries of x_back are refused. A link type refused for its back links leaves its own name to a need type’s field, unless that name is the back links of a link type that remains (as x_back in the chain above, or links_back). A core field may be declared like any other: status takes a default and an enum. A derived field or link type (one with derive or derive_by_type) takes only a description, a narrower schema, (a field) nullable, and a severity: its rules give its value, so a default or predicates is refused, and so is a link type’s target_types in this release, and so is a schema adding an enum to a field that has none, as its rules are checked against the field’s own declaration (a derived field declared on need types alone takes none).

Severity. A need failing its type’s declaration – a value outside its schema, a link count outside minItems and maxItems – is reported by the schema validation as a violation (sn_schema_violation.field_fail, .link_fail), and a need without a field its type declares nullable = false, with no default, is not created (needs.create_need). A declaration’s severity changes that for every constraint of the declaration as the type has it, its ancestors’ and the field’s own included: at "warning" or "info" the failure is reported as sn_schema_warning.* or sn_schema_info.* (a warning, not an error; both are logged at Sphinx’s WARNING level, as a schema rule’s are, so a -W build fails on either unless suppress_warnings names it), and a need without a value of a field not nullable is created, the field None, and reported at that severity (Field 'x' is not nullable, but no value or default was given., schema path fields > nullable). It is then checked by the schema validation alone, so needs_schema_validation_enabled = False silences it. The needs.json writes such a field nullable, with a null default, as a need may hold null of it: its needs_schema is one block for every need type, so the field is nullable there as a whole, while one every need type declares not nullable at violation is written as it is declared. A type inheriting a declaration keeps its severity (see Narrowing). A needs_fields or needs_links entry takes no severity: what it declares fails as a violation where no need type gives one, and a severity there is one needs.config warning, and ignored:

needs_fields['asil'] sets 'severity', which is declared on a need type's entry ([needs.types.<type>.fields.asil]); it is ignored here

A lowered severity is reported as the type whose entry gave it declares it, which may be an ancestor further up than the nearest type with an entry of the field (... widens the field as need type 'req' declares it: Child 'severity' 'info' is lower than parent 'severity' 'warning'.).

The value of a need. A field a need of the type does not set takes the first matching predicate of the type’s declaration (the field’s own, unless the type declares predicates), else the type’s default, else the field’s default; a value set in the need wins over all of them. In conf.py, "default": None gives a nullable field no default on the type (its needs leave it unset), and is refused (needs.type_conflict) on a field that is not nullable. A needextend deleting a field (:-x:) empties it as the need’s type declares it: None where the field is nullable on that type, else the empty value of the field’s type. A default a type declares is not the one a fingerprint compares against: a need’s value equal to its type’s default enters the fingerprint, unless it equals the field’s own default too. Nor is it in the needs.json, whose needs_schema is the schema every need type shares: no need type’s narrowing is in it (its enum, its default, a field it makes not nullable at the default severity), the default it gives a field, which needs_json_remove_defaults compares against, is never a need type’s, and a reader that has only the file checks less than the project that wrote it did.

The warnings of these declarations, given when the schema is built, name an entry by its directive in either shape (needs_types['spec']), while those given when the configuration is read name an entry of the list by its position (needs_types entry 2 ('spec')). An entry an extension adds to needs_types once the configuration is read has the shape of its inherits, fields and links checked when the schema is built, with the same needs.config warnings; once the schema is built it is complete, and nothing declares a field later.

The executable half of this section is a conformance corpus, packages/sphinx-needs/tests/fixtures/field_declaration_conformance.toml in the sphinx-needs repository: one project per rule, with the values its needs hold and the warnings it gives, which sphinx-needs’ test suite runs and ubCode is to vendor, and to be held to.

needs_fields

Added in version 7.0.0.

This setting allows you to customise the fields that can be used for each need; how they are defined, processed, and validated.

needs_fields must be a dictionary, where each key is the name of the field, and the value is another dictionary defining the field.

Fields can either “specialize” existing core fields or define completely new ones. A core field a need computes, such as type_name or docname, takes no entry: one naming it is ignored, with a needs.config warning, needs_fields entry 'type_name' names the core field 'type_name', which a project cannot declare; the entry is ignored.

For new fields the following can be defined:

  • description: A description of the field (optional).

    This will be output in the schema of the needs.json, and can be used by other tools.

  • schema: A schema definition for the field (optional).

    This uses the same format as needs_schema_definitions and needs_schema_definitions_from_json. If specified, a value of another type is refused: given in a need (its directive, a needimport or needs_external_needs), the need is not created; from a needextend or a dynamic function, the value alone is refused, with a warning; as a default or in predicates, it is refused when the configuration is read. The other constraints are checked by the schema validation, see Schema validation for more details. By default the field schema will be {"type": "string"}.

  • nullable: If set to True, the field can be set to None (optional), e.g. if no value is specifically given and no default applies,

    If False, the field must have a value (either explicitly set or via default/predicates), otherwise the need is invalid and will not be created (unless a need type’s entry gives the field a severity below violation, which reports it instead: Fields per need type).

  • predicates: A list of (match expression, value) tuples (optional).

    If specified, these will be evaluated in order for any need that does not explicitly set the field, with the first match setting the field value.

  • default: A default value for the field (optional).

    If specified, this value will be used for any need that does not explicitly set the field and does not match any predicates.

  • parse_variants: If set to True, the field will support variant options and variant data references.

    Default: False.

  • parse_dynamic_functions: If set to True, the field will support Dynamic functions.

    Default: the value of needs_parse_dynamic_functions (True).

  • derive: A rule computing the field for every need (optional), which makes it a derived field:

    a table naming a kind and the kind’s roles; with derive_by_type beside it, for every need of a type derive_by_type does not list. A derived field cannot be set in a need or by a needextend, and takes no default or predicates. New in version 9.0.0.

  • derive_by_type: Rules per need type (optional), which make it a derived field too,

    the spelling of a derive for a need type the project does not declare, such as a GitHub service’s, and an older one of a derive in a need type’s own entry (Rules per need type): a table of need type (the directive name, as type holds it) to a rule, as derive takes one, overriding derive on that type. A need of a type without a rule holds the default (a literal, given only without derive), else None, or the empty value of the field’s type when it is not nullable. The field is derived on every need type, see Rules per need type. New in version 9.0.0.

Any other key in an entry, such as a misspelt derive, is ignored and the entry kept, one needs.config warning per key, naming the entry, the key and the keys an entry has (a name, left from a needs_extra_options entry, is accepted where it repeats the entry’s name, and reported where it gives another, needs_fields['level'] gives 'name' = 'lvl', which differs from the entry's name 'level'; it is ignored):

needs_fields['total'] has an unknown key 'dervie'; known keys are default, derive, derive_by_type, description, nullable, parse_dynamic_functions, parse_variants, predicates, schema; the key is ignored

A keyword the schema of the field’s type does not have (enmu, or minimum on a string), at the top of the schema or in its items or contains, is dropped and the rest of the schema kept, one needs.config warning per keyword:

needs_fields['asil'].schema has an unknown keyword 'enmu'; known keywords of a schema of type 'string' are const, enum, format, maxLength, minLength, pattern, type; the keyword is ignored

The same holds for a core field’s entry, whose type it may leave out, and for the schema of a field an extension or a service registers (add_field['x'].schema ...). Such a keyword stopped the build until this release. A need type’s own entry is checked apart: a declaration there with an unknown key or keyword is reported as described in Fields per need type.

A need type may declare a field anew for its needs, narrowing it, or declare one no needs_fields entry declares, for the needs of the types that declare it alone: see Fields per need type.

A field named as a link type’s back links, <name>_back, is kept, and the link type is refused (needs_links); but a field named links_back or parent_needs_back, the back links of the link types every project has, is ignored, one needs.config warning, as it is when an extension or a service registers it.

A directive option matches a field or link type ignoring case, in reStructuredText and in MyST alike, and the value is stored under the name as declared: a field declared Owner is set by :Owner:, :owner: or :OWNER: on a need directive, a needextend or a needservice, and is Owner in the needs.json, in filters and in table columns; MyST’s :Status: sets status. (docutils lowercases the name of every reStructuredText option, which made a field or link type declared with capitals unreachable from it.) An option written exactly as a name matches it first, so nothing set before changes; where MyST writes one name twice in two cases, that option – or else the first written – keeps its value, and the other is ignored with a warning (needs.directive; needs.needextend on a needextend). Two names equal ignoring case cannot be told apart, so they are a configuration error that stops the build: two fields (Owner and owner), a field and a core field (Status), a field and a link type, two link types, a link type or field and a link type’s back links (Tests_Back beside the link type tests), or one of these and an option a directive reads itself (Strict and needextend’s strict). Names spelt alike keep what they always did: an entry of a core field’s own name specialises it.

For example:

needs_fields = {
    "introduced": {
        "description": "Date when the need was introduced",
        "schema": {
            "type": "string",
            "format": "date",
        },
        "nullable": False,
    },
    "cost": {
          "description": "Approximated cost in Euros",
          "schema": {
             "type": "number",
             "minimum": 0,
          },
          "predicates": [
             ('"high" in tags', 10000),
             ('"medium" in tags', 5000),
          ],
          "default": 0,
    },
}

These fields would then be available to set in need directives, such as:

.. req:: My Requirement
   :id: REQ_001
   :status: open
   :introduced: 2024-01-15
   :cost: 1500.50

Note

To filter on these fields in needlist, needtable, etc. you must use the Filtering needs option.

Core field specialization

The following core fields can be specialized:

Name

Type

Nullable

Default

title

string

false

status

string

true

tags

array(string)

false

[]

collapse

boolean

false

False

hide

boolean

false

False

layout

string

true

style

string

true

template

string

true

pre_template

string

true

post_template

string

true

constraints

array(string)

false

[]

Specialization allows you to redefine the description and tighten the schema of these fields: Schemas will inherit any constraints defined in the core schema that are not redefined, and redefinitions must be not weaken the constraints of the original schema (this is intended to obey the Liskov substitution principle). For example, you could redefine the status and tags fields to only allow certain values:

needs_fields = {
    "status": {
        "schema": {
            # inherits "type": "string" from core schema
            # adds tighter constraint on allowed values
            "enum": ["open", "in progress", "done", "closed"],
        },
        # adds tighter constraint on nullability,
        # i.e. the status must always be set
        "nullable": False,
    },
      "tags": {
         "schema": {
               # inherits "type": "array" from core schema
               "items": {
                  # inherits "type": "string" from core schema
                  # adds tighter constraint on allowed item values
                  "enum": ["important", "complex", "external", "internal"],
               },
               # adds tighter constraint on array length
               "minItems": 1,
         },
      },
}

The following would be invalid specializations:

needs_fields = {
    "title": {
        "schema": {
            # invalid: core schema allows only strings
            "type": "number",
        },
    },
    "tags": {
        "schema": {
            "items": {
                # invalid: core schema allows only string
                "type": "number",
            },
        },
    },
}

Default values

Default values either must match the type defined in the schema for the field, or can be dynamic values, that resolve to a value of the correct type.

For predicates, the match expression is a string, using Python syntax, that will be evaluated against data from each need (before the resolution of defaults or dynamic functions etc):

  • id (str)

  • type (str)

  • title (str)

  • tags (tuple[str, ...])

  • status (str | None)

  • docname (str | None)

  • is_external (bool)

  • is_import (bool)

  • needs_fields

  • needs_links (tuple[str, ...])

  • needs_variant_data (via the var namespace)

An expression that cannot be evaluated, such as one naming something not in this list, is reported as a needs.config warning and then skipped, so that the remaining predicates and the default apply just as they would for an expression that did not match. The c.source facets of a filter (Filtering by where a need comes from (c.source)) are not in it, as a predicate is evaluated while the need is created, with no check context: c.source.path there is reported as name 'c' is not defined; the c.source facets are not available in a field predicate.

For example:

needs_fields = {
    "field1": {
      "schema": {"type": "string"},
      "predicates": [
         # if status is "done", set to "value1"
         ("status == 'done'", "value1"),
         # else if status is "ongoing", set to a dynamic value
         ("status == 'ongoing'", '[[copy("yyy")]]'),
      ],
      # the base default is a dynamic value
      "default": '[[copy("xxx")]]',
    },
}

Derived fields

A derive or derive_by_type table in a field’s entry, or in a needs_links entry, makes the field or link type derived: a rule computes its value for every need, and an author does not write it. The kinds, their roles and how a rule is computed are described in Derived fields.

needs_variant_data

Added in version 8.2.0.

Provides structured variant data accessible under the var namespace in filter expressions. This replaces the flat needs_filter_data option with a namespaced, nested data structure that avoids collisions with need field names.

The dot-access syntax (var.build.debug) is more readable than dictionary-style access (var["build"]["debug"]) and mirrors Jinja2 template syntax, which Sphinx users are already familiar with.

Configuration example:

needs_variant_data = {
    "cpu": "arm",
    "debug": True,
    "build": {
        "optimization": 2,
        "features": ["feature_a", "feature_b"],
    },
}

The data is then available in filter expressions via the var namespace:

.. needtable::
   :filter: var.cpu == "arm" and var.build.debug == True

.. needlist::
   :filter: "feature_a" in var.build.features

Allowed data shape:

  • Top-level must be a dictionary with string keys.

  • Intermediate nodes: dictionaries only.

  • Leaf values: str, bool, int, float, or uniform lists of these types.

  • Arrays must be uniform (all elements the same scalar type).

  • No None values, no dictionaries inside arrays.

Accessing a missing key raises an AttributeError, which helps catch typos in filter expressions.

The var namespace can also be referenced directly within need field values using the <{ … }> syntax.

Default: {}

In a toml file the inline table is data in the [variants] table.

See also

needs_variant_data_file for loading variant data from a JSON file.

needs_variant_data_file

Added in version 8.2.0.

Changed in version 8.4.0: The file is loaded while the configuration is being initialised, rather than once document reading starts.

Path to a JSON file containing variant data. The file is loaded and its contents are made available under the var namespace, just like needs_variant_data.

If both needs_variant_data_file and needs_variant_data are set, the file is loaded first and the inline dictionary is deep-merged on top (inline values win on conflict).

The path is resolved relative to the Sphinx confdir (the directory containing conf.py). In a toml file the file is data_file in the [variants] table, and it is resolved relative to the directory containing the toml file.

The file is read during configuration initialisation (a file named in the toml file is read twice there: once when the toml file is read, and once when the variant data is resolved), so a missing file or one whose contents are not valid variant data fails the build before any document is read. The merged result becomes the value of needs_variant_data, which means it is also what Sphinx compares between builds: editing the file changes the configuration and re-reads every document, while leaving it alone no longer does.

Configuration example:

needs_variant_data_file = "variants/arm_debug.json"

Where variants/arm_debug.json contains:

{
  "cpu": "arm",
  "debug": true,
  "build": {
    "optimization": 2,
    "features": ["feature_a", "feature_b"]
  }
}

This is particularly useful for switching configurations at build time:

sphinx-build -D needs_variant_data_file=variants/x86_release.json docs/ _build/

Default: None

needs_allow_unsafe_filters

Allow unsafe filter for Filter function. Default is False.

If set to True, the filtered results will keep all fields as they are returned by the dynamic functions. Fields can be added or existing fields can even be manipulated. A field with a derive rule cannot be manipulated, whatever this option says: need[name] = value on one raises KeyError, and the build fails.

Note

Keep in mind this only affects the filter results, original needs as displayed somewhere else are not modified.

If set to False, the filter results contains the original need fields and any manipulations of need fields are lost.

needs_allow_unsafe_filters = True

needs_filter_max_time

Added in version 4.0.0.

If set, warn if any filter processing call takes longer than the given time in seconds.

needs_views_max_items

Added in version 8.4.0.

The maximum number of items a view directive shows, when it does not set its own max_items option.

It applies to needlist, needtable and needflow, which count needs (and need parts), and to needsequence, which counts messages. The limit is applied after filtering and sorting, so a view keeps the first items it would otherwise have shown, and reports how many it is hiding. A truncated view says so in the page and emits a needs.max_items warning, so that a build does not have to be read page by page to find it; a project that caps deliberately can silence the warning with suppress_warnings = ["needs.max_items"].

A value of 0 means that nothing is limited. A single view can opt out of a project-wide limit again with :max_items: 0.

needs_views_max_items = 50

Default: 0

needs_uml_process_max_time

Added in version 4.0.0.

If set, warn if any needuml or needarch jinja content rendering takes longer than the given time in seconds.

needs_flow_engine

Added in version 3.0.0.

Select between the rendering engines for needflow diagrams,

  • plantuml: Use PlantUML to render the diagrams (default).

  • graphviz: Use Graphviz to render the diagrams.

Any other value is reported as a needs.config warning, once for the project, and every diagram is drawn with the default engine.

needs_flow_direction

Added in version 8.4.0.

The direction needflow diagrams flow in by default: down (the default), up, right or left.

needs_flow_direction = "right"

A diagram overrides it with direction; only a diagram that does not set the option consults this value.

needs_flow_legends

Added in version 8.4.0.

Named legend configurations that a diagram selects by name with show_legend.

needs_flow_legends = {
    "beside": {"parts": ["types", "links"], "placement": "external"},
}

Default value: {}.

parts is a list of the sections to describe – types, links or both – in the order they are shown; it defaults to ["types"].

Order is contract, not an artefact of how the list happens to be written: ["links", "types"] puts the link table first and keeps it there on every engine, so a reader scanning two diagrams finds the same section in the same place.

Only a list is accepted. A bare string such as "both" is reported and ignored – a single name cannot express an order, and a second accepted spelling would have to keep meaning the same thing in every tool that reads this configuration.

placement is a preference, not a demand:

internal

Draw the legend inside the picture where the engine can, and beside it where the engine cannot.

external

Draw the legend beside the picture, as a document table. The table looks the same on every engine, its text is selectable and searchable, and it can describe link types – which no in-diagram legend ever could.

Unset, placement takes the engine’s own default placement. There is no single right answer to write down here: both engines in Sphinx-Needs can draw a legend of need types inside the picture and always have, so unset means internal for them, while an engine with no legend construct at all has only the external table to fall back on and unset means external for it. Naming the engine’s default, rather than a fixed value, is what keeps one contract across the tools that read this key.

An engine that cannot draw the legend asked for inside the picture substitutes the external one without warning. Both engines here draw an in-image legend of need types, and neither can describe link types that way, so a legend whose parts include links is always drawn beside the diagram however it was placed.

That substitution is silent by design. The two legends carry identical information and differ only in where they sit, so it is a cosmetic one, and a warning about it would be unactionable on a project whose other engine can never satisfy the preference.

An entry that cannot be used is reported as a needs.config warning, once for the project, and the rest of the configuration is still read.

needs_flow_show_legend

Added in version 8.4.0.

Which entry of needs_flow_legends a diagram gets when it asks for a legend without naming one.

needs_flow_show_legend = "beside"

Default value: "".

This selects which legend, never whether one is drawn: a diagram still has to ask, with show_legend. There is deliberately no project-wide way of putting a legend on every diagram – a legend describes one picture, and the decision belongs with that picture.

A diagram that names its own legend overrides this; a diagram whose name is not defined falls back to it, having said so. If this value names nothing either, that is reported once for the build and the engine’s own legend is drawn.

needs_flow_configs

Added in version 0.5.2.

needs_flow_configs must be a dictionary which can store multiple PlantUML configurations. These configs can then be selected when using needflow.

needs_flow_configs = {
   'my_config': """
       skinparam monochrome true
       skinparam componentStyle uml2
   """,
   'another_config': """
       skinparam class {
           BackgroundColor PaleGreen
           ArrowColor SeaGreen
           BorderColor SpringGreen
       }
   """
}

This configurations can then be used like this:

Example 2

.. needflow::
   :tags: flow_example
   :types: spec
   :config: lefttoright,my_config

@startuml

' Config

left to right direction
skinparam monochrome true
skinparam componentStyle uml2


' Nodes definition 

node "<size:12>Specification</size>\n**A specification**\n<size:10>spec_flow_001</size>" as spec_flow_001 [[../directives/needflow.html#spec_flow_001]] #FEDCD2{
'parts:
rectangle "<size:12>Specification (part)</size>\n**A testable part**\n**of the**\n**specification**\n<size:10>spec_flow_001.**subspec_1**</size>" as spec_flow_001.subspec_1 [[../directives/needflow.html#spec_flow_001.subspec_1]] #FEDCD2
rectangle "<size:12>Specification (part)</size>\n**Another**\n**testable part**\n**of the**\n**specification**\n<size:10>spec_flow_001.**subspec_2**</size>" as spec_flow_001.subspec_2 [[../directives/needflow.html#spec_flow_001.subspec_2]] #FEDCD2
'child needs:
node "<size:12>Specification</size>\n**A child**\n**specification**\n<size:10>spec_flow_003</size>" as spec_flow_003 [[../directives/needflow.html#spec_flow_003]] #FEDCD2
}
node "<size:12>Specification</size>\n**Another**\n**specification**\n<size:10>spec_flow_002</size>" as spec_flow_002 [[../directives/needflow.html#spec_flow_002]] #FEDCD2

' Connection definition 

spec_flow_002 -[#AA0000]-o spec_flow_001

@enduml

Multiple configurations can be used by separating them with a comma, these will be applied in the order they are defined.

See needflow config option for more details and already available configurations.

needs_graphviz_styles

Added in version 3.0.0.

This must be a dictionary which can store multiple Graphviz configurations. These configs can then be selected when using needflow and the engine is set to graphviz.

Each configuration maps an element type – root, graph, node or edge – to a mapping of the attributes to set on it. An element type holding anything else is reported as a needs.needflow warning and ignored, rather than failing the build.

needs_graphviz_styles = {
    "my_config": {
        "graph": {
            "rankdir": "LR",
            "bgcolor": "transparent",
        },
        "node": {
            "fontname": "sans-serif",
            "fontsize": 12,
        },
        "edge": {
            "color": "#57ACDC",
            "fontsize": 10,
        },
    }
}

This configurations can then be used like this:

.. needflow::
    :engine: graphviz
    :config: lefttoright,my_config

Multiple configurations can be used by separating them with a comma, these will be merged in the order they are defined. For example my_config1,my_config2 would be the same as my_config3:

needs_graphviz_styles = {
    "my_config1": {
        "graph": {
            "rankdir": "LR",
        }
    },
    "my_config2": {
        "graph": {
            "bgcolor": "transparent",
        }
    }
    "my_config3": {
        "graph": {
            "rankdir": "LR",
            "bgcolor": "transparent",
        }
    }
}

needs_report_template

Added in version 1.0.1.

You can customise the layout of needreport with a template of your own. Set needs_report_template to the path of the template file:

needs_report_template = "/needs_templates/report_template.need"

Finding the template

needs_report_template is resolved relative to the source directory — the directory Sphinx reads the documents from, which is also the directory holding conf.py unless sphinx-build -c separates the two. A leading / is stripped before that join, so "/needs_templates/report_template.need" and "needs_templates/report_template.need" name the same file.

A POSIX-style absolute path is therefore not read from where it points. It is stripped and joined onto the source directory like any other value, which normally ends in a Could not load needs report template file ... warning naming a path that does not exist.

On Windows a drive-letter path such as D:\templates\report.need is an exception: it is not a relative path, so joining it onto the source directory replaces it, and the file is read from where it points. The rebase above applies to POSIX-style absolute values.

The first of the following that is set provides the template:

  1. the :template: option of an individual needreport directive (see template), resolved relative to the document the directive is written in;

  2. needs_report_template, resolved relative to the source directory as described above;

  3. otherwise the packaged default template shown below.

Note

The file extension is not checked, so any is accepted; .rst, .need and .txt are the conventional ones. Prefer .need or .txt: a template named .rst and placed inside the source directory is also read by Sphinx as a document in its own right, and its unrendered Jinja source then produces a cascade of parse warnings. To keep the .rst extension, exclude the template from the build:

exclude_patterns = ["needs_templates/*.rst"]

The packaged default template

If you do not set needs_report_template, this template, shipped with Sphinx-Needs, is used:

packages/sphinx-needs/src/sphinx_needs/directives/needreport_template.rst
{# Output for needs_types #}
{% if types|length != 0 %}

.. {{ report_directive }}:: Need Types

   .. list-table::
      :widths: 40 20 20 20
      :header-rows: 1

      * - TITLE
        - DIRECTIVE
        - PREFIX
        - STYLE
      {% for type in types %}
      * - {{ type.title }}
        - {{ type.directive }}
        - `{{ type.prefix }}`
        - {{ type.style }}
      {% endfor %}
{% endif %}
{# Output for needs_types #}

{# Output for needs_links #}
{% if links|length != 0 %}

.. {{ report_directive }}:: Need Links

   .. list-table::
      :widths: 10 30 30 5 20
      :header-rows: 1

      * - NAME
        - INCOMING
        - OUTGOING
        - COPY
        - ALLOW DEAD LINKS
      {% for link in links %}
      * - {{ link.option | capitalize }}
        - {{ link.incoming | capitalize }}
        - {{ link.outgoing | capitalize }}
        - {{ link.get('copy', None) | capitalize }}
        - {{ link.get('allow_dead_links', False) | capitalize }}
      {% endfor %}
{% endif %}
{# Output for needs_links #}

{# Output for needs_fields #}
{% if options|length != 0 %}

.. {{ report_directive }}:: Need Fields

   {% for option in options %}
   * {{ option }}
   {% endfor %}
{% endif %}
{# Output for needs_fields #}

{# Output for needs metrics #}
{% if usage %}

.. {{ report_directive }}:: Need Metrics

   .. list-table::
      :widths: 40 40
      :header-rows: 1

      * - NEEDS TYPES
        - NEEDS PER TYPE
      {% for type in usage["needs_types"] %}
      * - {{ type | capitalize }}
        - :need_count:`type=="{{ type }}"`
      {% endfor %}
      * - **Total Needs Amount**
        - :need_count:`True`
{% endif %}
{# Output for needs metrics #}

Note

dropdown is provided neither by Sphinx nor by Sphinx-Needs. It comes from an extension that supplies one, for example sphinx-design. If no loaded extension provides it, the report is rendered with admonition instead and a needs.needreport warning says so. To choose the directive yourself — and to silence that warning — name one through needs_render_context:

needs_render_context = {
    "report_directive": "admonition",
}

A value set that way is always used exactly as given, "dropdown" included: an explicit choice is never substituted, so a project that asks for dropdown without a provider keeps failing as it did before.

The substitution is decided on the rendered report, and is made only when it changes it. A template of your own that never renders a dropdown — because it writes its own directive, or shadows report_directive with a {% set %} — is left alone and warns about nothing. A template with .. dropdown:: hardcoded in it is also left alone: re-rendering cannot reach a name the template does not read from the context, so nothing would be fixed, and that report keeps the errors it gets today. Should the substituted render fail where the default one succeeded, the default is kept and nothing is reported — the fallback can leave a report as it was, never lose it.

The decision is a textual scan of the rendered report, so it has no notion of reStructuredText block context: a report that merely shows .. dropdown:: as example markup — inside a literal block, say — while producing it through report_directive is treated as though it used it, and the example shown will name admonition instead.

Template context

Templates are rendered with MiniJinja, which implements a large subset of Jinja but is not identical to it, so a template written strictly against the Jinja documentation may still fail here.

The following five names are passed to every template, and are all reserved: needs_render_context is merged over them, so an entry of the same name replaces the value described below. That is the intended way to set report_directive; doing it to any of the other four is reported as a needs.needreport warning.

types

The needs_types configuration, as a list of dictionaries, plus any types registered by a loaded service or extension.

links

The needs_links configuration, as a list of dictionaries carrying the keys option, incoming, outgoing, copy and allow_dead_links.

options

The names of the configured needs_fields, as a list of strings, plus any fields registered by a loaded service or extension.

report_directive

The name of the directive each section of the packaged template is wrapped in. dropdown, unless needs_render_context names another one, or nothing provides dropdown and substituting admonition changes what the report renders — see the note above.

usage

A dictionary with the keys needs_amount and needs_types, the latter holding one entry per directive name in needs_types.

Warning

Only the keys of usage["needs_types"] carry information. Every number in usage — needs_amount included — is permanently 0, and is kept only for backwards compatibility: the directive runs while the documents are still being read, so no correct count exists yet at that point. A template that prints one of these values reports 0 however many needs the project has.

Real counts come from the need_count role, which is evaluated once every document has been read. That is why the packaged template above reads usage for its type names only, and emits one role per name.

Such counts cover the whole project: needs from every document, needs pulled in by needs_external_needs, and need parts, which each count as a need of their parent’s type.

needs_diagram_template

This option allows to control the content of diagram elements which get automatically generated by using .. needflow:: / needflow (when using the plantuml engine).

This function is based on plantuml, so that each supported style can be used.

The rendered template is used inside the following plantuml syntax and must care about leaving the final string valid:

'node "YOUR_TEMPLATE" as need_id [[need_link]]'

By default the following template is used:

{%- if is_need -%}
<size:12>{{type_name}}</size>\\n**{{title|wordwrap(15, wrapstring='**\\\\n**')}}**\\n<size:10>{{id}}</size>
{%- else -%}
<size:12>{{type_name}} (part)</size>\\n**{{content|wordwrap(15, wrapstring='**\\\\n**')}}**\\n<size:10>{{id_parent}}.**{{id}}**</size>
{%- endif -%}

Displaying ports in a needflow

The PlantUML portin and portout styles can show interface ports inside a containing need. Define a need type for the container and each direction of port, then use needs_diagram_template to keep the port labels compact. The example defines the complete needs_types list; add these entries to your existing list if the project also uses other need types:

# conf.py
needs_types = [
    {
        "directive": "block",
        "title": "Block",
        "prefix": "B_",
        "color": "#BFD8D2",
        "style": "node",
    },
    {
        "directive": "inport",
        "title": "Input Port",
        "prefix": "IP_",
        "color": "#FEDCD2",
        "style": "portin",
    },
    {
        "directive": "outport",
        "title": "Output Port",
        "prefix": "OP_",
        "color": "#DF744A",
        "style": "portout",
    },
]

needs_diagram_template = """
{%- if type in ["inport", "outport"] -%}
{{ title }}
{%- elif is_need -%}
<size:12>{{type_name}}</size>\\n**{{title|wordwrap(15, wrapstring='**\\\\n**')}}**\\n<size:10>{{id}}</size>
{%- else -%}
<size:12>{{type_name}} (part)</size>\\n**{{content|wordwrap(15, wrapstring='**\\\\n**')}}**\\n<size:10>{{id_parent}}.**{{id}}**</size>
{%- endif -%}
"""

Nest the port needs in the containing block and include all three needs in the same needflow:

.. block:: Controller
   :id: CONTROLLER
   :tags: controller_ports

   .. inport:: Sensor input
      :id: SENSOR_INPUT
      :tags: controller_ports

   .. outport:: Actuator command
      :id: ACTUATOR_COMMAND
      :tags: controller_ports

.. needflow::
   :tags: controller_ports
   :engine: plantuml

The nested directives set the parent-child relationship that makes PlantUML place the ports inside CONTROLLER. The compact template applies only to the two port directives; all other need types retain the default diagram label.

Note

portin and portout are PlantUML-specific styles. Use the PlantUML needflow engine for this layout.

needs_id_required

Added in version 0.1.19.

Forces the user to set an ID for each need, which gets defined.

So no ID is autogenerated any more, if this option is set to True:

needs_id_required = True

By default this option is set to False.

Example:

.. With needs_id_required = True

.. req:: Working Requirement
   :id: R_001

.. req:: **Not working**, because :id: is not set.


.. With needs_id_required = False

.. req:: This works now!

needs_id_from_title

Generates needs ID from title. By default, this setting is set to False.

When no need ID is given by the user, and needs_id_from_title is set to True, then a need ID will be calculated based on the current need directive prefix, title, and a hashed value from title.

Example 3

.. req:: Group big short
Requirement: Group big short R_446C7

The calculated need ID will be: R_GROUP_BIG_SHORT_{hashed value}, if the need ID length doesn’t exceed the setting from needs_id_length.

Note

The user needs to ensure the uniqueness of the given title, and also match the settings of needs_id_length and needs_id_regex.

needs_parse_dynamic_functions

Added in version 7.0.0.

Sets the global default for whether Dynamic functions ([[...]]) are parsed in extra fields and link fields.

When True (the default), all extra fields and links will have dynamic function parsing enabled unless explicitly set to False per-field/link via needs_fields or needs_links.

# Disable dynamic function parsing globally
needs_parse_dynamic_functions = False

# Then opt-in per field
needs_fields = {
    "my_field": {
        "parse_dynamic_functions": True,
    },
}

By default this option is set to True for backward compatibility. In a future major release, the default will change to False.

needs_title_optional

Added in version 0.2.3.

Normally a title is required to follow the need directive as follows:

.. req:: This is the required title
    :id: R_9999

By default this option is set to False.

When this option is set to True, a title does not need to be provided, but either some content or an :id: element will be required. If a title is not provided and no ID is provided, then an ID will be generated based on the content of the requirement.

It is important to note in these scenarios that titles will not be available in other directives such as needtable, needlist, needflow.

A title can be auto-generated for a requirement by either setting needs_title_from_content to True or providing the flag :title_from_content: as follows:

The resulting requirement would have the title derived from the first sentence of the requirement.

Example 4

.. req::
   :title_from_content:

   This will be my title.  Anything after the first sentence will not be
   part of the title.
Requirement: This will be my title R_D8F29

This will be my title. Anything after the first sentence will not be part of the title.

needs_title_from_content

Added in version 0.2.3.

This setting defaults to False. When set to True and a need does not provide a title, then a title will be generated using the first sentence in the content of the requirement. The length of the title will adhere to the needs_max_title_length setting (which is not limited by default).

Note

When using this setting be sure to exercise caution that special formatting that you would not want in the title (bulleted lists, nested directives, etc.) do not appear in the first sentence.

If a title is specified for an individual requirement, then that title will be used over the generated title.

Example 5

.. req::
   :id: R_ERROR_LOGGING

   The tool must have error logging.
   All critical errors must be written to the console.
Requirement: R_ERROR_LOGGING

The tool must have error logging. All critical errors must be written to the console.

needs_max_title_length

This option is used in conjunction with auto-generated titles as controlled by needs_title_from_content and title_from_content. By default, there is no limit to the length of a title.

If you provide a maximum length and the generated title exceeds that limit, then we use an elided version of the title.

When generating a requirement ID from the title, the full generated title will still be used.

Example:

Requirement: This is a requirement with a very long title that will need to be R_565A6

This is a requirement with a very long title that will need to be shortened to prevent our titles from being too long. Additional content can be provided in the requirement and not be part of the title.

needs_file

Added in version 0.1.30.

Defines the location of a JSON file, which is used by the builder needs as input source. Default value: needs.json.

needs_css

Added in version 0.1.42.

Defines the location of a CSS file, which will be added during documentation build.

If path is relative, Sphinx-Needs will search for related file in its own CSS-folder only! Currently supported CSS files:

  • blank.css : CSS file with empty styles

  • modern.css: modern styles for a need (default)

  • dark.css: styles for dark page backgrounds

Use it like this:

needs_css = "blank.css"

To provide your own CSS file, the path must be absolute. Example:

import os

conf_py_folder = os.path.dirname(__file__)
needs_css =  os.path.join(conf_py_folder, "my_styles.css")

See Sphinx-needs CSS option for available CSS selectors and more.

needs_role_need_template

Added in version 0.1.48.

Changed in version 8.3.0: The template is now rendered with Jinja instead of Python’s str.format. Replace {field} placeholders with {{ field }}. The old str.format syntax is still supported for now but is deprecated and emits a needs.deprecated warning.

Provides a way of changing the text representation of a referenced need.

If you use the role need, Sphinx-Needs will create a text representation of the referenced need. By default a referenced need is described by the following string:

{{ title }} ({{ id }})

By using needs_role_need_template this representation can be easily adjusted to own requirements.

Here are some ideas, how it could be used inside the conf.py file:

needs_role_need_template = "[{{ id }}]: {{ title }}"
needs_role_need_template = "-{{ id }}-"
needs_role_need_template = "{{ type }}: {{ title }} ({{ status }})"
needs_role_need_template = "{{ title }} ({{ tags }})"
needs_role_need_template = "[{{ id }}] {{ title }} ({{ status }}) {{ type_name }}/{{ type }} - {{ tags }} - {{ links }} - {{ links_back }} - {{ content }}"
needs_role_need_template = "{% if type == 'spec' %}[SPEC] {{ title }}{% else %}[{{ type | upper }}] {{ title }}{% endif %}"

needs_role_need_template must be a Jinja string, which supports the following variables:

  • id or id_complete

  • id_parent

  • id_part

  • type (short version)

  • type_name (long, human readable version)

  • title

  • status

  • tags, joined by “;”

  • links, joined by “;”

  • links_back, joined by “;”

  • content

  • is_need

  • is_part

To access the same values via an object, use need (for example {{ need.type }}).

Jinja filters and control structures are supported. Please see https://jinja.palletsprojects.com/ for syntax and features.

RST-attributes like **bold** are not supported.

needs_role_need_max_title_length

Added in version 0.3.14.

Defines the maximum length of need title that is shown in need references.

By default, need titles that are longer than 30 characters are shortened when shown in need text representation and “…” is added at end. By using needs_role_need_max_title_length, it is possible to change this maximum length.

If set to -1 the title will never be shortened.

# conf.py
needs_role_need_max_title_length = 45

needs_table_style

Added in version 0.2.0.

Defines the default style for each table. Can be overridden for specific tables by setting parameter style of directive needtable.

# conf.py
needs_table_style = "datatables"

Default value: "datatables"

Supported values:

  • table: a plain Sphinx table.

  • datatables: the interactive table – sorting, search, pagination, column visibility, copy and CSV download, added in the browser by a small script that ships with Sphinx-Needs. See style for what it does and does not do.

Changed in version 9.0.0: datatables used to name the bundled DataTables package. It now names Sphinx-Needs’ own interactive table, which needs no third-party JavaScript; the configuration value and the NEEDS_DATATABLES CSS class are unchanged, so no project has to be edited.

needs_table_page_size

Added in version 9.0.0.

How many rows a page of an interactive table holds. Can be overridden for a single table with page_size.

# conf.py
needs_table_page_size = 25

Default value: 10

Must be a positive whole number. A need and its parts count as one row, so that a page never splits a need from its parts.

needs_table_page_sizes

Added in version 9.0.0.

The page sizes an interactive table offers the reader, in the order they are offered. 0 means “All”.

# conf.py
needs_table_page_sizes = [10, 25, 50, 0]

Default value: [10, 25, 50, 0]

Must be a non-empty list of whole numbers that are not negative. If needs_table_page_size (or a table’s own page_size) is not among them, it is added, so the control can always show the size in use.

needs_table_columns

Added in version 0.2.0.

Defines the default columns for each table. Can be overridden for specific tables by setting parameter columns of directive needtable.

# conf.py
needs_table_columns = "title;status;tags"

Default value: "id;title;status;type;outgoing;tags"

Supported values:

  • id

  • title

  • status

  • type

  • tags

  • incoming

  • outgoing

needs_id_regex

Added in version 0.2.0.

Defines a regular expression used to validate all manually set IDs and to generate valid IDs for needs without a given ID.

Default value: ^[A-Z0-9_]{5,}

By default, an ID is allowed to contain upper characters, numbers and underscore only. The ID length must be at least 3 characters.

The regular expression is matched against the need’s local id (the whole id while ids carry no namespace), as is a need type’s id_regex. It applies to the needs defined in this project’s sources. It is not applied to imported needs (needimport) or to external needs (needs_external_needs): their ids are the data of the project that wrote them, and an id_prefix may not match any pattern of this project.

A need type may add a pattern of its own, the id_regex of its needs_types entry: the id of a need of that type matches both, and the id_regex of every type it inherits from.

Warning

An automatically generated ID of needs without a manually given ID must match the default value of needs_id_regex only.

If you change the regular expression, you should also set needs_id_required so that authors are forced to set an valid ID.

needs_functions

Added in version 0.3.0.

Used to register own dynamic functions.

Must be a list of DynamicFunction.

Default value: []

Assigning a function to this option deactivates the incremental build feature of Sphinx (Incremental build support). How to register a function, by this option or, better, with add_dynamic_function() in setup(), is described in Registration; what a function can do, in Dynamic functions. A function that declares what it reads (Declaring what a function reads) is computed in order, like a built-in one; one that does not is computed after the built-in functions of its step.

needs_part_prefix

Added in version 0.3.6.

String used as prefix for need_part / np output in tables.

Default value: u'\u2192\u00a0'

The default value contains an arrow right and a non breaking space.

needs_part_prefix = u'\u2192\u00a0'

See show_parts for an example output.

needs_warnings

Added in version 0.5.0.

needs_warnings allows the definition of warnings which all needs must avoid during a Sphinx build.

A raised warning will print a sphinx-warning during build time.

Use -W in your Sphinx build command to stop the whole build, if a warning is raised. This will handle all warnings as exceptions.

def my_custom_warning_check(need, log):
    if need["status"] == "open":
        log.info(f"{need['id']} status must not be 'open'.")
        return True
    return False


needs_warnings = {
  # req need must not have an empty status field
  'req_with_no_status': "type == 'req' and not status",

  # status must be open or closed
  'invalid_status' : "status not in ['open', 'closed']",

  # user defined filter code function
  'type_match': my_custom_warning_check,
}

needs_warnings must be a dictionary. The dictionary key is used as identifier and gets printed in log outputs. The value must be a valid filter string or a custom defined filter code function and defines a not allowed behavior.

So use the filter string or filter code function to define how needs are not allowed to be configured/used. The defined filter code function must return True or False.

Warning

Assigning a function to a Sphinx option will deactivate the incremental build feature of Sphinx. Please use the Sphinx-Needs API and read Incremental build support for details.

Example output:

...
looking for now-outdated files... none found
pickling environment... done
checking consistency... WARNING: Sphinx-Needs warnings were raised. See console / log output for details.

Checking Sphinx-Needs warnings
  type_check: passed
  invalid_status: failed
      failed needs: 11 (STYLE_005, EX_ROW_1, EX_ROW_3, copy_2, clv_1, clv_2, clv_3, clv_4, clv_5, T_C3893, R_AD4A0)
      used filter: status not in ["open", "in progress", "closed", "done"] and status is not None

  type_match: failed
      failed needs: 1 (TC_001)
      used filter: <function my_custom_warning_check at 0x7faf3fbcd1f0>
done
...

Due to the nature of Sphinx logging, a sphinx-warning may be printed wherever in the log.

needs_warnings_always_warn

If set to True, will allow you to log needs_warnings not passed into a given file if using your Sphinx build command with -w.

Default: False.

For example, set this option to True:

needs_warnings_always_warn = True

Using Sphinx build command sphinx-build -M html {srcdir} {outdir} -w error.log, all the needs_warnings not passed will be logged into a error.log file as you specified.

If you use sphinx-build -M html {srcdir} {outdir} -W -w error.log, the first needs_warnings not passed will stop the build and be logged into the file error.log.

needs_layouts

Added in version 0.5.0.

You can use needs_layouts to define custom grid-based layouts with custom data.

Please read Layouts & Styles for a lot more detailed information.

The layouts added by extensions (with add_need_layout()) and the configured GitHub services’ github layout are not part of the option’s value, and a configured layout replaces one of its name added by either.

needs_layouts must be a dictionary and each key represents a layout. A layout must define the used grid-system and a layout-structure.

Example:

needs_layouts = {
    'my_layout': {
        'grid': 'simple',
        'layout': {
            'head': ['my custom head'],
            'meta': ['my first meta line',
                     'my second meta line']
        }
    }
}

Note

Sphinx-Needs provides some default layouts. These layouts cannot be overwritten. See layout list for more information.

needs_card_layouts

Added in version 8.4.0.

needs_card_layouts describes layouts declaratively, as a dictionary of card specifications, and is the recommended way to adjust how needs are rendered. Each specification is compiled into a needs_layouts entry of the same name, so a card can be used wherever a layout name is accepted.

Please read Card layouts for the full specification vocabulary.

Example:

needs_card_layouts = {
    'my_card': {
        'meta': {'include': ['status', 'tags']},
        'footer': ['id', 'type'],
        'collapse': 'closed',
    }
}

A specification that cannot be compiled, or whose name is already taken by a built-in layout or a needs_layouts entry, is reported as a needs.card_layout warning and skipped; the rest of the build is unaffected.

needs_default_layout

Added in version 0.5.0.

needs_default_layout defines the layout to use by default.

The name of the layout must have been provided by Sphinx-Needs or by user via configuration needs_layouts.

Default value of needs_default_layout is clean.

needs_default_layout = 'my_own_layout'

needs_default_style

Added in version 0.5.0.

The value of needs_default_style is used as default value for each need which does not define its own style information via :style: option.

See Styles for a list of default style names.

needs_default_layout = 'border_yellow'

A combination of multiple styles is possible:

needs_default_style = 'blue, green_border'

Custom values can be set as well, if your projects provides the needed CSS-files for it.

needs_template_folder

Added in version 0.5.2.

needs_template_folder allows the definition of your own Sphinx-Needs template folder. By default this is needs_templates/.

The folder must already exist, otherwise an exception gets thrown, if a need tries to use a template.

Read also need_template option description for information of how to use templates.

needs_duration_option

Added in version 0.5.5.

Used to define option to store duration information for needgantt.

See also duration_option, which overrides this value for specific needgantt charts.

Default: duration

needs_completion_option

Added in version 0.5.5.

Used to define option to store completion information for needgantt.

See also completion_option, which overrides this value for specific needgantt charts.

Default: completion

needs_services

Added in version 0.6.0.

Takes extra configuration options for Services:

needs_services = {
    'jira': {
        'url': 'my_jira_server.com',
    },
    'git': {
        'url': 'my_git_server.com',
    },
    'my_service': {
        'class': MyServiceClass,
        'class_init': {},
        'config_1': 'value_x',
    }
}

Each key-value-pair in needs_services describes a service specific configuration.

The built-in GitHub services (github-issues, github-prs and github-commits) are registered only when this option names them, with a mapping of their options ({} will do): each then adds its fields, its need type and the github layout, and a project that names none of them has none of these. A built-in named with a value that is not a mapping is reported as a needs.config warning, and that service is not registered. The built-in services are decided once, by sphinx-needs’ own config-inited handler at priority 12: one named later, by an extension’s handler above 12, is not registered, so name it in conf.py, the needs_from_toml file, or a config-inited handler at priority 11 or below. An incremental build after a built-in service is configured or removed re-reads every document.

needs_services = {"github-issues": {}}

Own services can be registered by setting class, together with class_init, as additional options.

The class is a Python type, so it can be set only here in conf.py, or registered by an extension through the API: in a needs_from_toml file a service’s table holds its options only. Note that the file’s services table replaces the whole needs_services of conf.py, as every key it sets does. A class that is not callable or has no options, or a class_init that is not a mapping, is reported as a needs.config warning and that service is not registered.

Config options are service specific and are described by Services.

See also needservice.

needs_service_all_data

Added in version 0.6.0.

If set to True, data for options which are unknown, is added as string to the need content. If False, unknown option data is not shown anywhere.

Default: False.

needs_service_all_data = True

needs_import_keys

Added in version 4.2.0.

For use with the needimport directive, mapping keys to file paths, see Global keys.

needs_import_parse_by_doctype

Added in version 9.0.0.

If True, needimport parses each imported need’s content in the markup its doctype names, rather than in the markup of the importing page; the directive’s parse_by_doctype option overrides it for one import. Default: False.

A doctype this project cannot parse is reported once per directive per doctype as a needs.import_doctype warning, and that content is parsed in the page’s markup, as before. To keep a -W build green while you register the suffix, add "needs.import_doctype" to suppress_warnings.

needs_import_parse_by_doctype = True

needs_external_needs

Added in version 0.7.0.

Allows to reference and use external needs without having their representation in your own documentation. (Unlike needimport, which creates need-objects from a local needs.json only).

needs_external_needs = [
  {
    'base_url': 'http://mydocs/my_project',
    'json_url':  'http://mydocs/my_project/needs.json',
    'version': '1.0',
    'id_prefix': 'ext_',
    'css_class': 'external_link',
  },
  {
    'base_url': 'http://mydocs/another_project/',
    'json_path':  'my_folder/needs.json',
    'version': '2.5',
    'id_prefix': 'other_',
    'css_class': 'project_x',
  },
  {
    'base_url': '<relative_path_from_my_build_html_to_my_project>/<relative_path_to_another_project_build_html>',
    'json_path':  'my_folder/needs.json',
    'version': '2.5',
    'id_prefix': 'ext_',
    'css_class': 'project_x',
  },
  {
    "base_url": "http://my_company.com/docs/v1/",
    "target_url": "issue/{{need['id']}}",
    "json_path": "needs_test.json",
    "id_prefix": "ext_need_id_",
  },
  {
    "base_url": "http://my_company.com/docs/v1/",
    "target_url": "issue/{{need['type']|upper()}}",
    "json_path": "needs_test.json",
    "id_prefix": "ext_need_type_",
  },
  {
    "base_url": "http://my_company.com/docs/v1/",
    "target_url": "issue/fixed_string",
    "json_path": "needs_test.json",
    "id_prefix": "ext_string_",
  },
]

Note

External needs support conditional links. Link strings in the JSON file can contain conditions, e.g. "links": ["REQ_001[status==\"open\"]"], and these conditions will be evaluated against the target needs during the build.

needs_external_needs must be a list of dictionary elements and each dictionary must/can have the following keys:

base_url:

Base url which is used to calculate the final, specific need url. Normally the path under which the index.html is provided. Base url supports also relative path, which starts from project build html folder (normally where index.html is located).

target_url:

Allows to config the final calculated need url. (optional)
If provided, target_url will be appended to base_url as the final calculate need url, e.g. base_url/target_url, unless it renders an absolute URL (scheme://… or //…, such as "{{need['remote_url']}}" rendering https://github.com/…), which is used as it is; base_url may then be "". A render with a scheme but no //, such as req:REQ_1, is appended as before. If no target_url is given, the external need url uses the default calculated base_url.
The target_url supports Jinja context {{need[]}}, need option used as key, e.g {{need['id']}} or {{need['type']}}.

json_url:

An url, which can be used to download the needs.json (or similar) file.

json_path:

The path to a needs.json file located inside your documentation project. Can not be used together with json_url.
The value must be a relative path, which is relative to the project configuration folder (where the conf.py is stored). (Since version 0.7.1)

version:

Defines the version to use inside the needs.json file (optional).

id_prefix:

Prefix as string, which will be added, as written, to all id of external needs. Needed, if there is the risk that needs from different projects may have the same id (optional).
The ids of the file are its namespace, and the prefix is that namespace’s name: a link field, or an id written in the content, that names a need of the file gets the prefix (a link given as a string that holds a dynamic function or a variant is left as written); a reference to an id the file does not contain is left as it is, and may resolve to a need of this project. This project references the external needs by their prefixed ids. The content is opaque markup, so every whole-word occurrence of a file id in it is rewritten, inside code blocks and file names too.

css_class:

A class name as string, which gets set in link representations like needtable. The related CSS class definition must be done by the user, e.g. by Own CSS file on sphinx level. (optional) (default: external_link)

allow_type_coercion:

Allows to enable or disable type coercion of fields for each need, and parsing of dynamic functions. For example if the tags need field is provided as a string like "tag1,tag2,[[func()]]", it will be parsed only if this option is set to True, otherwise will fail. (optional) (default: True)

Each source is read as a needimport reads its file: the key of a need in the file is its id (a differing id in the need is reported and ignored), and needs_id_regex is not applied. A source that cannot be obtained or read – a missing json_path, a failed download, a file that is not valid JSON, or one without the version asked for – is one needs.external_needs warning, and adds no need; the build goes on. When two sources define the same id, the first one listed keeps it and the other is warned about (needs.load_external_need). A need of this project with the id of an external need replaces the external need, with a needs.create_need warning naming where it came from.

needs_needextend_strict

Added in version 1.0.3.

needs_needextend_strict allows you to deactivate or activate the strict option behaviour for all needextend directives.

needs_table_classes

Added in version 0.7.2.

Allows to define custom CSS classes which get set for the HTML tables of need and needtable. This may be needed to avoid custom table handling of some specific Sphinx theme like ReadTheDocs.

needs_table_classes = ['my_custom_class', 'another_class']

These classes are not set for needtables using the table style, which is using the normal Sphinx table layout and therefore must be handled by themes.

needs_builder_filter

Added in version 0.7.2.

Defines a Filter string used to filter needs for the builder needs.

Default is 'is_external==False', so all locally defined need objects are taken into account. Need objects imported via needs_external_needs get sorted out.

needs_builder_filter = 'status=="open"'

needs_build_json

Added in version 0.7.6.

Builds a needs.json file during other builds, like html.

This allows to have one single Sphinx-Build for two output formats, which may save some time.

All other needs.json related configuration values, like needs_file, needs_build_json_per_id and needs_json_remove_defaults are taken into account.

Default: False

Example:

needs_build_json = True

Hint

The created needs.json file gets stored in the outdir of the current builder. So if html is used as builder, the final location is e.g. _build/html/needs.json.

See this section, for an explanation of the output format.

needs_reproducible_json

Added in version 2.0.0.

Setting needs_reproducible_json = True will ensure the needs.json output is reproducible, e.g. by removing timestamps from the output.

needs_json_exclude_fields

Added in version 3.0.0.

Setting needs_json_exclude_fields = ["key1", "key2"] will exclude the given fields from all needs in the needs.json output.

Default: ['lineno_content', 'collapse', 'hide', 'type_prefix', 'type_color', 'type_style', 'is_need', 'is_part', 'id_parent', 'id_complete']

needs_json_remove_defaults

Added in version 2.1.0.

Setting needs_json_remove_defaults = True will remove all need fields with default from needs.json, greatly reducing its size.

The defaults can be retrieved from the needs_schema now also output in the JSON file (see this section for the format). A value is left out exactly where it equals the default its field’s entry in that needs_schema carries, as a JSON value of the same type (1.0 is not 1, [1.0] not [1]): never a need type’s default, which the needs_schema does not carry (Fields per need type). A need holding its type’s default, its own type’s or one it inherits, writes it wherever it differs from that default. So a reader that restores a left-out value from the file’s needs_schema, as needimport does, gets the same needs from the file as from the same file written in full.

Default: False

needs_build_json_per_id

Added in version 2.0.0.

Builds list json files for each need. The name of each file is the id of need. This option works like needs_build_json.

Default: False

Example:

needs_build_json_per_id = False

Hint

The created single json file per need, located in needs_build_json_per_id_path folder, e.g _build/needs_id/abc_432.json

needs_build_json_per_id_path

Added in version 2.0.0.

This option sets the location of the set of needs.json for every needs-id.

Default value: needs_id

Example:

needs_build_json_per_id_path = "needs_id"

Hint

The created needs_id folder gets stored in the outdir of the current builder. The final location is e.g. _build/needs_id

needs_build_needumls

Exports needuml data during each build.

This option works like needs_build_json. But the value of needs_build_needumls should be a string, not a boolean. Default value of is: "".

This value of this option shall be a relative folder path, which specifies and creates the relative folder in the outdir of the current builder.

Example:

needs_build_needumls = "my_needumls"

As a result, all the needuml data will be exported into folder in the outdir of the current builder, e.g. _build/html/my_needumls/.

needs_constraints

Added in version 1.0.1.

needs_constraints = {

    "critical": {
        "check_0": "'critical' in tags",
        "check_1": "'security_req' in links",
        "severity": "CRITICAL"
    },

    "security": {
        "check_0": "'security' in tags",
        "severity": "HIGH"
    },

    "team": {
        "check_0": "author == \"Bob\"",
        "severity": "LOW"
    },

}

needs_constraints needs to be enabled by adding “constraints” to needs_fields

needs_constraints contains a dictionary which contains dictionaries describing a single constraint. A single constraint’s name serves as the key for the inner dictionary. Inside there are (multiple) checks and a severity. Each check describes an executable constraint which allows to set conditions the specific need has to fulfill. Depending on the severity, different behaviours in case of failure can be configured. See needs_constraint_failed_options

Each need now contains additional attributes named “constraints_passed” and “constraints_results”.

constraints_passed is a bool showing if ALL constraints of a corresponding need were passed.

constraints_results is a dictionary similar in structure to needs_constraints above. Instead of executable python statements, inner values contain a bool describing if check_0, check_1 … passed successfully.

Added in version 2.0.0: The "error_message" key can contain a string, with Jinja templating, which will be displayed if the constraint fails, and saved on the need as constraints_error:

needs_constraints = {

    "critical": {
        "check_0": "'critical' in tags",
        "severity": "CRITICAL",
        "error_message": "need {{id}} does not fulfill CRITICAL constraint, because tags are {{tags}}"
    }

}
.. req::
    :id: SECURITY_REQ

    This is a requirement describing security processes.

.. req::
    :tags: critical
    :links: SECURITY_REQ
    :constraints: critical

    Example of a successful constraint.

.. req::
    :id: FAIL_01
    :author: "Alice"
    :constraints: team

    Example of a failed constraint with medium severity. Note the style from :ref:`needs_constraint_failed_options`
Requirement: SECURITY_REQ
links incoming: R_6F47F

This is a requirement describing security processes.

Requirement: R_6F47F
tags: critical
links outgoing: SECURITY_REQ

Example of a successful constraint.

Requirement: FAIL_01
style: yellow_bar,
author: "Alice"

Example of a failed constraint with medium severity. Note the style from needs_constraint_failed_options

needs_constraint_failed_options

needs_constraint_failed_options = {
    "CRITICAL": {
        "on_fail": ["warn"],
        "style": ["red_bar"],
        "force_style": True
    },

    "HIGH": {
        "on_fail": ["warn"],
        "style": ["orange_bar"],
        "force_style": True
    },

    "MEDIUM": {
        "on_fail": ["warn"],
        "style": ["yellow_bar"],
        "force_style": False
    },

    "LOW": {
        "on_fail": [],
        "style": ["yellow_bar"],
        "force_style": False
    }
}

needs_constraint_failed_options must be a dictionary which stores what to do if a certain constraint fails. Dictionary keys correspond to the severity set when creating a constraint. Each entry describes in an “on_fail” action what to do:

  • “break” breaks the build process and raises a NeedsConstraintFailed Exception when a constraint is not met.

  • “warn” creates a warning in the sphinx.logger if a constraint is not met. Use -W in your Sphinx build command to stop the whole build, if a warning is raised. This will handle all warnings as exceptions.

“style” sets the style of the failed object see Styles for available styles. Please be aware of conflicting styles!

If “force style” is set, all other styles are removed and just the constraint_failed style remains.

needs_variants

Added in version 1.0.2.

needs_variants configuration option must be a dictionary which has pre-defined variants assigned to “filter strings”. The filter string defines which variant a need belongs in the current situations.

For example, in conf.py:

needs_variants = {
  "var_a": "'var_a' in build_tags"  # filter_string
  "var_b": "assignee == 'me'"
}

The dictionary consists of key-value pairs where the key is a string used as a reference to the value. The value is a string which consists of a Python-supported “filter string”.

Default: {}

needs_render_context

Added in version 1.0.3.

This option allows you to use custom data as context when rendering Jinja templates or strings.

Configuration example:

def custom_defined_func():
    return "my_tag"

needs_render_context = {
    "custom_data_1": "Project_X",
    "custom_data_2": custom_defined_func(),
    "custom_data_3": True,
    "custom_data_4": [("Daniel", 811982), ("Marco", 234232)],
}

The``needs_render_context`` configuration option must be a dictionary. The dictionary consists of key-value pairs where the key is a string used as reference to the value. The value can be any data type (string, integer, list, dict, etc.)

Warning

The value can also be a custom defined function, however, this will deactivate the caching and incremental build feature of Sphinx.

Note

needreport reserves the five names types, links, options, usage and report_directive in its own templates, and needs_render_context is merged over them. report_directive is meant to be set this way; the other four are reported as a needs.needreport warning. See Template context.

The data passed via needs_render_context will be available as variable(s) when rendering Jinja templates or strings. You can use the data passed via needs_render_context as shown below:

Example 7

.. req:: Need with jinja_content enabled
   :id: JINJA1D8913
   :jinja_content: true

   Need with alias {{ custom_data_1 }} and ``jinja_content`` option set to {{ custom_data_3 }}.

   {{ custom_data_2 }}
   {% for author in custom_data_4 %}

   * {{ author[0] }}

     + {{ author[1] }}

   {% endfor %}
Requirement: Need with jinja_content enabled JINJA1D8913

Need with alias Project_X and jinja_content option set to True.

List of contributors:

  • Daniel

    • 811982

  • Marco

    • 234232

needs_debug_measurement

Added in version 1.3.0.

Activates Runtime debugging, which measures the execution time of different functions and creates a helpful JSON and HTML report.

See Runtime debugging for details.

To activate it, set it to True:

needs_debug_measurement = True

needs_debug_filters

Added in version 4.0.0.

Changed in version 9.1.0: Each record says which tier answered the filter (tier), and for eval why (fallback_reason).

If set to True, all calls to filter processing will be logged to a debug_filters.jsonl file in the build output directory, appending a single-line JSON for each filter call. The calls logged are those of the directives taking the filter options (needlist, needtable, needflow, …); a need_count, a needextend or a filter in the configuration writes no record. A record holds:

  • origin, source and line: the directive and where it is written;

  • filter: the directive’s filter, its :status:, :tags: and :types: joined to its :filter: with and;

  • needs_count and runtime: how many needs it selected, and in how many seconds;

  • tier: which of the three tiers answered the :filter:: "index" (from the indexes, a directive with no :filter: included), "fast" (the portable filter language) or "eval" (Python’s eval), or "refused" for a filter that is a constant (see Filter string), which no tier answers and which selects nothing;

  • fallback_reason, for "eval" only: the construct that kept the string out of the portable language, a short name that stays the same across releases – subscript, comprehension, arithmetic, literal (a literal where the language has none, 1 == 1), call:<function> (a call of a function the language lacks, or of one of its own in a shape it lacks: call:any, call:len; a method of a var. value or of c is named by its chain, call:var.build.strip, call:c.in_namespace), call (a call of anything else, x()()), method:<name> (method:strip), attribute:<root> (a dotted name not under var.), name:<name> (needs, current_need, c, var, search or a __dunder__ name as a value), not (a not as an operand, (not x) == y), compare:<shape> (compare:name-in-name, compare:list, compare:ordering, compare:is, compare:chained, compare:in), the kind of any other expression (ifexp, fstring, lambda, tuple, …), and filter-code and filter-func for a directive’s filter code and Filter function. syntax names a string that is no Python expression, but no record carries it today: such a filter stops the build before its record is written.

needs_schema_validation_enabled

Added in version 6.1.1.

Enable schema validation for needs, True by default.

See Schema validation for detailed documentation.

needs_schema_definitions

Added in version 6.0.0.

Defines validation schemas for needs using a definition format derived from JSON Schema. Schemas can be used to validate need fields, enforce constraints, and ensure data consistency.

Default value: {}

needs_schema_definitions = {
    "$defs": {
        "type-spec": {
            "properties": {"type": {"const": "spec"}}
        },
        "safe-need": {
            "properties": {"asil": {"enum": ["A", "B", "C", "D"]}},
            "required": ["asil"]
        }
    },
    "schemas": [
        {
            "id": "unique-id-validation",
            "severity": "warning",
            "message": "ID must be uppercase",
            "validate": {
                "local": {
                    "properties": {
                        "id": {"pattern": "^[A-Z0-9_]+$"}
                    }
                }
            }
        },
        {
            "id": "safe-spec",
            "validate": {
                "local": {
                    "allOf": [
                        {"$ref": "#/$defs/type-spec"},
                        {"$ref": "#/$defs/safe-need"}
                    ]
                }
            }
        }
    ]
}

See Schema validation for detailed documentation.

needs_schema_definitions_from_json

Added in version 6.0.0.

Path to a JSON file containing schema definitions. This is the recommended approach for defining schemas as it provides better IDE support and maintainability.

Default value: None

needs_schema_definitions_from_json = "schemas.json"

The JSON file should contain the same structure as needs_schema_definitions:

needs_schema_debug_active

Added in version 6.0.0.

Activates debug mode for schema validation. When enabled, the validation dumps JSON files, schema files, and validation messages to help troubleshoot schema validation issues.

Default value: False

needs_schema_debug_active = True

Debug files are written to the directory specified by needs_schema_debug_path.

needs_schema_debug_path

Added in version 6.0.0.

Directory path where schema debug files are stored when needs_schema_debug_active is enabled.

If the path is relative, it will be resolved relative to the conf.py directory.

Default value: "schema_debug"

needs_schema_debug_path = "debug/schemas"

needs_schema_debug_ignore

Added in version 6.0.0.

List of validation scenarios to ignore when dumping debug information. This helps reduce noise in debug output by filtering out irrelevant validations.

Default value:

[
   "field_success",
   "link_success",
   "select_success",
   "select_fail",
   "local_success",
   "network_local_success"
]
needs_schema_debug_ignore = [
    "field_success",
    "local_success",
    "network_local_success"
]

To write all scenarios, set it to an empty list: [].

Available scenarios that can be ignored:

  • cfg_schema_error: The user provided schema is invalid

  • field_success: Global field validation was successful

  • field_fail: Global field validation failed

  • link_success: Global extra link validations was successful

  • link_fail: Global extra link validation failed

  • select_success: Successful select validation

  • select_fail: Failed select validation

  • local_success: Successful local validation

  • local_fail: Need local validation failed

  • network_missing_target: An outgoing link target cannot be resolved

  • network_contains_too_few: minContains or minItems validation failed for the given link_schema link type

  • network_contains_too_many: maxContains or maxItems validation failed for the given link_schema link type

  • network_items_fail: items validation failed for the given link_schema link type

  • network_local_success: Successful network local validation

  • network_local_fail: Need does not validate against the local schema in a network context

  • network_max_nest_level: The maximum nesting level of network links was exceeded

The debug information is written to the directory specified by needs_schema_debug_path. The _success scenarios exist to analyze why a validation was successful and how the final need and schema looks like.

Note

For large need counts, the debug output can become very large. Writing debug output also affects the validation performance negatively.

Deprecated Options

needs_filter_data

Deprecated since version 8.2.0: Use needs_variant_data and needs_variant_data_file instead. These provide a dedicated var namespace that avoids collisions with need field names and supports nested structured data.

This option allows to use custom data inside a Filter string.

Configuration example:

def custom_defined_func():
    return "my_tag"

needs_filter_data = {
    "current_variant": "project_x",
    "sphinx_tag": custom_defined_func(),
}

The defined needs_filter_data must be a dictionary. Its values can be a string variable or a custom defined function. The function gets executed during config loading and must return a string.

The value of needs_filter_data will be available as data inside Filter string and can be very powerful together with internal needs information to filter needs.

needs_extra_options

Deprecated since version 7.0.0: Use needs_fields instead.

The option allows the addition of extra options that you can specify on needs.

You can set needs_extra_options as a list inside conf.py as follows:

needs_extra_options = ['introduced', 'updated', 'impacts']

And use it like:

.. req:: My Requirement
   :status: open
   :introduced: Yes
   :updated: 2018/03/26
   :tags: important;complex;
   :impacts: really everything

Note

To filter on these options in needlist, needtable, etc. you must use the Filtering needs option.

Show example

conf.py

needs_extra_options = ["my_extra_option",  "another_option"]

index.rst

.. req:: My requirement with custom options
   :id: xyz_123
   :status: open
   :my_extra_option: A new option
   :another_option: filter_me

   Some content

.. needlist::
   :filter: "filter_me" in another_option

Result

Requirement: My requirement with custom options xyz_123
status: open
my_extra_option: A new option
another_option: filter_me

Some content

Added in version 4.1.0: Values in the list can also be dictionaries, with keys:

  • name: The name of the option (required).

  • description: A description of the option (optional).

    This will be output in the schema of the needs.json, and can be used by other tools.

For example:

needs_extra_options = [
    "my_extra_option",
    {"name": "my_other_option", "description": "This is a description of the option"}
]

Added in version 6.0.0: The needs_extra_options can now contain schema information for each option:

needs_extra_options = [
    {
        "name": "efforts",
        "description": "Efforts in days",
        "schema": {
            "type": "integer",
            "minimum": 0,
        },
    }
]

The same fields for the Supported data types and constraints as in the Schema validation are accepted. If schema is given, type is required. All the other keys can also be defined via needs_schema_definitions or in the file passed via needs_schema_definitions_from_json. If specified via needs_fields, the constraints are applied to all usages of the option.

Added in version 9.0.0: A dictionary entry can carry a derive rule, or derive_by_type rules, which make the option a derived field, as on a needs_fields entry.

A dictionary entry is read for name, description, schema, derive and derive_by_type alone. Any other key, such as nullable or default, which only a needs_fields entry reads, is reported and ignored as in a needs_fields entry, one needs.config warning per key (needs_extra_options['efforts'] has an unknown key 'nullable'; ...), and so is a keyword its schema does not have.

needs_global_options

Deprecated since version 7.0.0: Use needs_fields and needs_links instead. A field’s or link type’s default or predicates set in more than one place is taken from a need type’s own declaration (Fields per need type) first, then from the field’s needs_fields entry or the link type’s needs_links (or needs_extra_links) entry, then from needs_global_options, whose value for a key that entry sets too is ignored with a needs.config warning.

Changed in version 5.1.0: The format of the global options was change to be more explicit.

Unknown keys are also no longer accepted, these should also be set in the needs_fields list.

Comparison to old format
Old format
needs_global_options = {
    "field1": "a",
    "field2": ("a", 'status == "done"'),
    "field3": ("a", 'status == "done"', "b"),
    "field4": [
        ("a", 'status == "done"'),
        ("b", 'status == "ongoing"'),
        ("c", 'status == "other"', "d"),
    ],
}
New format
needs_global_options = {
    "field1": {"default": "a"},
    "field2": {"predicates": [('status == "done"', "a")]},
    "field3": {
        "predicates": [('status == "done"', "a")],
        "default": "b",
    },
    "field4": {
        "predicates": [
            ('status == "done"', "a"),
            ('status == "ongoing"', "b"),
            ('status == "other"', "c"),
        ],
        "default": "d",
    },
}

This configuration allows for global defaults to be set for all needs, for any of the following fields:

Defaults will be used if the field is not set specifically by the user and thus has a “empty” value.

needs_fields = {"option1": {}}
needs_global_options = {
   "tags": {"default": ["tag1", "tag2"]},
   "option1": {"default": "new value"},
}

To set a default based on a one or more predicates, use the predicates key. These predicates are a list of (match expression, value), evaluated in order, with the first match set as the default value.

A match expression is a string, using Python syntax, that will be evaluated against data from each need (before the resolution of defaults or dynamic functions etc):

  • id (str)

  • type (str)

  • title (str)

  • tags (tuple[str, ...])

  • status (str | None)

  • docname (str | None)

  • is_external (bool)

  • is_import (bool)

  • needs_fields

  • needs_links (tuple[str, ...])

  • needs_variant_data (via the var namespace)

If no predicates match, the default value is used (if present).

needs_fields = {"option1": {}}
needs_global_options = {
   "option1": {
   # if field is unset:
      "predicates": [
         # if status is "done", set to "value1"
         ("status == 'done'", "value1"),
         # else if status is "ongoing", set to "value2"
         ("status == 'ongoing'", "value2"),
      ]
      # else, set to "value3"
      "default": "value3",
   }
}

Tip

You can combine global options with Dynamic functions to automate data handling.

needs_fields = {"option1": {}}
needs_global_options = {
        "option1": {"default": '[[copy("id")]]'}
}

needs_statuses

Deprecated since version 7.0.0: Use needs_fields instead.

Defines a set of valid statuses, which are allowed to be used inside documentation. If we detect a status not defined, an error is thrown and the build stops. The checks are case sensitive.

Activate it by setting it like this:

needs_statuses = [
    dict(name="open", description="Nothing done yet"),
    dict(name="in progress", description="Someone is working on it"),
    dict(name="implemented", description="Work is done and implemented"),
]

If parameter is not set or set to False, no checks will be performed.

Default value: [].

needs_tags

Deprecated since version 7.0.0: Use needs_fields instead.

Defines a set of valid tags, which are allowed to be used inside documentation. If we detect a tag not defined, an error is thrown and the build stops. The checks are case sensitive.

Activate it by setting it like this:

needs_tags = [
    dict(name="new", description="new needs"),
    dict(name="security", description="tag for security needs"),
]

If parameter is not set or set to [], no checks will be performed.

Default value: [].

needs_variant_options

Deprecated since version 7.0.0: Use needs_fields instead.

Added in version 1.0.2.

needs_variant_options must be a list which consists of the options to apply variants handling. You can specify the names of the options you want to check for variants.

for example, in conf.py:

needs_variant_options = ["author", "status"]

From the example above, we apply variants handling to only the options specified.

Default: []

Note

You must ensure the options needs_variant_options are one of: