Importing and extending needs

Three directives create or change needs without a need directive of their own: needimport reads needs from a needs.json file, needextend changes needs written elsewhere, and list2need turns a bullet list into needs. ubCode applies all three while it indexes the project, so every card, view and needs.json export shows their result, in the editor preview and in its html and pdf builds (the pdf build cannot draw the cards of a list2need yet).

The specimens below create and change only needs whose ids start EX_IMP_, EX_REQ_EXTEND_ or EX_*_LIST_, so no view on another page shows them.

Importing needs

needimport reads a needs.json file, as a Sphinx-Needs or ubCode build exports it, and creates a need for each record it selects, drawn as a card where the directive stands. The file of this specimen is beside these docs’ source directory; a path starting with / is read from the source directory, and any other path from the document’s own directory.

Importing needs from a file

.. needimport:: /../specimens/needs/imported.json
   :ids: EX_IMP_REQ_1, EX_IMP_SPEC_1
   :tags: ex-import
Requirement: Back up the database EX_IMP_REQ_1
status: open
tags: ex-import
links incoming: EX_IMP_SPEC_1

A backup runs every night.

Specification: Keep seven backups EX_IMP_SPEC_1
status: done
tags: ex-import
links outgoing: EX_IMP_REQ_1

The oldest backup is deleted when an eighth is written.

```{needimport} /../specimens/needs/imported.json
:ids: EX_IMP_MYST_REQ_1, EX_IMP_MYST_SPEC_1
:tags: ex-import
```

The MyST form renders live in the MyST import.

The argument can also be a URL, which is downloaded when the project is read; these docs import only a local file, so that building them reaches no network.

:ids:

The ids of the records to import, separated by commas; unset, every record is imported.

:filter:

An expression the records must pass, in the syntax of a view’s :filter: (see Python syntax).

:tags:

Tags added to every imported need, after the tags of its record.

:id_prefix:

Text put in front of every imported id, and of every id a record’s links name that belongs to the file.

:version:

The version of the file to read; unset, its current_version.

Note

ubCode draws the imported cards in id order, where a Sphinx-Needs build draws them in the order of :ids:, or of the file (see the need-card differences).

A record’s id is its key in the file’s needs object: a record whose own id says otherwise is imported under its key, and reported, in ubCode and from Sphinx-Needs 9.0.0 on.

Extending needs

needextend changes needs that are written somewhere else in the project. Its argument is a need id, or a filter in double quotes (or any argument with a space in it); the quotes are taken off, so a string inside the filter is written in single quotes. Each option names a field and the change made to it.

Extending a need

.. req:: Sign the release
   :id: EX_REQ_EXTEND_1
   :status: open
   :tags: ex-extend

   Every release is signed before it is published.

.. needextend:: EX_REQ_EXTEND_1
   :status: done

.. needextend:: "'ex-extend' in tags and status == 'open'"
   :+tags: reviewed
Requirement: Sign the release EX_REQ_EXTEND_1
status: done
tags: ex-extend, reviewed

Every release is signed before it is published.

```{req} Sign the release
:id: EX_REQ_EXTEND_MYST_1
:status: open
:tags: ex-extend-myst

Every release is signed before it is published.
```

```{needextend} EX_REQ_EXTEND_MYST_1
:status: done
```

```{needextend} "'ex-extend-myst' in tags and status == 'open'"
:+tags: reviewed
```

The MyST form renders live in the MyST extends.

The card shows the need as both extends leave it: done, and tagged reviewed. The second filter still matches although the first extend has set the status to done, because every filter is matched against the needs as written, before any needextend applies. That is the rule from Sphinx-Needs 9.0.0 on, and ubCode’s; an earlier Sphinx-Needs matched each filter against the changes of the extends before it.

:<field>:

Replaces the field’s value.

:+<field>:

Adds to it: text is appended, and a list or link type gains the values.

:-<field>:

Empties it.

:extend_priority:

The order the extends are applied in, lower first (500 when unset); where two set the same field, the one applied last wins.

A needextend draws nothing in a built page; the editor preview shows it as a chip naming the need or filter and the changes, so that you can see it while you write (see needextend renders nothing in a built page). An id that names no need is reported (needs.extend_missing_id); a filter that matches nothing is not. How the argument is read, and the order the extends apply in, are under The needextend argument: id or filter? and The order needextend directives apply in.

Needs from a list

list2need turns a bullet list into needs: each item is a need, and :types: names the need type of each level of the list, two spaces deeper per level. An item reads (ID) Title. Content: the id in parentheses, the title up to the first full stop, and the rest as the need’s content.

Needs from a list

.. list2need::
   :types: req, spec
   :tags: ex-list

   * (EX_REQ_LIST_1) Load a settings file. The settings are read at start-up.
     * (EX_SPEC_LIST_1) Read the file as TOML. Any other format is reported.
Requirement: Load a settings file EX_REQ_LIST_1
tags: ex-list
child needs: EX_SPEC_LIST_1

The settings are read at start-up.

Specification: Read the file as TOML EX_SPEC_LIST_1
tags: ex-list
parent needs: EX_REQ_LIST_1

Any other format is reported.

```{list2need}
:types: req, spec
:tags: ex-list

* (EX_REQ_MYST_LIST_1) Load a profile. The profile is read at log-in.
  * (EX_SPEC_MYST_LIST_1) Read the profile as JSON. Any other format is reported.
```

The MyST form renders live in the MyST list.

Note

ubc build pdf cannot place a list2need directive yet (it reports one as build.pdf_block_unsupported), so the PDF shows this specimen’s source only.

In the editor preview and the built site, the specification is drawn inside the card of the requirement above it, and each records the other as its parent or child need.

:types:

The need type of each level, separated by commas.

:tags:

Tags given to every need of the list.

:presentation:

nested, the default, draws a deeper item’s card inside the card above it; standalone draws every card on its own.

:links-down:

The link type each level links to the items below it with, separated by commas.

:delimiter:

The text that ends the title, . when unset.

An item without an id gets one made from its need type’s prefix and a hash of its title, the same in both tools and without a report, even where id_required is set; give every item an id, so that it does not change when the title does. Where the two tools read a list differently is under the list differences.