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.betaBeta feature, subject to changeneeds.card_layoutInvalidneeds_card_layoutsspecificationneeds.chooseError in processing choose/when/otherwise directiveneeds.configInvalid configurationneeds.constraintConstraint violationneeds.create_needCreation of a need from directive failedneeds.delete_needDeletion of a need failedneeds.deprecatedDeprecated featureneeds.derive_authoredA derived field is set in a need or by a needextend; the value is ignoredneeds.derive_cycleA dynamic function or variant is on a cycle of computed values; the field is not computedneeds.derive_denseA 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 projectneeds.derive_invalidA derive rule of needs_fields or needs_links cannot be read, or a default is given beside itneeds.derive_scopeA dynamic function, variant or needextend filter reads a value that cannot be computed before itneeds.derive_uniqueA derived copy with select = “unique” finds several needs that set the field; the lowest id is copiedneeds.diagram_scaleFailed to process diagram scale optionneeds.directiveError in processing a need directiveneeds.duplicate_idDuplicate need ID found when merging needs from parallel processesneeds.duplicate_part_idDuplicate part ID found when parsing need contentneeds.dynamic_functionFailed to load/execute dynamic functionneeds.external_link_outgoingUnknown outgoing link in external needneeds.external_link_target_typeA link of an external need points to a need of a type its link type’s target_types does not acceptneeds.external_needsAn external needs source cannot be read, or what it holds is reportedneeds.filter_funcError loading needs filter functionneeds.filterError processing needs filterneeds.filter_typeA filter’s c.is_a names no need type, so it selects no needneeds.githubError in processing GitHub service directiveneeds.ifError in processing if directiveneeds.import_doctypeImported need content declares a doctype the project cannot parse; parsed as the page’s markupneeds.import_needFailed to import a needneeds.json_loadneeds.layoutError occurred during layout rendering of a needneeds.link_condition_failedLink condition not satisfied by targeted needneeds.link_condition_invalidLink condition has invalid filter syntaxneeds.link_outgoingUnknown outgoing link in standard needneeds.link_refNeed could not be referencedneeds.link_target_typeA link points to a need of a type its link type’s target_types does not acceptneeds.link_textReference text could not be generatedneeds.load_external_needFailed to load an external needneeds.load_service_needFailed to load a service needneeds.max_itemsView truncated by a max_items limitneeds.mistyped_external_valuesUnexpected value types found in external need dataneeds.mistyped_import_valuesUnexpected value types found in imported need dataneeds.mplMatplotlib required but not installedneeds.needextendError processing needextend directiveneeds.needextractError processing needextract directiveneeds.needflowError processing needflow directiveneeds.needganttError processing needgantt directiveneeds.needimportError processing needimport directiveneeds.needreportError processing needreport directiveneeds.needsequenceError processing needsequence directiveneeds.needumlError processing needuml/needarch directiveneeds.partError processing need partneeds.string_linkInvalidneeds_string_linksconfigurationneeds.titleError creating need titleneeds.type_conflictA need type’s declaration of a field or link type cannot be applied to it; the declaration is ignoredneeds.type_inheritsA need type’s inherits names no need type, or is on a cycle; it is ignored and the type has no parentneeds.type_near_nameA 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 sameneeds.type_wideningA need type’s declaration of a field or link type widens the declaration it inherits; the declaration is ignoredneeds.umlError in processing of UML diagramneeds.undeclared_for_typeA field or link type is set on a need of a need type that does not declare it; the value is ignoredneeds.unknown_external_keysUnknown keys found in external need dataneeds.unknown_import_keysUnknown keys found in imported need dataneeds.variantError processing variant in need fieldneeds.variant_data_locationVariant data set in both[variants]and[needs]; the[needs]keys are ignoredneeds.variants_unknown_keyUnknown key in the[variants]tableneeds.warningsNeed 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 documentstitle: 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
directivethat is missing or not a non-empty string; in the dictionary, an empty key. Adirectiveinside a dictionary entry that differs from its key is reported, and the key is used;an entry whose
titleorprefixis 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
colororstylethat is not a string, aninheritsthat is not a non-empty string, and afieldsorlinksthat is not a dictionary, are ignored, and the type kept;a key other than
directive,title,prefix,color,style,inherits,fieldsandlinksis 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 asstatus, 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, orlinks, 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 typelto how many links oflpoint 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’sc.is_afollows 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 of the field |
|
schema of the field: only the keywords it changes, the others are kept |
|
|
|
default value |
|
|
|
rule computing the field on the type’s needs and on those of the types inheriting from it (below;
|
|
severity a need failing the declaration – its |
and a declaration in links these, as needs_links takes them:
key |
the type’s |
|---|---|
|
description of the link type |
|
schema of the link list ( |
|
default links |
|
|
|
rule computing the links of the type’s needs and of those of the types inheriting from it (below;
|
|
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 a need whose links fail the |
|
the labels of the links, on every need type: set by the root declaration of a link type declared on need types alone (below) |
|
whether the links are copied into |
|
whether a link to no need is allowed: likewise |
|
whether the link type is a summary (Summary link types): likewise |
|
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
typeis 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 adefaultor inpredicates, 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 toTrue, the field can be set toNone(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 aseveritybelowviolation, 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 toTrue, the field will support variant options and variant data references.Default:
False.
parse_dynamic_functions: If set toTrue, 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
kindand the kind’s roles; withderive_by_typebeside it, for every need of a typederive_by_typedoes not list. A derived field cannot be set in a need or by aneedextend, and takes nodefaultorpredicates. 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
derivefor a need type the project does not declare, such as a GitHub service’s, and an older one of aderivein a need type’s own entry (Rules per need type): a table of need type (the directive name, astypeholds it) to a rule, asderivetakes one, overridingderiveon that type. A need of a type without a rule holds thedefault(a literal, given only withoutderive), elseNone, 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_links (
tuple[str, ...])needs_variant_data (via the
varnamespace)
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_links¶
Added in version 7.0.0.
Allows the definition of additional link types as a dictionary mapping link name to configuration. A link type’s name is matched by a directive option ignoring case, as a field’s is, and two names equal ignoring case are a configuration error (option names and case).
Each configured link can define:
description(optional): A description of the link type.schema(optional): A schema definition for the links.This uses the same format as needs_schema_definitions and needs_schema_definitions_from_json, for a list of need IDs, with keywords such as the number of links (
minItems,maxItems), the IDs (items, withpattern,minLengthormaxLength), andcontainswithminContainsormaxContains(minContainsis 1 unless given, so giveminContains = 0beside amaxContainsthat allows no match). The links are validated against it by the schema validation, see Schema validation for more details. By default the link schema will be{"type": "array", "items": {"type": "string"}}.
predicates(optional): A list of(match expression, value)tuples.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(optional): A default value for the field.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 toTrue, the field will support variant options and variant data references.Default:
False.
parse_dynamic_functions: If set toTrue, the field will support Dynamic functions.Default: the value of needs_parse_dynamic_functions (
True).
parse_conditions: If set toFalse, the[condition]bracket syntax will not be parsed for this link type.Default:
True. New in version 8.0.0.
derive(optional): A rule computing the links of every need, which makes the link type derived:a table naming the kind
links,content_linksorunion(A union of link types), orcopyorcollect, a path through other links (A chain as links: copy and collect on a link type), and its roles; withderive_by_typebeside it, of every need of a typederive_by_typedoes not list. A derived link type cannot be set in a need or by aneedextend, and takes nodefaultorpredicates. New in version 9.0.0.
derive_by_type(optional): Rules per need type, which make the link type derived too,the spelling of a
derivefor a need type the project does not declare, such as a GitHub service’s, and an older one of aderivein a need type’s own entry (Rules per need type): a table of need type (the directive name) to a rule, asderivetakes one, overridingderiveon that type. A need of a type without a rule holds thedefault(a literal, given only withoutderive), else no links. See Rules per need type. New in version 9.0.0.
incoming(optional): Incoming text, to use for incoming links. E.g. “is blocked by”. Default: “<name> incoming”.outgoing(optional): Outgoing text, to use for outgoing links. E.g. “blocks”. Default: “<name>”.copy(optional): True/False. If True, the links will be copied also to the common link-list (link typelinks). Default: False. Nothing is copied into a derivedlinks, nor from a derived link type (copyis not available on one in this release), and thecopyis reported.Deprecated since version 9.1.0:
copy = trueis removed in 10.0. Until then the links are still copied, and each declaration writing it is oneneeds.deprecatedwarning:needs_links['blocks'] sets 'copy = true', which is deprecated and will be removed in sphinx-needs 10.0; declare a link type deriving the union instead, e.g. derive = {kind = "union", fields = ["links", "blocks"]}, and read it where the copies in links were read
Declare a link type deriving the union of
linksand the copying link types instead, and read it wherelinkswas read for the copies (a needflow’s:link_types:, a filter, a needtable column). Before:[needs.links.blocks] copy = true
After:
[needs.links.blocks] [needs.links.all_links] derive = { kind = "union", fields = ["links", "blocks"] }
linksthen holds only the links written in it, andall_linkswhatlinksheld with the copies, with four differences: a link a needextend adds toblocksis inall_links, where it was not copied; a need from needimport or needs_external_needs keeps theall_linksof its needs.json, where itsblockswere copied; a dead link ofblocksis reported once, underblocksand as it allows dead links, where the copy reported it underlinkstoo; and ablocksfilled by one of your own functions, or by a call whose filter cannot be read (alinks_from_filterwhose filter namesneeds), is read by a union computed after it, among your own functions in need-id order, so a built-in function or rule readingall_linksin the link fields’ step cannot wait for it, and is reported (needs.derive_scope). The readers that take onlylinks(A union of link types) read no union in this release: a project that relies on them keepscopyuntil 10.0, and the warning with it (suppress_warnings = ["needs.deprecated"]silences it, and every other deprecation).allow_dead_links(optional): True/False. If True, dead links are allowed and do not throw a warning. See allow_dead_links for details. Default: False.summary(optional): True/False. Default: False. Set it for a link type whose links are shortcuts across the trace rather than steps in it, such as a test result linked straight to the requirements it covers, three links up (Summary link types explains when to use it). Such a link type works as any other wherever it is named: a filter ("REQ_1" in covers), a needtable column, a rule’soverorfield, a needflow’s:link_types:, a schema rule; and a need holds its links and back links (<name>_back) and shows them, as usual. The views that take every link type leave it out: a needflow without:link_types:neither draws it nor walks it from:root_id:. The schema of the needs.json marks it, and its back links,"summary": true, so that a tool reading the file can leave it out too. A union cannot name it as a member (needs.derive_invalid). A link type acopyorcollectrule computes is a summary whether or not it says so (A chain as links: copy and collect on a link type), andsummary = falsebeside such a rule is refused (needs.derive_invalid).copy = truebesidesummary = truewould copy every summary link intolinks, which every view reads: it is aneeds.configwarning, and nothing is copied. With every link type a summary, a needflow without:link_types:draws none, itsneeds_flow_link_typesfallback included. It is a link type’s on every need type: on a link type declared here, a need type’s entry (Fields per need type) does not give it, and one that does is aneeds.configwarning, the key ignored; a link type declared on need types alone takes it from the first need type’s entry declaring it, which the others may repeat (Fields per need type); a rule (derive,derive_by_type) does not give it, where it is no role (needs.derive_invalid). A value that is not a boolean is aneeds.configwarning, and ignored. New in version 9.2.0.target_types(optional): The need types the links may point to, a list of directive names, such as["req"]. A link to a need of a listed type, or of a type inheriting from one (inherits, transitively), is accepted; each other link is reported, and kept, oneneeds.link_target_typewarning at the need it is set in:index.rst:12: WARNING: Need 'T_002' link 'S_001' in field 'verifies': target need type 'spec' is not one of 'req' (or a type inheriting from it) [needs.link_target_type]
naming the need type whose needs_types entry gives the target types, where one does (
..., as need type 'test' declares it). It restricts the outgoing links alone, and only their target’s type. It followsinherits, unlike a filter (type == 'req') and a schema rule’sconst, which compare the type name literally. Since a subtype is accepted,inheritsreads as “is a”: a type that inherits another only to reuse its fields is accepted wherever its parent is. “Areq, but not asafety_req”, or anything about the target’s other fields, takes a schema rule. It is checked once every link is final (after the needextend directives, defaults, predicates and dynamic functions), whether or not the schema validation runs. A dead link is not checked,allow_dead_linksor not: it is left to the dead-link warning (whichallow_dead_linkssilences), and a link to a part its target lacks is a dead link. A link to a need part is checked by the type of the need owning the part, and a link to a need from needimport or needs_external_needs by that need’s type. The links of an imported need are reported at itsneedimport, and those of a need from needs_external_needs asneeds.external_link_target_type, with its URL and no place in a document. While another link type copies intolinks(copy),linksholds links written in it and links copied into it, so its owntarget_typeswould not say one thing: for nowtarget_typesonlinksis refused beside such a link type, oneneeds.configwarning per declaration (theneeds_linksentry, a need type’s entry), and ignored untilcopyis replaced:needs_links['links'] has a 'target_types', but 'verifies' copies into links (copy = true); the key is ignored until copy is replaced
The copying link type’s own
target_typesstill holds.copyonlinksitself, or on a derived link type, copies nothing, and refuses nothing.target_typesand the link type’sschemacount (minItems,maxItems) are checked apart. The count is every link the need holds, a linktarget_typesrefuses and a dead link included, so atestwhose only link is aspecsatisfiesminItems = 1. It is checked by the schema validation, and switched off with it (needs_schema_validation_enabled= False), and reported assn_schema_violation.link_fail, with no place in a document; so one refused link over amaxItemsis reported twice, once by each. “At least onereq” among links that may point to several types takes a schema rule’scontainswithminContains(Link count constraints). A link written twice is one link, and reported once. A value that is not a non-empty list of names is oneneeds.configwarning, and ignored. The names that are no need type (a title, a typo) are oneneeds.configwarning per declaration, naming them, and are ignored. Atarget_typesnaming no need type at all is ignored: the links keep the target types of the declaration before it, and are unrestricted where none gives any. A derived link type takes none in this release: besidederiveorderive_by_typeit is reported (needs.derive_invalid) and ignored. A need type may narrow it for its needs, see Fields per need type. New in version 9.1.0.style(optional): A plantuml style description, e.g. “#FFCC00”. Used for needflow. See style / style_part.style_part(optional): Same asstyle, but get used if link is connected to a need_part / np. See style / style_part.style_start(optional): See style_start / style_end.style_end(optional): See style_start / style_end.
Any other key in an entry, such as a misspelt target_types, and a keyword the schema of a link type
(or its items or contains) does not have, such as uniqueItems, is reported and ignored as in a
needs_fields entry, one needs.config warning per key
(an option, left from a needs_extra_links entry, is accepted where it repeats the entry’s name, and reported where it gives another):
needs_links['verifies'] has an unknown key 'target_type'; known keys are allow_dead_links, color, copy, default, derive, derive_by_type, description, incoming, outgoing, parse_conditions, parse_dynamic_functions, parse_variants, predicates, schema, style, style_end, style_part, style_start, target_types; the key is ignored
needs_links['verifies'].schema has an unknown keyword 'uniqueItems'; known keywords of a link type's schema are contains, items, maxContains, maxItems, minContains, minItems, type; the keyword is ignored
A need type may declare a link type anew for its needs, narrowing it: see Fields per need type.
A link type the need types that have it declare alone, with its labels, copy and dead links, needs no entry here (Fields per need type).
Configuration example:
needs_links = {
"checks": {},
"triggers": {
"description": "Links to needs that are triggered by this need",
"predicates": [
('"urgent" in tags', ["ID999", "ID998"]),
],
"default": ["ID123"],
"incoming": "is triggered by",
"outgoing": "triggers",
"copy": False,
"allow_dead_links": True,
"style": "#00AA00",
"style_part": "#00AA00",
"style_start": "-",
"style_end": "--o",
},
}
The above example configuration allows the following usage:
Example 1
.. req:: My requirement
:id: EXTRA_REQ_001
.. test:: Test of requirements
:id: EXTRA_TEST_001
:checks: EXTRA_REQ_001, DEAD_LINK_NOT_ALLOWED
:triggers: DEAD_LINK
Link types with name links and parent_needs are added by default. You are free to overwrite the default config by defining your own type with name links or parent_needs. This type will be used as default configuration for all links.
The back links of a link type are named <name>_back on every need.
A link type whose back links would have the name of a field – of needs_fields or needs_extra_options,
or one an extension or a service registers – or of another link type, one not refused itself, is refused, one needs.config warning naming both:
needs_links entry 'x' declares the link type 'x', whose back links would be 'x_back', which is a field (from needs_fields); the link type is ignored
and does not exist: the need directive has no option of its name, its needs have no back links,
and neither the needs.json, a needflow nor a needtable knows it; the field (or link type) x_back keeps its values.
A link type that is itself refused claims no name: of the link types x, x_back and x_back_back,
x_back is refused and x kept, its back links named x_back.
The back links of links and parent_needs yield to nothing: a link type, or a field, named links_back or parent_needs_back is ignored instead,
one needs.config warning.
Default values¶
Added in version 7.0.0.
A link type’s default and predicates are given, and evaluated, as a field’s are:
see Default values for the values they take and the data a match expression reads.
For example:
needs_links = {
"custom_link": {
"predicates": [
# if status is "done", set to ["ID123"]
("status == 'done'", ["ID123"]),
# else if status is "ongoing", set to a dynamic value
("status == 'ongoing'", '[[copy("yyy")]]'),
],
# the base default is a dynamic value
"default": '[[copy("xxx")]]',
},
}
allow_dead_links¶
Added in version 0.6.3.
By setting allow_dead_links to True, referenced, but not found needs do not throw a warning.
Instead the same text gets printed as log message on level INFO.
Filtering¶
Need objects have the two attributes has_dead_links and has_forbidden_dead_links.
has_dead_links gets set to True, if any dead link was found in the need.
And has_forbidden_dead_links is set to True only, if dead links were not allowed
(so allow_dead_links was set to False for at least one link type with dead links).
A union its rule computed counts only through its members:
its dead links are forbidden where a member holding them does not allow dead links, as they are drawn.
HTML style¶
Also dead links get specific CSS attributes on the HTML output:
needs_dead_link for all found dead links and an additional forbidden for link_types
with allow_dead_links not set or set to False.
By default not allowed dead links will be shown in red , allowed ones in gray (see above example).
style / style_part¶
The style string can contain the following comma separated information:
color: #ffcc00 or red
line style: dotted, dashed, bold
Valid configuration examples are:
#ffcc00dasheddotted,#red
An empty string uses the default plantuml settings.
style_start / style_end¶
These two options can define the arrow type, line type and line length.
See Plantuml documentation page for details about supported formats.
Here are some examples:
description |
style_start |
style_end |
|---|---|---|
default |
|
|
reverse |
|
|
Both sides, dotted line |
|
|
Deeper level / longer line |
|
|
Use style_start and style_end like this:
needs_links = {
"tests": {
"incoming": "is tested by",
"outgoing": "tests",
"copy": False,
"style_start": "<-",
"style_end": "down-->",
"style": "#00AA00",
"style_part": "dotted,#00AA00",
},
}
Note
Some plantuml diagrams have restrictions in the order of color (style)
and orientation (left, right, up and down). We suggest to set the orientation
in style_end like in the example above, as this is more often supported.
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
Nonevalues, 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_derive_max_links_per_need¶
Added in version 9.1.0.
Default: 100
How many links per need of the project a link type may compute before it is reported:
when the lists a links or content_links rule computes (Derived fields),
or the links_from_filter, links_from_content and links_from_match calls of a link type without one,
hold more links in all than this value times the needs of the project,
the warning needs.derive_dense names the link type once (see What a rule costs).
Written links, those a needextend adds and back links are not counted;
the needs of the project are every need, external and imported ones too, but not need parts.
0 (or less) never warns, and suppress_warnings = ["needs.derive_dense"] silences it.
Unlike needs_filter_max_time it counts rather than times, so every build of the same project warns alike.
[needs]
derive_max_links_per_need = 500
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:
internalDraw the legend inside the picture where the engine can, and beside it where the engine cannot.
externalDraw 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_show_links¶
Added in version 0.3.11.
Changed in version 8.4.0: Accepts a value as well as a boolean.
What needflow diagrams label their connections with by default:
none (the default), outgoing, incoming or type.
needs_flow_show_links = "outgoing"
Default value: False, i.e. none.
True and False are also accepted, and mean outgoing and none, which is
what they have always meant.
The same goes for any other non-string value: this option was declared a boolean for
years, so a truthy one such as 1 still draws labels.
A string that is not one of the four values is a mistake rather than a truth value, so
it warns and falls back to none – which is the one input whose behaviour changes,
since it used to draw labels.
A diagram overrides it with show_link_names,
including turning labels off again with none.
Note
Every enumerated needs_flow_* value – this one, needs_flow_direction
and needs_flow_engine – is matched without regard to case or surrounding
whitespace, exactly as the matching directive option is.
needs_flow_link_types¶
Added in version 0.3.11.
Defines the link_types to show in a needflow diagram:
needs_flow_link_types = ['links', 'blocks', 'tests']
You can define this setting on each specific needflow by using the needflow directive option link_types.
See also link_types for more details.
Default value: ['links']
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
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:
the
:template:option of an individual needreport directive (see template), resolved relative to the document the directive is written in;needs_report_template, resolved relative to the source directory as described above;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:
{# 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.
typesThe needs_types configuration, as a list of dictionaries, plus any types registered by a loaded service or extension.
linksThe needs_links configuration, as a list of dictionaries carrying the keys
option,incoming,outgoing,copyandallow_dead_links.optionsThe names of the configured needs_fields, as a list of strings, plus any fields registered by a loaded service or extension.
report_directiveThe name of the directive each section of the packaged template is wrapped in.
dropdown, unless needs_render_context names another one, or nothing providesdropdownand substitutingadmonitionchanges what the report renders — see the note above.usageA dictionary with the keys
needs_amountandneeds_types, the latter holding one entry per directive name in needs_types.Warning
Only the keys of
usage["needs_types"]carry information. Every number inusage—needs_amountincluded — is permanently0, 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 reports0however 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
usagefor 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.
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.
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:
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_show_link_type¶
Added in version 0.1.27.
This option mostly affects the roles need_outgoing and need_incoming by showing the type beside the ID of the linked need.
Can be combined with needs_show_link_title.
Activate it by setting it on True in your conf.py:
needs_show_link_type = True
needs_show_link_title¶
Added in version 0.1.27.
This option mostly affects the roles need_outgoing and need_incoming by showing the title beside the ID of the linked need.
Can be combined with needs_show_link_type.
Activate it by setting it on True in your conf.py:
needs_show_link_title = True
needs_show_link_id¶
Added in version 1.0.3.
This option mostly affects the roles need_outgoing and need_incoming by showing the ID of the linked need.
Can be combined with needs_show_link_type and needs_show_link_title.
needs_show_link_id = True
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.htmlis provided. Base url supports also relative path, which starts from project build html folder (normally whereindex.htmlis located).- target_url:
Allows to config the final calculated need url. (optional)
If provided,target_urlwill be appended tobase_urlas the final calculate need url, e.g.base_url/target_url, unless it renders an absolute URL (scheme://…or//…, such as"{{need['remote_url']}}"renderinghttps://github.com/…), which is used as it is;base_urlmay then be"". A render with a scheme but no//, such asreq:REQ_1, is appended as before. If notarget_urlis given, the external need url uses the default calculatedbase_url.
Thetarget_urlsupports Jinja context{{need[]}},need optionused 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.jsonfile located inside your documentation project. Can not be used together withjson_url.
The value must be a relative path, which is relative to the project configuration folder (where the conf.py is stored). (Since version0.7.1)- version:
Defines the version to use inside the
needs.jsonfile (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
tagsneed field is provided as a string like"tag1,tag2,[[func()]]", it will be parsed only if this option is set toTrue, 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_string_links¶
Added in version 0.7.4.
Transforms a given option value to a link.
Helpful e.g. to generate a link to a ticket system based on the given ticket number only.
needs_string_links = {
'custom_name': {
'regex': "...",
'link_url' : "...",
'link_name': '...'
'options': ['status', '...']
}
}
All four keys are required.
- regex:
Must be a valid regular expression. Named capture groups are supported. An already-compiled
re.Patternis also accepted, and keeps its flags; a bytes pattern is not, as it could never match a field value.- link_url:
The final url as string. Supports Jinja.
- link_name:
The final link name as string. Supports Jinja.
- options:
List of option names, for which the regex shall be checked. A tuple, set or frozenset is also accepted; the names are only ever membership-tested, so their order does not matter. A bare string is not a valid spelling of a single name.
link_name and link_url are rendered with MiniJinja,
which implements a subset of the Jinja2 syntax; most notably, not every Jinja2 filter exists.
All named capture group values get injected, so that parts of the option-value can be reused for
link name and url. Unnamed groups are not available to the templates.
Example:
# conf.py
needs_string_links = {
# Adds link to the Sphinx-Needs configuration page
'config_link': {
'regex': r'^(?P<value>\w+)$',
'link_url': 'https://sphinx-needs.readthedocs.io/en/latest/configuration.html#{{value | replace("_", "-")}}',
'link_name': 'Sphinx-Needs docs for {{value | replace("_", "-") }}',
'options': ['config']
},
# Links to the related github issue
'github_link': {
'regex': r'^(?P<value>\w+)$',
'link_url': 'https://github.com/useblocks/sphinx-needs/issues/{{value}}',
'link_name': 'GitHub #{{value}}',
'options': ['github']
}
}
Example 6
.. spec:: Use needs_string_links
:id: EXAMPLE_STRING_LINKS
:config: needs_string_links
:github: 404,652
Replaces the string from ``:config:`` and ``:github:`` with a link to the related website.
Replaces the string from |
Note
You must define the options specified under needs_string_links inside needs_fields as well.
Values are split into items¶
A field named in any entry’s options has its value split on ``,`` and ``;``, and each item
is stripped and then linked on its own. This is how a field can hold several ticket numbers, as in
the :github: 404,652 example above.
The splitting applies to every field named in options, whether or not the regular expression
ends up matching anything, and there is no way to escape a separator: a value such as
https://example.com/a,b is split into two items, of which only the first is linked. If a field
may hold a literal , or ;, do not name it in options.
Items that are empty once stripped are dropped, so AB-1, , AB-2 is two items. Rendered items
are joined with ;, which means the separators in the output do not necessarily match the ones
in the source value.
The first entry naming a field wins¶
Only the first entry whose options names the field is ever consulted – entries are tried
in the order they are declared, and there is no fallthrough. If that entry’s regular expression
does not match, the value renders as plain text even when a later entry would have matched it. To
apply different patterns to one field, combine them into a single regular expression with |.
A value that matches no entry renders as plain text, silently. This is the intended fallback, not an error.
The regular expression is searched, not anchored¶
The pattern is applied with Python’s re.Pattern.search(), so it is unanchored. On a match, the
whole item is replaced by the rendered link – any text around the match is discarded. Anchor
the pattern with ^ and $ unless you intend the entire value to be replaced.
Interaction with needs_render_context¶
needs_render_context is merged over the named capture groups, so a context key shadows a
capture group of the same name. As the examples above use value as their group name, a
needs_render_context entry called value will silently rewrite every such link in the
project. Keys that do not collide are simply available to both templates as extra variables.
Where string links are applied¶
String links are applied in the need’s meta area (and therefore in needextract too) and in needtable cells. For a field holding a list, each element is linked individually.
They are not applied to the ID column of a needtable, nor to its link-type columns, which
keep their references to the needs themselves; nor do they appear in needs.json, which always
holds the raw value.
Invalid configurations¶
Changed in version 8.4.0: The configuration is validated once, when it is loaded.
An entry that cannot be used – a missing key, a regular expression that does not compile, a
template that does not parse, options that is none of the accepted collection spellings
(a bare string and a mapping are the two that get rejected) – is reported as a
needs.string_link warning naming the entry, and skipped. The build continues and every other
entry still applies. Previously such an entry aborted the build the moment the first need was
rendered.
The same subtype reports the cases that used to pass in silence – an unknown key inside an
entry, an options entry naming a field that is registered nowhere, an empty options –
none of which skips the entry.
A template can still fail while it is rendered – an unknown filter, for instance, only fails
then – which is reported as a needs.layout warning; the value renders as plain text. Every
render-time failure uses that subtype, on every surface.
The two subtypes therefore divide as follows, and both take a Sphinx suppress_warnings entry:
needs.string_link:the configuration is unusable, or contains something that can never apply. Emitted once per problem when the configuration is loaded.
needs.layout:a template failed while rendering a particular value. Emitted per value, and shared with the other layout-rendering warnings.
suppress_warnings = ["needs.string_link", "needs.layout"]
Note
A configuration mistake that was previously silent – or that crashed the build – is now a
warning, and a warning fails a -W build. So a project that passed with -W before
8.4.0 can start failing on a needs_string_links it never changed. The same applies to
render-time failures the list-field fix newly reaches: a template that fails on a list
field is now reported (as needs.layout), where the meta area used to swallow it.
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_json_include_link_conditions¶
Added in version 8.0.0.
When True (the default), outgoing link fields in the needs.json output include
any conditions attached to the link, for example NEED-1[status=="open"].
When False, only the target need ID is written, for example NEED-1.
This option only affects outgoing link fields. Backlink fields (e.g. links_back)
never carry conditions, so they are unaffected by this setting.
Default: True
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_permalink_file¶
The option specifies the name of the permalink html file, which will be copied to the html build directory during build.
The permalink web site will load a needs.json file as specified
by needs_permalink_data and re-direct the web browser to the html document
of the need, which is specified by appending the need ID as a query
parameter, e.g., http://localhost:8000/permalink.html?id=REQ_4711.
Example:
needs_permalink_file = "my_permalink.html"
Results in a file my_permalink.html in the
html build directory.
If this directory is served on localhost:8000, then the file will be
available at http://localhost:8000/my_permalink.html.
Default value: permalink.html
needs_permalink_data¶
This options sets the location of a needs.json file.
This file is used to create permanent links for needs as described
in needs_permalink_file.
The path can be a relative path (relative to the permalink html file), an absolute path (on the web server) or an URL.
Default value: needs.json
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
|
This is a requirement describing security processes. |
Requirement: R_6F47F
|
Example of a successful constraint. |
Requirement: FAIL_01
|
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 %}
Need with alias Project_X and List of contributors:
|
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,sourceandline: the directive and where it is written;filter: the directive’s filter, its:status:,:tags:and:types:joined to its:filter:withand;needs_countandruntime: 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’seval), 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 avar.value or ofcis 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 undervar.),name:<name>(needs,current_need,c,var,searchor a__dunder__name as a value),not(anotas 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, …), andfilter-codeandfilter-funcfor a directive’s filter code and Filter function.syntaxnames 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 invalidfield_success: Global field validation was successfulfield_fail: Global field validation failedlink_success: Global extra link validations was successfullink_fail: Global extra link validation failedselect_success: Successful select validationselect_fail: Failed select validationlocal_success: Successful local validationlocal_fail: Need local validation failednetwork_missing_target: An outgoing link target cannot be resolvednetwork_contains_too_few: minContains or minItems validation failed for the given link_schema link typenetwork_contains_too_many: maxContains or maxItems validation failed for the given link_schema link typenetwork_items_fail: items validation failed for the given link_schema link typenetwork_local_success: Successful network local validationnetwork_local_fail: Need does not validate against the local schema in a network contextnetwork_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
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
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"),
],
}
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:
any needs_fields key
any needs_links field
statuslayoutstyletagsconstraints
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_links (
tuple[str, ...])needs_variant_data (via the
varnamespace)
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_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: []
needs_report_dead_links¶
Deprecated since version 2.1.0: Instead add needs.link_outgoing to the suppress_warnings list:
suppress_warnings = ["needs.link_outgoing"]
Deactivate/activate log messages of disallowed outgoing dead links. If set to False, then deactivate.
Default value is True.
Configuration example:
needs_report_dead_links = False
needs_extra_links¶
Deprecated since version 7.0.0: Use needs_links instead.
Allows the definition of additional link types as a list.
Each configured link should define:
option: The name of the option. Example “blocks”.predicates(optional): A list of(match expression, value)tuples.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(optional): A default value for the field.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 toTrue, the field will support variant options and variant data references.Default:
False.
parse_dynamic_functions: If set toTrue, the field will support Dynamic functions.Default: the value of needs_parse_dynamic_functions (
True).
parse_conditions: If set toFalse, the[condition]bracket syntax will not be parsed for this link type.Default:
True. New in version 8.0.0.
incoming(optional): Incoming text, to use for incoming links. E.g. “is blocked by”.outgoing(optional): Outgoing text, to use for outgoing links. E.g. “blocks”.copy(optional): True/False. If True, the links will be copied also to the common link-list (link typelinks). Default: False. Deprecated since 9.1.0 and removed in 10.0, as on needs_links: a union replaces it.allow_dead_links(optional): True/False. If True, dead links are allowed and do not throw a warning. See allow_dead_links for details. Default: False.target_types(optional): The need types the links may point to, as for needs_links.style(optional): A plantuml style description, e.g. “#FFCC00”. Used for needflow. See style / style_part.style_part(optional): Same asstyle, but get used if link is connected to a need_part / np. See style / style_part.
The back links of a link type are named <option>_back, and one whose back links would have the name of a field
or of another link type is refused, one needs.config warning, as for needs_links.
Any other key in an entry, and a keyword its schema does not have, is reported and ignored as for needs_links
(needs_extra_links['blocks'] has an unknown key ...).
Configuration example:
needs_extra_links = [
{
"option": "checks",
},
{
"option": "triggers",
"predicates": [
('"urgent" in tags', ["ID999", "ID998"]),
],
"default": ["ID123"],
"incoming": "is triggered by",
"outgoing": "triggers",
"copy": False,
"allow_dead_links": True,
"style": "#00AA00",
"style_part": "#00AA00",
"style_start": "-",
"style_end": "--o",
}
]