From 96ddb075580617c04e567bbcf1ba792d3e7f673d Mon Sep 17 00:00:00 2001 From: jce <28319872+JasperCraeghs@users.noreply.github.com> Date: Tue, 17 May 2022 10:45:38 +0200 Subject: [PATCH 1/7] Allow a second callback function to inspect items after all directives have been processed --- mlx/directives/item_directive.py | 2 ++ mlx/traceability.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mlx/directives/item_directive.py b/mlx/directives/item_directive.py index 34b8d7d1..629dd1bf 100644 --- a/mlx/directives/item_directive.py +++ b/mlx/directives/item_directive.py @@ -20,6 +20,8 @@ def perform_replacement(self, app, collection): """ self._item = collection.get_item(self['id']) item_id = self._item.get_id() + if app.config.traceability_inspect_item: + app.config.traceability_inspect_item(item_id, collection) top_node = self.create_top_node(item_id, app=app) dl_node = nodes.definition_list() if app.config.traceability_render_attributes_per_item: diff --git a/mlx/traceability.py b/mlx/traceability.py index 1b0eff61..d416b89d 100644 --- a/mlx/traceability.py +++ b/mlx/traceability.py @@ -473,9 +473,12 @@ def setup(app): # Configuration for exporting collection to json app.add_config_value('traceability_json_export_path', None, 'env') - # Configuration for adapting items through a callback + # Configuration for adapting items through a callback while processing the ``item`` directives app.add_config_value('traceability_callback_per_item', None, 'env') + # Configuration for inspecting items through a callback after all directives have been processed + app.add_config_value('traceability_inspect_item', None, 'env') + # Create default attributes dictionary. Can be customized in conf.py app.add_config_value( 'traceability_attributes', From 4d3f20078cdde5287eb4c19816e2d15eca0937d5 Mon Sep 17 00:00:00 2001 From: jce <28319872+JasperCraeghs@users.noreply.github.com> Date: Tue, 17 May 2022 10:53:21 +0200 Subject: [PATCH 2/7] Demonstrate use case of traceability_inspect_item callback function --- doc/conf.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/doc/conf.py b/doc/conf.py index 99df47a4..965c3f05 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -18,6 +18,7 @@ from collections import OrderedDict import mlx.traceability +from mlx.traceability import report_warning from pkg_resources import get_distribution pkg_version = get_distribution('mlx.traceability').version @@ -347,12 +348,38 @@ traceability_json_export_path = '_build/exported_items.json' def traceability_callback_per_item(name, collection): + """Callback function called when an item-directive is being processed + + Note: attributes, relationships and content (body) of the item can be modified. + + Args: + name (str): Item ID + collection (TraceableCollection): Storage class for collection of traceable items + """ if name == 'r001': item = collection.get_item(name) content_str = item.get_content() content_str += '\n\nThis line was added by ``traceability_callback_per_item`` and is parsed as |RST| syntax.' item.set_content(content_str) + +def traceability_inspect_item(name, collection): + """Callback function called when all directives have been processed + + Note: the item cannot be modified, only inspected. At this stage of the documentation build, all directives, e.g. + attribute-link and item-link, have been processed and any gaps in your documentation can be exposed by reporting + a warning. + + Args: + name (str): Item ID + collection (TraceableCollection): Storage class for collection of traceable items + """ + if name.startswith('CL-'): + item = collection.get_item(name) + if 'checked' not in item.attributes: + report_warning(f"traceability_inspect_item: Checklist item {name!r} is missing the 'checked' attribute.") + + rst_epilog = ".. |RST| replace:: :abbr:`RST (reStructuredText)`" # OrderedDict([('regex', (default, :hover+:active, :visited)), ...]) From e8a3498e29d6df4b51500448990bd907eb5fb1d1 Mon Sep 17 00:00:00 2001 From: jce <28319872+JasperCraeghs@users.noreply.github.com> Date: Tue, 17 May 2022 10:53:45 +0200 Subject: [PATCH 3/7] Allow 1 additional warning, reported by traceability_inspect_item --- tox.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index f9c4bb78..808d2a90 100644 --- a/tox.ini +++ b/tox.ini @@ -73,8 +73,8 @@ whitelist_externals = tee mlx-warnings commands= - mlx-warnings --sphinx --exact-warnings 22 --command make -C doc html - mlx-warnings --sphinx --exact-warnings 22 --command make -C doc latexpdf + mlx-warnings --sphinx --exact-warnings 23 --command make -C doc html + mlx-warnings --sphinx --exact-warnings 23 --command make -C doc latexpdf [testenv:sphinx-latest] deps= @@ -87,8 +87,8 @@ whitelist_externals = tee mlx-warnings commands= - mlx-warnings --sphinx --exact-warnings 22 --command make -C doc html - mlx-warnings --sphinx --exact-warnings 22 --command make -C doc latexpdf + mlx-warnings --sphinx --exact-warnings 23 --command make -C doc html + mlx-warnings --sphinx --exact-warnings 23 --command make -C doc latexpdf [testenv:coveralls] deps = From 8457f6a5c3462892211660a76fd9b37ee7a7b2bd Mon Sep 17 00:00:00 2001 From: jce <28319872+JasperCraeghs@users.noreply.github.com> Date: Tue, 17 May 2022 11:20:37 +0200 Subject: [PATCH 4/7] Document traceability_inspect_item --- doc/conf.py | 21 ++++++++++---------- doc/configuration.rst | 45 +++++++++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 965c3f05..92f00494 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -348,13 +348,14 @@ traceability_json_export_path = '_build/exported_items.json' def traceability_callback_per_item(name, collection): - """Callback function called when an item-directive is being processed + """Callback function called when an item-directive is being processed. - Note: attributes, relationships and content (body) of the item can be modified. + Note: attributes, relationships and content (body) of the item can be modified. Sphinx processes each directive + in turn, so attributes and relationships added or modified by other directives may not have been processed yet. Args: - name (str): Item ID - collection (TraceableCollection): Storage class for collection of traceable items + name (str): Name (id) of the item currently being parsed + collection (TraceableCollection): Collection of all items that have been parsed so far """ if name == 'r001': item = collection.get_item(name) @@ -364,15 +365,15 @@ def traceability_callback_per_item(name, collection): def traceability_inspect_item(name, collection): - """Callback function called when all directives have been processed + """Callback function called when an item-directive is being rendered. - Note: the item cannot be modified, only inspected. At this stage of the documentation build, all directives, e.g. - attribute-link and item-link, have been processed and any gaps in your documentation can be exposed by reporting - a warning. + Note: the item should not be modified, only inspected. At this stage of the documentation build, all directives, + e.g. attribute-link and item-link, have been processed and any gaps in your documentation can be exposed by + reporting a warning. Args: - name (str): Item ID - collection (TraceableCollection): Storage class for collection of traceable items + name (str): Name (id) of the item currently being parsed + collection (TraceableCollection): Collection of all items that have been parsed so far """ if name.startswith('CL-'): item = collection.get_item(name) diff --git a/doc/configuration.rst b/doc/configuration.rst index cdda8814..344aef61 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -270,32 +270,55 @@ The actual content (RST content with images, formulas, etc) of the item is curre Callback per item (advanced) ---------------------------- +Callback to modify item +======================= + The plugin allows parsing and modifying documentation objects *behind the scenes* using a callback. The callback has this prototype: .. code-block:: python def traceability_callback_per_item(name, collection): - ''' Custom callback on items + """Callback function called when an item-directive is being processed. + + Note: attributes, relationships and content (body) of the item can be modified. Sphinx processes each directive + in turn, so attributes and relationships added or modified by other directives may not have been processed yet. Args: name (str): Name (id) of the item currently being parsed collection (TraceableCollection): Collection of all items that have been parsed so far - ''' + """ pass -The callback is executed while parsing the documentation item from your rst-file. Note that not all items are -available at the time this callback executes, the *collection* parameter is a growing collection of documentation -objects. +.. note:: + + The callback is executed while parsing the documentation item from your RST file. Note that not all items are + available at the time this callback executes, the *collection* parameter is a growing collection of documentation + objects. -.. _traceability_no_callback: +Callback to inspect item +======================== -Example of no callback per item -=============================== +To overcome the limitation of ``traceability_callback_per_item`` (see note above), a secondary callback function can be +defined. This function will be called when *rendering* each ``item``-directive. At that moment, all other directive +types, e.g. ``attribute-link`` and ``item-link``, will have been processed. You can use this callback function to detect +and warn about any gaps in your documentation but you shouldn't use it to make any modifications. +The callback has this prototype: .. code-block:: python - traceability_callback_per_item = None + def traceability_inspect_item(name, collection): + """Callback function called when an item-directive is being rendered. + + Note: the item should not be modified, only inspected. At this stage of the documentation build, all directives, + e.g. attribute-link and item-link, have been processed and any gaps in your documentation can be exposed by + reporting a warning. + + Args: + name (str): Name (id) of the item currently being parsed + collection (TraceableCollection): Collection of all items that have been parsed so far + """ + pass .. _traceability_optional_mandatory: @@ -303,7 +326,8 @@ Example of requiring certain attributes on an item ================================================== The callback function can modify traceable items, e.g. add attributes. In this example it reports a warning -when the item doesn't have either the `functional` or `non-functional` attribute: +when the item doesn't have either the `functional` or `non-functional` attribute defined *at the time its +``item``-directive is being processed*: .. code-block:: python @@ -316,6 +340,7 @@ when the item doesn't have either the `functional` or `non-functional` attribute "adding 'functional'".format(name), docname=item.docname, lineno=item.lineno) item.add_attribute('functional', '') + .. _traceability_config_link_colors: ------------------------------ From d21fc94bdc5f51a11d9f72056de7138137e75926 Mon Sep 17 00:00:00 2001 From: jce <28319872+JasperCraeghs@users.noreply.github.com> Date: Tue, 17 May 2022 11:24:47 +0200 Subject: [PATCH 5/7] Replace f-string formatting for Python 3.5 support --- doc/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 92f00494..c4c953ea 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -378,7 +378,8 @@ def traceability_inspect_item(name, collection): if name.startswith('CL-'): item = collection.get_item(name) if 'checked' not in item.attributes: - report_warning(f"traceability_inspect_item: Checklist item {name!r} is missing the 'checked' attribute.") + report_warning("traceability_inspect_item: Checklist item {!r} is missing the 'checked' attribute." + .format(name)) rst_epilog = ".. |RST| replace:: :abbr:`RST (reStructuredText)`" From 8c7c74c30e607424188eb3ad7c5534b4724d65cf Mon Sep 17 00:00:00 2001 From: jce <28319872+JasperCraeghs@users.noreply.github.com> Date: Tue, 17 May 2022 11:56:39 +0200 Subject: [PATCH 6/7] Call callback function 'traceability_inspect_item' after rendering the item as it shouldn't be used to modify the item --- mlx/directives/item_directive.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mlx/directives/item_directive.py b/mlx/directives/item_directive.py index 629dd1bf..3aec7bad 100644 --- a/mlx/directives/item_directive.py +++ b/mlx/directives/item_directive.py @@ -20,8 +20,6 @@ def perform_replacement(self, app, collection): """ self._item = collection.get_item(self['id']) item_id = self._item.get_id() - if app.config.traceability_inspect_item: - app.config.traceability_inspect_item(item_id, collection) top_node = self.create_top_node(item_id, app=app) dl_node = nodes.definition_list() if app.config.traceability_render_attributes_per_item: @@ -32,6 +30,8 @@ def perform_replacement(self, app, collection): top_node.append(dl_node) # Note: content should be displayed during read of RST file, as it contains other RST objects self.replace_self(top_node) + if app.config.traceability_inspect_item: + app.config.traceability_inspect_item(item_id, collection) def _process_attributes(self, dl_node, app): """ Processes all attributes for the given item and adds the list of attributes to the given definition list. From 42676d558a07db3a81ea9be33b9ace95621c6ce6 Mon Sep 17 00:00:00 2001 From: jce <28319872+JasperCraeghs@users.noreply.github.com> Date: Tue, 17 May 2022 12:05:38 +0200 Subject: [PATCH 7/7] Warn user to not modify the collection of items --- doc/conf.py | 7 ++++--- doc/configuration.rst | 14 ++++++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index c4c953ea..f718ec35 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -367,9 +367,10 @@ def traceability_callback_per_item(name, collection): def traceability_inspect_item(name, collection): """Callback function called when an item-directive is being rendered. - Note: the item should not be modified, only inspected. At this stage of the documentation build, all directives, - e.g. attribute-link and item-link, have been processed and any gaps in your documentation can be exposed by - reporting a warning. + Warning: the item cannot not be modified, only inspected. + + Note: At this stage of the documentation build, all directives, e.g. attribute-link and item-link, + have been processed and any gaps in your documentation can be exposed by reporting a warning. Args: name (str): Name (id) of the item currently being parsed diff --git a/doc/configuration.rst b/doc/configuration.rst index 344aef61..5b540caa 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -302,7 +302,7 @@ Callback to inspect item To overcome the limitation of ``traceability_callback_per_item`` (see note above), a secondary callback function can be defined. This function will be called when *rendering* each ``item``-directive. At that moment, all other directive types, e.g. ``attribute-link`` and ``item-link``, will have been processed. You can use this callback function to detect -and warn about any gaps in your documentation but you shouldn't use it to make any modifications. +and warn about any gaps in your documentation but you cannot use it to make any modifications. The callback has this prototype: .. code-block:: python @@ -310,9 +310,10 @@ The callback has this prototype: def traceability_inspect_item(name, collection): """Callback function called when an item-directive is being rendered. - Note: the item should not be modified, only inspected. At this stage of the documentation build, all directives, - e.g. attribute-link and item-link, have been processed and any gaps in your documentation can be exposed by - reporting a warning. + Warning: the item cannot not be modified, only inspected. + + Note: At this stage of the documentation build, all directives, e.g. attribute-link and item-link, + have been processed and any gaps in your documentation can be exposed by reporting a warning. Args: name (str): Name (id) of the item currently being parsed @@ -320,6 +321,11 @@ The callback has this prototype: """ pass +.. warning:: + + The collection should not be modified, only inspected. Modifying the collection in this step can corrupt it without + triggering any warnings. + .. _traceability_optional_mandatory: Example of requiring certain attributes on an item