Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Needs warnings extended with all needs #1248

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a81dcb2
added test case
PhilipPartsch Aug 27, 2024
4751dd2
Merge branch 'useblocks:master' into needs_warnings_extended_with_all…
PhilipPartsch Aug 27, 2024
18cc8f0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 27, 2024
725370b
fixed existing tests to cover new test data
PhilipPartsch Aug 27, 2024
dadf9e3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 27, 2024
eb1f916
enable new warning with use of all needs
PhilipPartsch Aug 27, 2024
84b3f3e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 27, 2024
dfc88e6
change process_warnings to support all needs as parameter
PhilipPartsch Aug 27, 2024
327ded7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 27, 2024
fadf1ca
enhance documentation
PhilipPartsch Aug 27, 2024
1371f78
Merge branch 'master' into needs_warnings_extended_with_all_needs
PhilipPartsch Oct 17, 2024
608e090
changed test_needs_warning.py to cover new created test output
PhilipPartsch Oct 17, 2024
84d39a4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 17, 2024
0e65ade
added test_needs_warning.py missed comma
PhilipPartsch Oct 17, 2024
9f8ff4c
removed test_needs_warning.py wrongly merged lines
PhilipPartsch Oct 17, 2024
2391bca
Hanlde call-arg for mypy in warnings.py
PhilipPartsch Oct 17, 2024
9188455
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 17, 2024
41a9266
Update warnings.py
PhilipPartsch Oct 17, 2024
9e902b8
Update warnings.py fixed mypy postition
PhilipPartsch Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 63 additions & 24 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ This would allow Sphinx to perform incremental builds which are much faster as c
# conf.py

# Defining one or more functions in conf.py is fine
def my_custom_warning(need, log):
def my_custom_warning(need, log, needs):
# some checks
return False

Expand Down Expand Up @@ -1365,30 +1365,64 @@ This will handle **all warnings** as exceptions.

.. code-block:: python

# conf.py

# Defining one or more functions in conf.py is fine
def my_custom_warning_check(need, log):
if need["status"] == "open":
log.info(f"{need['id']} status must not be 'open'.")
return True
return False

def custom_warning_multi_needs(need, log, needs):
# need is closed, but linked need is still open.
# This is not allowed by this rule.
return_code: bool = False
if need["status"] in [
"closed",
"done",
]:
for linked_need in need["depend"]:
if needs[linked_need]["status"] not in [
"closed",
"done",
]:
return_code = True

return return_code

needs_warnings = {
# req need must not have an empty status field
'req_with_no_status': "type == 'req' and not status",
# req need must not have an empty status field
'req_with_no_status': "type == 'req' and not status",

# status must be open or closed
'invalid_status' : "status not in ['open', 'closed']",
# status must be open or closed
'invalid_status' : "status not in ['open', 'closed']",

# user defined filter code function
'type_match': my_custom_warning_check,
# This assignment will deactivate incremental build support inside Sphinx and
# can create an unpickable configuration warning.
# user defined filter code function
'type_match': my_custom_warning_check,
}

# Better, register all warnings via Sphinx-Needs API. In all cases avoid to double definition of filters.
from sphinx_needs.api.configuration import add_warning
def setup(app):
#add_warning(app, "req_with_no_status", "type == 'req' and not status"
#add_warning(app, "invalid_status", "status not in ['open', 'closed']"
#add_warning(app, "type_match", my_custom_warning_check
add_warning(app, "depend_need_not_closed", custom_warning_multi_needs)

``needs_warnings`` must be a dictionary.
The **dictionary key** is used as identifier and gets printed in log outputs.
The **value** must be a valid filter string or a custom defined filter code function and defines a *not allowed behavior*.

So use the filter string or filter code function to define how needs are not allowed to be configured/used.
The defined filter code function must return ``True`` or ``False``.
The defined filter string and filter code function must return:

* ``True`` - Warning shall be raised
* ``False`` - No warning needed



.. warning::

Expand All @@ -1399,22 +1433,27 @@ Example output:

.. code-block:: text

...
looking for now-outdated files... none found
pickling environment... done
checking consistency... WARNING: Sphinx-Needs warnings were raised. See console / log output for details.

Checking Sphinx-Needs warnings
type_check: passed
invalid_status: failed
failed needs: 11 (STYLE_005, EX_ROW_1, EX_ROW_3, copy_2, clv_1, clv_2, clv_3, clv_4, clv_5, T_C3893, R_AD4A0)
used filter: status not in ["open", "in progress", "closed", "done"] and status is not None

