Skip to content

Commit

Permalink
Merge pull request #361 from melexis/fix-crash-rel-to-str
Browse files Browse the repository at this point in the history
Clarify error about incomplete traceability_relationship_to_string
  • Loading branch information
Letme authored Oct 27, 2023
2 parents 7706ed2 + 5ce0eea commit 4b83986
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 39 deletions.
6 changes: 2 additions & 4 deletions mlx/directives/item_directive.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,13 @@ def _list_targets_for_relation(self, relation, targets, dl_node, app):
dl_node (nodes.definition_list): Definition list of the item.
app: Sphinx's application object to use.
"""
env = app.builder.env
li_node = nodes.definition_list_item()
dt_node = nodes.term()
if relation in app.config.traceability_relationship_to_string:
relstr = app.config.traceability_relationship_to_string[relation]
else:
report_warning('Traceability: relation {rel} cannot be translated to string'
.format(rel=relation),
env.docname, self.line)
report_warning(f'Traceability: relation {relation} cannot be translated to string',
docname=self['document'], lineno=self['line'])
relstr = relation
dt_node.append(nodes.Text(relstr))
li_node.append(dt_node)
Expand Down
2 changes: 1 addition & 1 deletion mlx/traceability.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def initialize_environment(app):
undefined_stringifications = all_relationships.difference(app.config.traceability_relationship_to_string)
if undefined_stringifications:
raise TraceabilityException(f"Relationships {undefined_stringifications!r} are missing from configuration "
"variable `traceability_relationships`")
"variable 'traceability_relationship_to_string'")

app.config.traceability_checklist['has_checklist_items'] = False
add_checklist_attribute(app.config.traceability_checklist,
Expand Down
73 changes: 39 additions & 34 deletions tests/directives/test_item_directive.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from unittest import TestCase
from unittest.mock import Mock, MagicMock
import logging

from docutils import nodes
from sphinx.application import Sphinx
from sphinx.builders.latex import LaTeXBuilder
from sphinx.builders.html import StandaloneHTMLBuilder
Expand All @@ -13,6 +15,8 @@

from parameterized import parameterized

LOGGER = logging.getLogger()


def raise_no_uri(*args, **kwargs):
raise NoUri
Expand All @@ -31,15 +35,22 @@ def setUp(self):
self.item.node = self.node
self.app.config = Mock()
self.app.config.traceability_hyperlink_colors = {}

def test_make_internal_item_ref_no_caption(self):
mock_builder = MagicMock(spec=StandaloneHTMLBuilder)
mock_builder.link_suffix = '.html'
self.collection = TraceableCollection()
self.collection.add_item(self.item)

def init_builder(self, spec=StandaloneHTMLBuilder):
mock_builder = MagicMock(spec=spec)
if spec == StandaloneHTMLBuilder:
mock_builder.link_suffix = '.html'
else:
mock_builder.get_relative_uri = Mock(side_effect=raise_no_uri)
mock_builder.env = BuildEnvironment(self.app)
self.app.builder = mock_builder
self.app.builder.env.traceability_collection = TraceableCollection()
self.app.builder.env.traceability_collection = self.collection
self.app.builder.env.traceability_ref_nodes = {}
self.app.builder.env.traceability_collection.add_item(self.item)

def test_make_internal_item_ref_no_caption(self):
self.init_builder()
p_node = self.node.make_internal_item_ref(self.app, self.node['id'])
ref_node = p_node.children[0]
em_node = ref_node.children[0]
Expand All @@ -54,13 +65,7 @@ def test_make_internal_item_ref_no_caption(self):
self.assertNotIn('onlycaptions', cache)

def test_make_internal_item_ref_show_caption(self):
mock_builder = MagicMock(spec=StandaloneHTMLBuilder)
mock_builder.link_suffix = '.html'
mock_builder.env = BuildEnvironment(self.app)
self.app.builder = mock_builder
self.app.builder.env.traceability_collection = TraceableCollection()
self.app.builder.env.traceability_ref_nodes = {}
self.app.builder.env.traceability_collection.add_item(self.item)
self.init_builder()
self.item.caption = 'caption text'
p_node = self.node.make_internal_item_ref(self.app, self.node['id'])
ref_node = p_node.children[0]
Expand All @@ -75,13 +80,7 @@ def test_make_internal_item_ref_show_caption(self):
self.assertEqual(p_node, cache['default'][f'{self.node["document"]}.html'])

def test_make_internal_item_ref_only_caption(self):
mock_builder = MagicMock(spec=StandaloneHTMLBuilder)
mock_builder.link_suffix = '.html'
mock_builder.env = BuildEnvironment(self.app)
self.app.builder = mock_builder
self.app.builder.env.traceability_collection = TraceableCollection()
self.app.builder.env.traceability_ref_nodes = {}
self.app.builder.env.traceability_collection.add_item(self.item)
self.init_builder()
self.item.caption = 'caption text'
self.node['nocaptions'] = True
self.node['onlycaptions'] = True
Expand All @@ -100,13 +99,7 @@ def test_make_internal_item_ref_only_caption(self):
self.assertEqual(p_node, cache['onlycaptions'][f'{self.node["document"]}.html'])

def test_make_internal_item_ref_hide_caption_html(self):
mock_builder = MagicMock(spec=StandaloneHTMLBuilder)
mock_builder.link_suffix = '.html'
mock_builder.env = BuildEnvironment(self.app)
self.app.builder = mock_builder
self.app.builder.env.traceability_collection = TraceableCollection()
self.app.builder.env.traceability_ref_nodes = {}
self.app.builder.env.traceability_collection.add_item(self.item)
self.init_builder()
self.item.caption = 'caption text'
self.node['nocaptions'] = True
p_node = self.node.make_internal_item_ref(self.app, self.node['id'])
Expand All @@ -124,13 +117,7 @@ def test_make_internal_item_ref_hide_caption_html(self):
self.assertEqual(p_node, cache['nocaptions'][f'{self.node["document"]}.html'])

def test_make_internal_item_ref_hide_caption_latex(self):
mock_builder = MagicMock(spec=LaTeXBuilder)
mock_builder.get_relative_uri = Mock(side_effect=raise_no_uri)
mock_builder.env = BuildEnvironment(self.app)
self.app.builder = mock_builder
self.app.builder.env.traceability_collection = TraceableCollection()
self.app.builder.env.traceability_ref_nodes = {}
self.app.builder.env.traceability_collection.add_item(self.item)
self.init_builder(spec=LaTeXBuilder)
self.item.caption = 'caption text'
self.node['nocaptions'] = True
p_node = self.node.make_internal_item_ref(self.app, self.node['id'])
Expand All @@ -154,3 +141,21 @@ def test_make_internal_item_ref_hide_caption_latex(self):
def test_is_relation_external(self, relation_name, expected):
external = self.node.is_relation_external(relation_name)
self.assertEqual(external, expected)

def test_item_node_replacement(self):
self.collection.add_relation_pair('depends_on', 'impacts_on')
# leaving out depends_on to test warning
self.app.config.traceability_relationship_to_string = {'impacts_on': 'Impacts on'}

target_item = TraceableItem('target_id')
self.collection.add_item(target_item)
self.collection.add_relation(self.item.identifier, 'depends_on', target_item.identifier)

with self.assertLogs(LOGGER, logging.DEBUG) as c_m:
self.node.parent = nodes.container()
self.node.parent.append(self.node)
self.node.perform_replacement(self.app, self.collection)

warning = "WARNING:sphinx.mlx.traceability_exception:Traceability: relation depends_on cannot be translated "\
"to string"
self.assertEqual(c_m.output, [warning])

0 comments on commit 4b83986

Please sign in to comment.