Skip to content

Commit

Permalink
Merge pull request #389 from SteinHeselmans/master
Browse files Browse the repository at this point in the history
Add option to item-directive to hide specific relation-types
  • Loading branch information
JasperCraeghs authored Dec 18, 2024
2 parents e513981 + 4cde1d5 commit a21db07
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 2 deletions.
13 changes: 12 additions & 1 deletion doc/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Documentation items can be defined using the *item* directive, specifying:
:status: Approved
:validated_by: ITEST-MY_FIRST_INTEGRATION_TEST
:ext_polarion_reference: project_x:workitem_y
:hidetype: validated_by
:nocaptions:
According to the Polarion reference, the software **shall** implement my first requirement.
Expand All @@ -74,7 +75,17 @@ The relations to other documentation items can be specified as:
ITEST-MY_SECOND_INTEGRATION_TEST
The output will contain hyperlinks to all related items. By default, the caption for the target item is displayed for
each of these related items. With the option *nocaptions* these captions can be omitted.
each of these related items.

:hidetype: *optional*, *multiple arguments (space-separated)*

A space-separated list of relation types. By default, the rendered item definition displays all relations to other items
in a list below the item name (id). The relation types given to this option will be omitted from this list.
It does not affect how the item is rendered in other directives, e.g. item-matrix.

:nocaptions: *optional*, *flag*

Omits the caption from the rendered item definition.

.. _adding_relations:

Expand Down
12 changes: 11 additions & 1 deletion mlx/traceability/directives/item_directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def _process_relationships(self, *args):
All targets get naturally sorted per relationship.
"""
for rel, targets in self._item.all_relations:
self._list_targets_for_relation(rel, targets, *args)
if rel not in self['hidetype']:
self._list_targets_for_relation(rel, targets, *args)

def _list_targets_for_relation(self, relation, targets, dl_node, app):
""" Add a list with all targets for a specific relation to the given definition list.
Expand Down Expand Up @@ -129,6 +130,7 @@ class ItemDirective(TraceableBaseDirective):
option_spec = {
'class': directives.class_option,
'nocaptions': directives.flag,
'hidetype': directives.unchanged,
}
# Content allowed
has_content = True
Expand All @@ -149,10 +151,18 @@ def run(self):
item_node['classes'].append('collapse')
if 'class' in self.options:
item_node['classes'].extend(self.options.get('class'))
self.process_options(
item_node,
{
'hidetype': {'default': []},
},
)
item = self._store_item_info(target_id, env)
if item is None:
return []

self.check_relationships(item_node['hidetype'], env)

# Custom callback for modifying items
if app.config.traceability_callback_per_item:
app.config.traceability_callback_per_item(target_id, env.traceability_collection)
Expand Down
1 change: 1 addition & 0 deletions tests/directives/test_item_directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def setUp(self):
self.node['document'] = 'some_doc'
self.node['id'] = 'some_id'
self.node['line'] = 1
self.node['hidetype'] = []
self.item = TraceableItem(self.node['id'])
self.item.set_location(self.node['document'], self.node['line'])
self.item.node = self.node
Expand Down
113 changes: 113 additions & 0 deletions tests/test_html.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import shutil
import tempfile
import textwrap
import unittest
import sphinx.cmd.build
import sphinx.cmd.quickstart
from pathlib import Path


class TestSphinx(unittest.TestCase):

@classmethod
def setUpClass(cls):
cls.doc_dir = Path(tempfile.mkdtemp())
cls.build_dir = cls.doc_dir / "_build"
cls.index_rst_path = cls.doc_dir / "index.rst"
cls.html_file = cls.build_dir / "index.html"
sphinx.cmd.quickstart.generate({
"path": cls.doc_dir,
"sep": False,
"project": "testdoc",
"author": "mlx.traceability contributors",
"version": "a",
"release": "a",
"language": "en",
"dot": "_",
"suffix": ".rst",
"master": "index",
"makefile": True,
"batchfile": False,
"extensions": ["mlx.traceability"],
}, silent=True)

cfg = r"""
traceability_render_relationship_per_item = True
traceability_relationships = {'my_relation': 'my_reverse_relation'}
traceability_relationship_to_string = {'my_relation': 'My relation',
'my_reverse_relation': 'My reverse relation'}
traceability_attributes = {}
traceability_attributes_sort = {}
"""

with open(cls.doc_dir / 'conf.py', 'a') as f:
f.write(textwrap.dedent(cfg))

@classmethod
def tearDownClass(cls):
shutil.rmtree(cls.doc_dir)

def build(self, builder="html"):
retcode = sphinx.cmd.build.main([
"-q",
"-b",
builder,
str(self.doc_dir),
str(self.build_dir),
])
self.assertEqual(retcode, 0)

def make_doc_with_rst(self, rst_content, **build_options):
with open(self.index_rst_path, "w") as f:
f.write(textwrap.dedent(rst_content))
self.build(**build_options)
with open(self.html_file, "r") as f:
return f.read()

def test_item_relation(self):
rst_content = r"""
.. item:: ITEM-A Description of item-a
.. item:: ITEM-B Description of item-b
:my_relation: ITEM-A
"""
content = self.make_doc_with_rst(rst_content)
assert 'My relation' in content
assert 'My reverse relation' in content

def test_item_relation_hide_forward(self):
rst_content = r"""
.. item:: ITEM-A Description of item-a
.. item:: ITEM-B Description of item-b
:my_relation: ITEM-A
:hidetype: my_relation
"""
content = self.make_doc_with_rst(rst_content)
assert 'My relation' not in content
assert 'My reverse relation' in content

def test_item_relation_hide_reverse(self):
rst_content = r"""
.. item:: ITEM-A Description of item-a
:hidetype: my_reverse_relation
.. item:: ITEM-B Description of item-b
:my_relation: ITEM-A
"""
content = self.make_doc_with_rst(rst_content)
assert 'My relation' in content
assert 'My reverse relation' not in content

def test_item_relation_hide_both(self):
rst_content = r"""
.. item:: ITEM-A Description of item-a
:hidetype: my_reverse_relation
.. item:: ITEM-B Description of item-b
:my_relation: ITEM-A
:hidetype: my_relation
"""
content = self.make_doc_with_rst(rst_content)
assert 'My relation' not in content
assert 'My reverse relation' not in content

0 comments on commit a21db07

Please sign in to comment.