Needs¶
The [needs] section is the heart of your ubproject.toml.
It tells ubCode how to identify, validate, and relate the need objects
in your reStructuredText files —
types, link types, custom fields, statuses, tags, and external needs.
See also
Minimal example¶
[needs]
id_required = true
id_regex = "^[A-Z]{3}_[0-9]{3}$"
[[needs.types]]
directive = "requirement"
title = "Requirement"
prefix = "REQ_"
[needs.links.implements]
outgoing = "implements"
incoming = "implemented by"
[needs.fields.priority]
description = "Priority level"
Core options¶
- id_required
Type:
boolean(default:false)If
true, every need must have an explicit ID. Iffalse, IDs will be auto-generated when not provided.- id_regex
Type:
string(default:"^[A-Z0-9_]{5,}")Regular expression pattern to validate need IDs against. Only applies when
id_requiredistrue.- id_length
Type:
integer(default:5)Length of auto-generated IDs when not explicitly provided.
- id_from_title
Type:
boolean(default:false)When
true, auto-generated IDs will be based on the need title instead of being random.- title_optional
Type:
boolean(default:false)When
true, allows needs to be created without a title.- title_from_content
Type:
boolean(default:false)When
true, auto-generates titles from the first line of need content when no title is provided.
Need types¶
The types array defines the available need directives in your project:
[[needs.types]]
directive = "requirement" # The RST directive name
title = "Requirement" # Human-readable title
prefix = "REQ_" # Prefix for auto-generated IDs
color = "#BFD8D2" # Color for diagrams
style = "node" # Style for diagrams
Each type supports:
directive(required): The reStructuredText directive nametitle(required): Human-readable title for the need typeprefix(required): Prefix used for auto-generated need IDscolor(optional, default:"#000000"): Color used in need diagramsstyle(optional, default:"node"): Style used in need diagrams
Link types¶
Links connect needs to one another and express relationships like implements, tests, or depends on. ubCode supports two configuration formats: the dict-based format (sphinx-needs ≥ 6.3, recommended) and the list-based format (sphinx-needs < 6.3).
Dict-based format (recommended)¶
Note
The dict-based [needs.links] format requires sphinx-needs ≥ 6.3.
It became the recommended format in sphinx-needs 7.0,
where the older list-based needs_extra_links was formally deprecated.
Use [needs.links.<name>] to define each link type as a named TOML table:
[needs.links.implements]
outgoing = "implements"
incoming = "implemented by"
copy = false
color = "#0000FF"
allow_dead_links = false
[needs.links.tests]
outgoing = "tests"
incoming = "tested by"
copy = true
Each link supports:
outgoing(optional): Description for outgoing linksincoming(optional): Description for incoming linkscopy(optional, default:false): Whether to copy to common linksallow_dead_links(optional, default:false): Allow links to non-existent needscolor(optional, default:"#000000"): Color for diagramsstyle(optional, default:"solid"): Line style for diagramsstyle_part(optional, default:"dotted"): Style for partial linksstyle_start(optional, default:"-"): Start marker for diagramsstyle_end(optional, default:">"): End marker for diagramsparse_variants(optional): Whether to parse variant functions in this link’s values. sphinx-needs ≥ 7.0.parse_dynamic_functions(optional): Whether to parse dynamic functions in this link’s values. sphinx-needs ≥ 6.3.parse_conditions(optional, default:true): Whether bracket syntax in link values is interpreted as a condition expression. sphinx-needs ≥ 8.0.description(optional): Human-readable description of the link type. sphinx-needs ≥ 6.3.schema(optional): JSON Schema validation for link values
List-based format (sphinx-needs < 6.3)¶
Deprecated since version 0.25.0: The list-based [[needs.extra_links]] format
(needs_extra_links in sphinx-needs)
was deprecated in sphinx-needs 6.3 in favour of the dict-based format,
and formally migrated in sphinx-needs 7.0.
It remains supported for backward compatibility.
For new projects, prefer the dict-based [needs.links] format.
[[needs.extra_links]]
option = "implements" # The option name used in need directives
incoming = "implemented by" # Description for incoming links
outgoing = "implements" # Description for outgoing links
copy = false # Whether to copy to common links
color = "#0000FF" # Color for diagrams
style = "solid" # Line style for diagrams
style_part = "dotted" # Style for partial links
style_start = "-" # Start marker for diagrams
style_end = ">" # End marker for diagrams
allow_dead_links = false # Allow links to non-existent needs
Fields¶
Every need carries fields — named pieces of metadata
such as status, tags, or any custom attribute you define.
Some fields are built in (id, title, status, tags);
you can add your own through the configuration.
ubCode supports two formats:
the dict-based [needs.fields] format (aligned with sphinx-needs ≥ 7)
and the list-based extra_options format (for sphinx-needs < 7).
Dict-based format (recommended)¶
Note
The dict-based [needs.fields] format requires sphinx-needs ≥ 7.0.
It replaces the older list-based needs_extra_options
and also allows specializing core fields (e.g. status, tags)
by narrowing their type constraints.
Use [needs.fields.<name>] to define each custom field:
[needs.fields.priority]
description = "Priority level"
default = "medium"
[needs.fields.assignee]
description = "Assigned team member"
[needs.fields.effort]
description = "Story points"
schema = {type = "integer", minimum = 1, maximum = 13}
Each field supports:
description(optional): Human-readable descriptiondefault(optional): Default value if not specified on a needschema(optional): JSON Schema to validate values (see Field schemas below). Schema support for fields was introduced in sphinx-needs 6.0 (via ``needs_extra_options``) and carried forward to ``needs_fields`` in sphinx-needs 7.0.nullable(optional): Whether the field accepts null values. sphinx-needs ≥ 7.0.predicates(optional): Conditional defaults (see Global options). sphinx-needs ≥ 7.0.parse_variants(optional): Whether to parse variant functions in this field’s values. sphinx-needs ≥ 7.0.parse_dynamic_functions(optional): Whether to parse dynamic functions in this field’s values. sphinx-needs ≥ 6.3.
Once declared, these fields can be used on any need:
.. req:: Encrypt data at rest
:id: REQ_002
:status: open
:priority: high
:assignee: alice
:effort: 5
List-based format (sphinx-needs < 7)¶
Deprecated since version 0.25.0: The list-based extra_options format
(needs_extra_options in sphinx-needs)
was deprecated in sphinx-needs 7.0 in favour of the dict-based format.
It remains supported for backward compatibility.
For new projects, prefer the dict-based [needs.fields] format.
Simple format (string list):
extra_options = ["priority", "effort", "assignee", "component"]
Detailed format (with descriptions and schemas):
extra_options = [
{name = "priority", description = "Priority level"},
{name = "effort", description = "Story points", schema = {type = "integer", minimum = 1, maximum = 13}},
{name = "assignee", description = "Assigned team member"},
]
Field schemas¶
The schema key on a field applies
JSON Schema validation
to every value entered for that field.
Invalid data is caught at index time, before the docs are built.
String schemas:
[needs.fields.contact]
schema = {type = "string", format = "email"}
[needs.fields.id_pattern]
schema = {type = "string", pattern = "^[A-Z]{3}-[0-9]{4}$"}
[needs.fields.severity]
schema = {type = "string", enum = ["low", "medium", "high", "critical"]}
String format options:
The format property supports various predefined formats:
"date": RFC 3339 date format (e.g.,2023-10-22)"date-time": RFC 3339 date-time format (e.g.,2023-10-22T14:30:00Z)"time": RFC 3339 time format (e.g.,14:30:00Z)"email": RFC 5322 email address (e.g.,user@example.com)"hostname": RFC 1123 hostname (e.g.,example.com)"uri": RFC 3986 URI (e.g.,https://example.com/path)"uuid": RFC 4122 UUID (e.g.,550e8400-e29b-41d4-a716-446655440000)"regex": ECMAScript regular expression
Integer and number schemas:
[needs.fields.priority]
schema = {type = "integer", minimum = 1, maximum = 10}
[needs.fields.rating]
schema = {type = "number", minimum = 0.0, maximum = 5.0}
[needs.fields.fibonacci]
schema = {type = "integer", enum = [1, 2, 3, 5, 8, 13, 21]}
Boolean schemas:
[needs.fields.approved]
schema = {type = "boolean"}
Array schemas:
[needs.fields.reviewers]
schema = {type = "array", items = {type = "string", format = "email"}, minItems = 1, maxItems = 3}
[needs.fields.categories]
schema = {type = "array", items = {type = "string"}, uniqueItems = true}
Usage in need directives:
Once defined, these fields can be used in your need directives:
.. requirement:: User Authentication
:priority: 5
:effort: 8
:assignee: developer@company.com
:due_date: 2024-12-31
:tags: security, authentication
:component: auth, backend
:active: true
Users must be able to authenticate using their corporate credentials.
External needs¶
Load needs from external sources (JSON files or URLs):
# From local file
[[needs.external_needs]]
json_path = "external/project_needs.json"
id_prefix = "EXT"
base_url = "https://external-project.com"
target_url = "docs/{{ id }}.html"
# From remote URL
[[needs.external_needs]]
json_url = "https://api.example.com/needs.json"
id_prefix = "REMOTE"
Each external needs source supports:
json_path: Path to a local JSON filejson_url: URL to a remote JSON fileid_prefix: Prefix prepended to external need IDsbase_url: Base URL for linking back to the source projecttarget_url: URL template for individual need links (supports{{ id }}placeholder)css_class: CSS class applied to external needsversion: Version string for the external needs sourceskip_in_ubcode(default:false): Whentrue, skip loading these external needs in ubCode analysis
Variants¶
The [needs.variants] section defines named filter expressions
that can be referenced from need fields using the <<name: value, fallback>> syntax.
This implements the Sphinx-Needs
variant functions
feature.
[needs.variants]
is_open = "status == 'open'"
is_html = "'html' in build_tags"
is_production = "environment == 'production'"
With these variants defined, need fields can use them:
.. req:: My requirement
:id: REQ_001
:status: <<is_open: active, inactive>>
:extra: <<is_html: web_only, general>>
You can also use inline bracketed expressions without pre-defining a variant:
.. req:: Another requirement
:id: REQ_002
:status: <<[status == 'open']: active, inactive>>
The last comma-separated value is always the fallback when no expression matches.
Note
Variant syntax is only parsed for fields that opt in.
In sphinx-needs ≥ 7.0, set parse_variants = true
on individual fields in [needs.fields].
For older versions, use the deprecated variant_options list
(see Deprecated needs options).
Parse and evaluation errors are surfaced as needs.variant diagnostics.
Dynamic functions¶
ubCode resolves some built-in dynamic functions using the [[...]] syntax
from sphinx-needs.
Three built-in functions are supported:
echo("text")— returns the given string unchangedtest(*args, **kwargs)— returns a debug string with the need ID and argumentscopy("field")— copies a field value from the current need (also supportslowerandupperkwargs)
For example:
.. req:: My requirement
:id: REQ_001
:status: [[copy("priority")]]
Dynamic function parsing is enabled by default and can be controlled globally or per-field/per-link:
[needs]
parse_dynamic_functions = false # disable globally (sphinx-needs ≥ 7.0)
[needs.fields.my_field]
parse_dynamic_functions = true # re-enable for this field (sphinx-needs ≥ 6.3)
[needs.links.implements]
parse_dynamic_functions = true # re-enable for this link (sphinx-needs ≥ 6.3)
- parse_dynamic_functions
Type:
boolean(default:true)Whether dynamic functions are parsed by default. Applies to extra fields and links unless overridden per-field/per-link. Core fields are not affected by this global setting.
The global
parse_dynamic_functionsoption was added in sphinx-needs 7.0 (needs_parse_dynamic_functions). Per-field and per-linkparse_dynamic_functionswas added in sphinx-needs 6.3.
filter_data¶
Type: object (default: {})
Additional context variables that can be referenced in filter expressions throughout your needs configuration. This allows you to define custom variables for conditional logic in multiple contexts.
Where filter_data can be used:
Predicate default filters — in
global_optionspredicates (orpredicateson individual fields/links in sphinx-needs ≥ 7.0) to conditionally set default valuesneedimport item filters — to filter which needs are imported from external sources
needextend filters — to conditionally extend or modify needs based on context
[needs]
filter_data = { environment = "production", team = "backend", version = "2.0" }
# Using predicates on a field directly (sphinx-needs ≥ 7.0, recommended)
[needs.fields.priority]
default = "medium"
predicates = [
["environment == 'production'", "high"],
["team == 'backend'", "high"]
]
# Or via global_options (sphinx-needs < 7, deprecated)
# [needs.global_options.priority]
# default = "medium"
# predicates = [
# ["environment == 'production'", "high"],
# ["team == 'backend'", "high"]
# ]
Example with needimport:
.. needimport:: external_needs.json
:filter: environment == 'production' and version == '2.0'
Example with needextend:
.. needextend:: team == 'backend'
:status: critical
Common use cases:
Setting environment-specific defaults (development, staging, production)
Filtering imported needs based on release version or team ownership
Applying team or project-specific configurations
Conditional formatting or validation based on build context
Dynamic behaviour in CI/CD pipelines
import_keys¶
Type: object (default: {})
Mapping of keys for needimport directives,
allowing short keys to reference longer file paths.
Available since sphinx-needs 4.2.
[needs.import_keys]
backend = "/path/to/backend_needs.json"
frontend = "/path/to/frontend_needs.json"