Skip to content

Commit

Permalink
rasied version to 0.1.25. Added incoming/outgoing roles. Restructured…
Browse files Browse the repository at this point in the history
… code and docs
  • Loading branch information
danwos committed Jun 19, 2017
1 parent e62841f commit 84f9f22
Show file tree
Hide file tree
Showing 22 changed files with 1,326 additions and 1,105 deletions.
8 changes: 8 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Changelog
=========

0.1.25
------

* Restructured code
* Restructured documentation
* Improvement: Role :ref:`role_need_outgoingt` was added to print outgoing links from a given need
* Improvement: Role :ref:`role_need_incoming` was added to print incoming links to a given need

0.1.24
------

Expand Down
165 changes: 165 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
.. _config:

Configuration
=============

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

Activation
----------

Add **sphinxcontrib.needs** to your extensions::

extensions = ["sphinxcontrib.needs",]

Options
-------

All options starts with the prefix **needs_** for this extension.

needs_include_needs
~~~~~~~~~~~~~~~~~~~
Set this option on 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

.. _need_types:

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 must be a list of dictionaries, where each dictionary **must** contain the following items:

* **directive**: Name of the directive. For instance "req", which can be used via `.. req::` in documents
* **title**: Title, which is 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.
* **style**: A plantuml node type, like node, artifact, frame, storage or database. See `plantuml documentation <http://plantuml.com/deployment-diagram>`_ for more.

needs_template
~~~~~~~~~~~~~~

The layout of needs can be fully customized by using `jinja <http://jinja.pocoo.org/>`_.

If nothing is set, the following default template is used:

.. code-block:: jinja
{% raw -%}
.. _{{id}}:
{% if hide == false -%}
{{type_name}}: **{{title}}** ({{id}})
{{content|indent(4) }}
{% if status and not hide_status -%}
**status**: {{status}}
{% endif %}
{% if tags and not hide_tags -%}
**tags**: {{"; ".join(tags)}}
{% endif %}
**links incoming**: :need_incoming:`{{id}}`
**links outgoing**: :need_outgoing:`{{id}}`
{% endif -%}
{% endraw %}
Available jinja variables are:

* type
* type_name
* type_prefix
* status
* tags
* id
* links
* title
* content
* hide
* hide_tags
* hide_status

.. warning::

You must add a reference like `.. _{{ '{{id}}' }}:` to the template. Otherwise linking will not work!

needs_diagram_template
~~~~~~~~~~~~~~~~~~~~~~

This option allows to control the content of diagram elements, which get automatically generated by using
`.. needfilter::` and `:layout: diagram.`

This function is based on `plantuml <http://plantuml.com>`_, so that each
`supported style <http://plantuml.com/creole>`_ can be used.

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

.. code-block:: python
'node "YOUR_TEMPLATE" as need_id [[need_link]]'
By default the following template is used:

.. code-block:: jinja
{% raw -%}
<size:12>{{type_name}}</size>\\n**{{title}}**\\n<size:10>{{id}}</size>
{% endraw %}
.. _needs_id_required:

needs_id_required
~~~~~~~~~~~~~~~~~

.. versionadded:: 0.1.19

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

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

needs_id_required = True

By default this option is set to **False**.

If an ID is missing sphinx throws the exception "NeedsNoIdException" and stops the build.

**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!
188 changes: 188 additions & 0 deletions docs/directives.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
Directives
==========

need/ req (or any other defined need type)
------------------------------------------

Example::

.. req:: User needs to login
:id: ID123
:status: open
:tags: user;login
:links: ID444; ID_555

Our users needs to get logged in via our login forms on **/login.php**.

This creates a new requirement, with a title, content, given id, a status and several tags.

All options are optional, only the title as argument must be given.

However, if no **id** is given, a short hash value is calculated based on the title. If the title gets not changed, the
id will be stable for all upcoming documentation generations.

**Tags** must be separated by "**;**", like tag1; tag2;tag3. Whitespaces get removed.

**links** can be used to create a link to one or several other needs, no matter what kind of type they are.
All you need is the related ID.

