Skip to content

Commit

Permalink
Merge pull request #143 from melexis/filter-poly-defects
Browse files Browse the repository at this point in the history
Exclude Polyspace defects with status "Not a Defect" or "Justified"; Add substitution of env variables for min/max possible for Robot and Polyspace
  • Loading branch information
JasperCraeghs authored Jul 25, 2024
2 parents 2831527 + cd52002 commit a561a37
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 267 deletions.
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,17 @@ For example, "run-time check" is the family of Code Prover and "defect" is the f
The value of that key is a list, which contains the name of the column to check as a key and
the value of that column to check together with ``min`` and ``max`` values.

All results with one of the following statuses are discarded altogether:

- Justified
- Not a Defect

These statuses indicate that you have given due consideration and justified that result, as described
in `Polyspace's documentation about results`_.
The status "No Action Planned" is not treated differently because this is the default status for annotations.

.. _`Polyspace's documentation about results`: https://nl.mathworks.com/help/polyspace_access/ug/fix-or-comment-polyspace-results-web-browser.html

Example Checks
^^^^^^^^^^^^^^

Expand Down
30 changes: 16 additions & 14 deletions src/mlx/warnings/polyspace_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ def parse_config(self, config):
"'Family' column. These dicts need to consist 3 key-value pairs (Note: if 'min' or "
"'max' is not defined, it will get the default value of 0):\n"
"{\n <column_name>: <value_to_check>,\n min: <number>,\n max: <number>\n};"
f"got {column_name} as column_name and {check_value} as value_to_check"
f"got {column_name!r} as column_name and {check_value!r} as value_to_check"
)
for checker in self.checkers:
checker.cq_enabled = self.cq_enabled
Expand All @@ -179,8 +179,6 @@ def __init__(self, family_value, column_name, check_value, **kwargs):
family_value (str): The value to search for in the 'Family' column
column_name (str): The name of the column
check_value (str): The value to check in the column
minimum (int): The minimum amount the check_value can occur
maximum (int): The maximum amount the check_value can occur
"""
super().__init__(**kwargs)
self.family_value = family_value
Expand Down Expand Up @@ -243,7 +241,7 @@ def add_code_quality_finding(self, row):
if "line" in row:
finding["location"]["positions"]["begin"]["line"] = row["line"]
if "col" in row:
finding["location"]["positions"]["begin"]["column"] = row["line"]
finding["location"]["positions"]["begin"]["column"] = row["col"]
finding["description"] = description
exclude = ("new", "status", "severity", "comment", "key")
row_without_key = [value for key, value in row.items() if key not in exclude]
Expand All @@ -258,13 +256,17 @@ def check(self, content):
content (dict): The row of the TSV file
'''
if content[self.column_name].lower() == self.check_value:
tab_sep_string = "\t".join(content.values())
if not self._is_excluded(tab_sep_string):
self.count = self.count + 1
self.counted_warnings.append('family: {} -> {}: {}'.format(
self.family_value,
self.column_name,
self.check_value
))
if self.cq_enabled and content["color"].lower() != "green":
self.add_code_quality_finding(content)
if content["status"].lower() in ["not a defect", "justified"]:
self.print_when_verbose("Excluded row {!r} because the status is 'Not a defect' or 'Justified'"
.format(content))
else:
tab_sep_string = "\t".join(content.values())
if not self._is_excluded(tab_sep_string):
self.count = self.count + 1
self.counted_warnings.append('family: {} -> {}: {}'.format(
self.family_value,
self.column_name,
self.check_value
))
if self.cq_enabled and content["color"].lower() != "green":
self.add_code_quality_finding(content)
23 changes: 0 additions & 23 deletions src/mlx/warnings/warnings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
import errno
import glob
import json
import os
import subprocess
import sys
from importlib.metadata import distribution
from pathlib import Path
from string import Template

from ruamel.yaml import YAML

Expand All @@ -23,26 +21,6 @@
__version__ = distribution('mlx.warnings').version


def substitute_envvar(checker_config, keys):
"""Modifies configuration for checker in-place, resolving any environment variables for ``keys``
Args:
checker_config (dict): Configuration for a specific WarningsChecker
keys (set): Set of keys to process the value of
Raises:
WarningsConfigError: Failed to find an environment variable
"""
for key in keys:
if key in checker_config and isinstance(checker_config[key], str):
template_obj = Template(checker_config[key])
try:
checker_config[key] = template_obj.substitute(os.environ)
except KeyError as err:
raise WarningsConfigError(f"Failed to find environment variable {err} for configuration value {key!r}")\
from None


class WarningsPlugin:

def __init__(self, verbose=False, config_file=None, cq_enabled=False):
Expand Down Expand Up @@ -229,7 +207,6 @@ def config_parser(self, config):
try:
checker_config = config[checker.name]
if bool(checker_config['enabled']):
substitute_envvar(checker_config, {'min', 'max'})
self.activate_checker(checker)
checker.parse_config(checker_config)
print("Config parsing for {name} completed".format(name=checker.name))
Expand Down
21 changes: 21 additions & 0 deletions src/mlx/warnings/warnings_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@
from .exceptions import WarningsConfigError


def substitute_envvar(checker_config, keys):
"""Modifies configuration for checker inplace, resolving any environment variables for ``keys``
Args:
checker_config (dict): Configuration for a specific WarningsChecker
keys (set): Set of keys to process the value of
Raises:
WarningsConfigError: Failed to find an environment variable
"""
for key in keys:
if key in checker_config and isinstance(checker_config[key], str):
template_obj = Template(checker_config[key])
try:
checker_config[key] = template_obj.substitute(os.environ)
except KeyError as err:
raise WarningsConfigError(f"Failed to find environment variable {err} for configuration value {key!r}")\
from None


class WarningsChecker:
name = 'checker'

Expand Down Expand Up @@ -156,6 +176,7 @@ def print_when_verbose(self, message):
print(message)

def parse_config(self, config):
substitute_envvar(config, {'min', 'max'})
self.maximum = int(config['max'])
self.minimum = int(config['min'])
self.add_patterns(config.get("exclude"), self.exclude_patterns)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_in/config_example_polyspace_exclude.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
"run-time check": [
{
"color": "red",
"min": 0,
"max": 0
"min": "$MIN_POLY_WARNINGS",
"max": "${MAX_POLY_WARNINGS}"
},
{
"color": "orange",
Expand Down
4 changes: 2 additions & 2 deletions tests/test_in/config_example_robot.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
},
{
"name": "b4d su1te name",
"min": 0,
"max": 0
"min": "$MIN_ROBOT_WARNINGS",
"max": "${MAX_ROBOT_WARNINGS}"
}
]
},
Expand Down
12 changes: 6 additions & 6 deletions tests/test_in/polyspace.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,28 @@ ID Family Group Color New Check Information Function File Status Severity Commen
22036 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset C4992326D32B4698C491 6 4
22065 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset C49953E693A45698C489 5 5
22035 Run-time Check Data flow Green no Non-initialized local variable dummy_function() dummy_file_name.c Unreviewed Unset C499232693A45698C491 5 6
21989 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Unreviewed Unset C4997327D32B4698C881 6 7
21989 Run-time Check Numerical Green no Overflow dummy_function() dummy_file_name.c Not a defect Unset C4997327D32B4698C881 6 7
19928 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 62C8B1F4CA9126336A 6 8
19962 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 62D8A9F4CA91263472 7 9
19962 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Not a defect Unset 62D8A9F4CA91263472 7 9
19526 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C899F4CA9126316A 7 10
19424 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62E489F4CA91263262 6 11
19429 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62E4A1F4CA91263162 6 2
19429 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Justified Unset 62E4A1F4CA91263162 6 2
19442 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62C091F4CA91263170 7 3
19450 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Unreviewed Unset 62C091F4CA91263170 7 3
19450 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.h Justified Unset 62C091F4CA91263170 7 3
19375 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C089F4CA9126326C 8 4
19378 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C091F4CA9126316E 8 5
19377 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C091F4CA9126336A 7 6
19357 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263368 7 7
19352 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263760 8 8
19351 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263862 8 9
19351 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Justified Unset 66C8A9F4CA91263862 8 9
19355 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8A9F4CA91263962 9 10
19354 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset CC9153E995234C62C091 9 11
19358 Run-time Check Numerical Orange no Overflow Origin: Path related issue dummy_function() dummy_file_name.c Unreviewed Unset CC9153E995234C62C0C1 8 3
19360 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8B1F4CA91263262 8 4
19349 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8C1F4CA91263262 9 5
19345 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8C1F4CA91263470 9 6
19344 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66C8C1F4CA91263572 10 7
19339 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66CC91F4CA91263464 10 8
19339 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Not a defect Unset 66CC91F4CA91263464 10 8
19338 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66CC91F4CA91263468 9 9
19336 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset 66CC91F4CA91263970 9 10
19335 Run-time Check Numerical Orange no Overflow dummy_function() dummy_file_name.c Unreviewed Unset CC9923E995234C62C0C9 10 11
Expand Down
Loading

0 comments on commit a561a37

Please sign in to comment.