type_match: failed
failed needs: 1 (TC_001)
used filter: <function my_custom_warning_check at 0x7faf3fbcd1f0>
done
...
...
looking for now-outdated files... none found
pickling environment... done
checking consistency... WARNING: Sphinx-Needs warnings were raised. See console / log output for details.

Checking Sphinx-Needs warnings
type_check: passed
invalid_status: failed
failed needs: 11 (STYLE_005, EX_ROW_1, EX_ROW_3, copy_2, clv_1, clv_2, clv_3, clv_4, clv_5, T_C3893, R_AD4A0)
used filter: status not in ["open", "in progress", "closed", "done"] and status is not None

type_match: failed
failed needs: 1 (TC_001)
used filter: <function my_custom_warning_check at 0x7faf3fbcd1f0>

depend_need_not_closed: failed
failed needs: 1 (TC_MULTI2)
used filter: <function custom_warning_multi_needs at 0x7faf3fbcd6f0>

done
...

Due to the nature of Sphinx logging, a sphinx-warning may be printed wherever in the log.

Expand Down
11 changes: 9 additions & 2 deletions sphinx_needs/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

from __future__ import annotations

from inspect import signature

from sphinx.application import Sphinx
from sphinx.util import logging

Expand Down Expand Up @@ -72,8 +74,13 @@ def process_warnings(app: Sphinx, exception: Exception | None) -> None:
# custom defined filter code used from conf.py
result = []
for need in needs_view.values():
if warning_filter(need, logger):
result.append(need)
sig = signature(warning_filter)
if len(sig.parameters) >= 3:
if warning_filter(need, logger, needs_view): # type: ignore[call-arg]
result.append(need)
else:
if warning_filter(need, logger):
result.append(need)
else:
log_warning(logger, f"Unknown needs warnings filter {warning_filter}!")

Expand Down
27 changes: 27 additions & 0 deletions tests/doc_test/doc_needs_warnings/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@
},
]

needs_extra_links = [
{
"option": "depend",
"incoming": "depended",
"outgoing": "depends on",
},
]

needs_external_needs = [
{
"base_url": "http://my_company.com/docs/v1/",
Expand All @@ -59,6 +67,24 @@ def custom_warning_func(need, log):
return need["status"] == "example_3"


def custom_warning_multi_needs(need, log, needs):
# need is closed, but linked need is still open.
# This is not allowed by this rule.
return_code: bool = False
if need["status"] in [
"closed",
"done",
]:
for linked_need in need["depend"]:
if needs[linked_need]["status"] not in [
"closed",
"done",
]:
return_code = True

return return_code


def setup(app):
from sphinx_needs.api.configuration import add_warning

Expand All @@ -69,6 +95,7 @@ def setup(app):
"invalid_status",
"status not in ['open', 'closed', 'done', 'example_2', 'example_3']",
)
add_warning(app, "depend_need_not_closed", custom_warning_multi_needs)


# Needs option to set True or False to raise sphinx-warning for each not passed warning check
Expand Down
9 changes: 9 additions & 0 deletions tests/doc_test/doc_needs_warnings/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,12 @@ TEST DOCUMENT NEEDS WARNINGS
.. test:: Test example 3
:id: TC_003
:status: example_3

.. test:: Multi needs 1
:id: TC_MULTI1
:status: open

.. test:: Multi needs 2
:id: TC_MULTI2
:status: closed
:depend: TC_MULTI1
5 changes: 4 additions & 1 deletion tests/test_needs_warning.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ def test_needs_warnings(test_app):
"WARNING: invalid_status: failed",
"\t\tfailed needs: 2 (SP_TOO_001, US_63252)",
"\t\tused filter: status not in ['open', 'closed', 'done', 'example_2', 'example_3'] [needs.warnings]",
"WARNING: depend_need_not_closed: failed",
"\t\tfailed needs: 1 (TC_MULTI2)",
"\t\tused filter: custom_warning_multi_needs [needs.warnings]",
"WARNING: type_match: failed",
"\t\tfailed needs: 1 (TC_001)",
"\t\tfailed needs: 2 (TC_001, TC_MULTI1)",
"\t\tused filter: my_custom_warning_check [needs.warnings]",
]

Expand Down