There is an additional option **:hide:**, if this is set (no value is needed), the need will not be printed in
documentation. But it will show up in need filters!

You can also use **:hide_status:** and **:hide_tags:** to hide the related information for this need.

.. note::

By default the above example works also with `.. spec::`, `.. impl::`, `.. test::` and all other need types,
which are configured via **needs_types**.

.. _needfilter:

needfilter
----------

Example::

.. needfilter::
:status: open;in_progress
:tags: user; login
:types: req;Specification
:filter: "my_tag" in tags and ("another_tag" in tags or "closed" in status)
:show_status:
:show_tags:
:show_filters:
:show_legend:
:sort_by: id
:layout: list

This prints a list with all found needs, which match the filters for status, tags and types.

For **:status:**, **:tags:** and **:types:** values are separated by "**;**".
**:filter:** gets evaluated.

The logic, if a need belongs to the needfilter result list, is as followed::

status = (open OR in_progress) AND tags = (user OR login) AND types = (req OR spec) AND eval(filter) is True

For **:types:** the type itself and the human-readable type_title can be used as filter value.

If **:show_status:** / **:show_tags:** is given, the related information will be shown after the name of the need.

To show the used filters under a list, set **:show_filters:**

**:show_legend:** is supported only by **:layout:diagram**. It adds a legend with colors to the generated diagram.

The showed list is unsorted as long as the parameter **:sort_by:** is not used.
Valid options for **:sort_by:** are **id** and **status**.

.. _filter:

`:filter:`
~~~~~~~~~~

The filter option allows the definition of a complex query string, which gets evaluated via eval() in Python.
So each valid Python expression is supported. The following variables/functions are available:

* tags, as Python list (compare like ``"B" in tags``)
* type, as Python string (compare like ``"story" == type``)
* status, as Python string (compare like ``"opened" != status``)
* id, as Python string (compare like ``"MY_ID_" in id``)
* title, as Python string (compare like ``len(title.split(" ")) > 5``)
* links, as Python list (compare like ``"ID_123" not in links``)
* content, as Python string (compare like ``len(content) == 0``)
* :ref:`re_search`, as Python function for performing searches with a regular expression

If your expression is valid and it's True, the related need is added to the filter result list.
If it is invalid or returns False, the related need is not taken into account for the current filter.

**Examples**::

.. req:: Requirement A
:tags: A;
:status: open

.. req:: Requirement B
:tags: B;
:status: closed

.. spec:: Specification A
:tags: A;
:status: closed

.. spec:: Specification B
:tags: B;
:status: open

.. test:: Test 1

.. needfilter::
:filter: ("B" in tags or ("spec" == type and "closed" == status)) or "test" == type


This will have the following result:

.. req:: Requirement A
:tags: A; filter
:status: open
:hide:

.. req:: Requirement B
:tags: B; filter
:status: closed
:hide:

.. spec:: Specification A
:tags: A; filter
:status: closed
:hide:

.. spec:: Specification B
:tags: B; filter
:status: open
:hide:

.. test:: Test 1
:tags: awesome; filter
:hide:

.. needfilter::
:filter: ("B" in tags or ("spec" == type and "closed" == status)) or ("test" == type and "awesome" in tags)

.. _re_search:

search
++++++

search(pattern, variable) is based on
`Pythons re.search() function <https://docs.python.org/3/library/re.html#re.search>`_

The first parameter must be a regular expression pattern.
The second parameter should be on of the above variables(status, id, content, ..)

Example::

.. Returns True, if a email address is inside the need content.

.. needfilter::
:filter: search("(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", content)

`:layout:`
~~~~~~~~~~
Three different types of layouts are available:

* list (default)
* table
* diagram

Only **list** supports each needfilter option.

**table** and **diagram** are supporting the filter options only (status, tags, types, filter) and their design is somehow fix.

diagram
+++++++

Diagrams are available only, if the sphinx extension
`sphinxcontrib-plantuml <https://pypi.python.org/pypi/sphinxcontrib-plantuml>`_ is installed, activated and has
a working configuration.

If the configured output is **svg**, the diagram elements are linked to the location of their definition.

0 comments on commit 84f9f22

Please sign in to comment.