Software Design

Class Diagram

@startuml classes
set namespaceSeparator none
class "CoverityChecker" as mlx.warnings.regex_checker.CoverityChecker {
    checkers : dict
    count : int
    cq_default_path
    cq_description_template
    cq_findings
    name : str
    pattern
    check(content)
    parse_config(config)
    return_check_limits()
    return_count()
}
class "CoverityClassificationChecker" as mlx.warnings.regex_checker.CoverityClassificationChecker {
    SEVERITY_MAP : dict
    classification
    count
    cq_description_template
    logging_fmt : str
    name : str
    add_code_quality_finding(match)
    check(content)
}
class "DebugOnlyFilter" as mlx.warnings.warnings_checker.DebugOnlyFilter {
    filter(record: logging.LogRecord) -> bool
}
class "DoxyChecker" as mlx.warnings.regex_checker.DoxyChecker {
    name : str
    pattern
}
class "Finding" as mlx.warnings.code_quality.Finding {
    column
    description
    fingerprint
    fingerprints : dict
    line
    path
    severity
    to_dict()
}
class "JUnitChecker" as mlx.warnings.junit_checker.JUnitChecker {
    count
    name : str
    name_repr
    check(content)
    prepare_tree(root_input)
}
class "PolyspaceChecker" as mlx.warnings.polyspace_checker.PolyspaceChecker {
    checkers : list
    count : int
    cq_default_path
    cq_description_template
    cq_findings
    maximum
    minimum
    name : str
    check(content)
    parse_config(config)
    return_check_limits()
    return_count()
}
class "PolyspaceFamilyChecker" as mlx.warnings.polyspace_checker.PolyspaceFamilyChecker {
    check_value
    code_quality_severity : dict
    column_name
    count
    cq_description_template
    family_value
    logging_fmt : str
    name : str
    add_code_quality_finding(row)
    check(content)
}
class "RegexChecker" as mlx.warnings.regex_checker.RegexChecker {
    SEVERITY_MAP : dict
    count
    name : str
    pattern : NoneType
    add_code_quality_finding(match)
    check(content)
}
class "RobotChecker" as mlx.warnings.robot_checker.RobotChecker {
    checkers : list
    count : int
    logging_fmt : str
    maximum
    minimum
    name : str
    check(content)
    parse_config(config)
    return_check_limits()
    return_count()
}
class "RobotSuiteChecker" as mlx.warnings.robot_checker.RobotSuiteChecker {
    check_suite_name : bool
    is_valid_suite_name : bool
    logging_fmt : str
    name : str
    suite_name
    suite_name_repr
    check(content)
}
class "SphinxChecker" as mlx.warnings.regex_checker.SphinxChecker {
    name : str
    pattern
    sphinx_deprecation_regex : str
    sphinx_deprecation_regex_in_match : str
    include_sphinx_deprecation()
}
class "WarningsChecker" as mlx.warnings.warnings_checker.WarningsChecker {
    count : int
    cq_default_path : str
    cq_description_template
    cq_enabled : bool
    cq_findings
    exclude_patterns : list
    include_patterns : list
    is_sub_checker
    logger : LoggerAdapter, NoneType, RootLogger
    logging_args : tuple
    logging_fmt : str
    maximum
    minimum
    name : str
    name_repr
    add_patterns(regexes, pattern_container)
    {abstract}check(content)
    parse_config(config)
    return_check_limits()
    return_count()
}
class "<color:red>WarningsConfigError</color>" as mlx.warnings.exceptions.WarningsConfigError {
}
class "WarningsPlugin" as mlx.warnings.warnings.WarningsPlugin {
    activated_checkers : dict
    count : int
    cq_enabled : bool
    printout : bool
    public_checkers : tuple
    activate_checker(checker_type)
    activate_checker_name(name)
    check(content)
    check_logfile(file)
    config_parser(config)
    configure_maximum(maximum)
    configure_minimum(minimum)
    get_checker(name)
    return_check_limits(name)
    return_count(name)
    toggle_printout(printout)
    write_code_quality_report(out_file)
}
class "XMLRunnerChecker" as mlx.warnings.regex_checker.XMLRunnerChecker {
    name : str
    pattern
}
mlx.warnings.junit_checker.JUnitChecker --|> mlx.warnings.warnings_checker.WarningsChecker
mlx.warnings.polyspace_checker.PolyspaceChecker --|> mlx.warnings.warnings_checker.WarningsChecker
mlx.warnings.polyspace_checker.PolyspaceFamilyChecker --|> mlx.warnings.warnings_checker.WarningsChecker
mlx.warnings.regex_checker.CoverityChecker --|> mlx.warnings.regex_checker.RegexChecker
mlx.warnings.regex_checker.CoverityClassificationChecker --|> mlx.warnings.warnings_checker.WarningsChecker
mlx.warnings.regex_checker.DoxyChecker --|> mlx.warnings.regex_checker.RegexChecker
mlx.warnings.regex_checker.RegexChecker --|> mlx.warnings.warnings_checker.WarningsChecker
mlx.warnings.regex_checker.SphinxChecker --|> mlx.warnings.regex_checker.RegexChecker
mlx.warnings.regex_checker.XMLRunnerChecker --|> mlx.warnings.regex_checker.RegexChecker
mlx.warnings.robot_checker.RobotChecker --|> mlx.warnings.warnings_checker.WarningsChecker
mlx.warnings.robot_checker.RobotSuiteChecker --|> mlx.warnings.junit_checker.JUnitChecker
@enduml

String Handling

Convention is to use plain python strings everywhere. Where needed the strings can be converted to anything else.

Example: junitparser expects byte array objects, so we encode our string right before passing it to junitparser.

Instrument Module

Melexis fork of warnings plugin

class mlx.warnings.CoverityChecker(*logging_args)[source]

Bases: RegexChecker

check(content)[source]

Function for counting the number of warnings, but adopted for Coverity output

Parameters:

content (str) – The content to parse

property cq_description_template

string.Template instance based on the configured template string

Type:

Template

property cq_findings

list of code quality findings

Type:

List[dict]

name = 'coverity'
parse_config(config)[source]

Process configuration

Parameters:

config (dict) – Content of configuration file

pattern = re.compile('(?P<path>[\\w\\.\\\\/\\- ]+)(:(?P<line>\\d+)(:(?P<column>\\d+))?)?: ?CID (?P<cid>\\d+) \\(#(?P<curr>\\d+) of (?P<max>\\d+)\\): (?P<checker>.+): (?P<classification>[\\w ]+),.+')
return_check_limits()[source]

Function for checking whether the warning count is within the configured limits

Returns:

int

0 if the amount of warnings is within limits, the count of warnings otherwise

(or 1 in case of a count of 0 warnings)

return_count()[source]

Getter function for the amount of warnings found

Returns:

int – Number of warnings found

class mlx.warnings.DoxyChecker(verbose, output)[source]

Bases: RegexChecker

name = 'doxygen'
pattern = re.compile('(?:(?P<path1>(?:[/.]|[A-Za-z]).+?):(?P<line1>-?\\d+):\\s*(?P<severity1>[Ww]arning|[Ee]rror)|<.+>:(?P<line2>-?\\d+)(?::\\s*(?P<severity2>[Ww]arning|[Ee]rror))?): (?P<description1>.+(?:(?!\\s*([Nn]otic)
class mlx.warnings.Finding(description)[source]

Bases: object

Code quality violation

property column

The column on which the code quality violation occurred. Defaults to 1.

Type:

int

property fingerprint

The unique fingerprint to identify this specific code quality violation.

The fingerprint is generated as follows:

  1. A base string is created by concatenating the severity, path, and description of the finding.

  2. The base string is hashed to produce an initial hash.

  3. If the hash already exists (hash collision), a new hash is generated by concatenating the base string with the current hash and hashing the result.

  4. Step 3 is repeated until a unique hash is obtained.

Type:

str

fingerprints = {}
property line

The line on which the code quality violation occurred. Defaults to 1.

Type:

int

property path

The file containing the code quality violation, expressed as a relative path in the repository.

Type:

str

property severity

The severity of the violation.

Type:

str

to_dict()[source]

Returns the code quality finding as dictionary with a unique fingerprint.

Returns:

dict – The code quality finding

class mlx.warnings.JUnitChecker(verbose, output)[source]

Bases: WarningsChecker

check(content)[source]

Function for counting the number of JUnit failures in a specific text

Parameters:

content (str) – The content to parse

name = 'junit'
property name_repr
static prepare_tree(root_input)[source]

Prepares the tree element by adding a testsuites element as root when missing (to please JUnitXml)

Parameters:

root_input (lxml.etree._Element/xml.etree.ElementTree.Element) – Top-level XML element from input file

Returns:

lxml.etree._Element/xml.etree.ElementTree.Element – Top-level XML element with testsuites tag

class mlx.warnings.PolyspaceChecker(*logging_args)[source]

Bases: WarningsChecker

check(content)[source]

Function for counting the number of failures in a TSV file exported by Polyspace

Parameters:

content (_io.TextIOWrapper) – The open file to parse

checkers = []
property cq_description_template

string.Template instance based on the configured template string

Type:

Template

property cq_findings

list of code quality findings

Type:

List[dict]

property maximum

Gets the highest minimum amount of warnings

Returns:

int – the highest maximum for warnings

property minimum

Gets the lowest minimum amount of warnings

Returns:

int – the lowest minimum for warnings

name = 'polyspace'
parse_config(config)[source]

Parsing configuration dict extracted by previously opened JSON or yaml/yml file

Args:

config (dict): Content of configuration file

Raises:

ValueError: Expected a list of dicts as value of the key which represents the value of the ‘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): {

<column-name>: <value_to_check>, min: <number>, max: <number>

}

return_check_limits()[source]

Function for checking whether the warning count is within the configured limits

Returns:

int

0 if the amount of warnings is within limits, the count of warnings otherwise

(or 1 in case of a count of 0 warnings)

return_count()[source]

Getter function for the amount of warnings found

Returns:

int – Number of warnings found

class mlx.warnings.PolyspaceFamilyChecker(family_value, column_name, check_value, *logging_args)[source]

Bases: WarningsChecker

add_code_quality_finding(row)[source]

Add code quality finding

Parameters:

row (dict) – The row of the warning with the corresponding colomn names

check(content)[source]

Function for counting the number of failures in a TSV/CSV file exported by Polyspace

Parameters:

content (dict) – The row of the TSV file

code_quality_severity = {'impact: high': 'critical', 'impact: low': 'minor', 'impact: medium': 'major', 'orange': 'major', 'red': 'critical'}
property cq_description_template

string.Template instance based on the configured template string

Type:

Template

logging_fmt = '{checker.name_repr}: {checker.family_value:15s} : {checker.column_name:11s} : {checker.check_value:14s} | {message}'
name = 'polyspace_sub'
class mlx.warnings.RobotChecker(*logging_args)[source]

Bases: WarningsChecker

check(content)[source]

Function for counting the number of failures in a specific Robot Framework test suite

Parameters:

content (str) – The content to parse

property ignored_testsuites
logging_fmt = '{checker.name_repr}: {message}'
property maximum

Gets the highest minimum amount of warnings

Returns:

int – the highest maximum for warnings

property minimum

Gets the lowest minimum amount of warnings

Returns:

int – the lowest minimum for warnings

name = 'robot'
parse_config(config)[source]
return_check_limits()[source]

Function for checking whether the warning count is within the configured limits

Returns:

int

0 if the amount of warnings is within limits, the count of warnings otherwise

(or 1 in case of a count of 0 warnings)

return_count()[source]

Getter function for the amount of warnings found

Returns:

int – Number of warnings found

class mlx.warnings.RobotSuiteChecker(suite_name, *logging_args, check_suite_name=False)[source]

Bases: JUnitChecker

check(content)[source]

Function for counting the number of JUnit failures in a specific text

The test cases with a classname that does not end with the name class attribute are ignored.

Parameters:

content (str) – The content to parse

Raises:

SystemExit – No suite with name self.suite_name found. Returning error code -1.

logging_fmt = '{checker.name_repr}: {checker.suite_name_repr:<20} {message}'
name = 'robot_sub'
property suite_name_repr
class mlx.warnings.SphinxChecker(verbose, output)[source]

Bases: RegexChecker

include_sphinx_deprecation()[source]

Adds the pattern for sphinx_deprecation_regex to the list patterns to include and alters the main pattern

name = 'sphinx'
pattern = re.compile('(?m)^(?:((?P<path1>.+?):(?P<line1>\\d+|None)?):?\\s*)?(?P<severity1>DEBUG|INFO|WARNING|ERROR|SEVERE|CRITICAL):\\s*(?P<description1>.+)$', re.MULTILINE)
sphinx_deprecation_regex = '(?m)^(?:(.+?:(?:\\d+|None)?):?\\s*)?(DEBUG|INFO|WARNING|ERROR|SEVERE|(?:\\w+Sphinx\\d+Warning)):\\s*(.+)$'
sphinx_deprecation_regex_in_match = 'RemovedInSphinx\\d+Warning'
class mlx.warnings.WarningsChecker(verbose, output)[source]

Bases: object

add_patterns(regexes, pattern_container)[source]

Adds regexes as patterns to the specified container

Parameters:
  • regexes (list[str]|None) – List of regexes to add

  • pattern_container (list[re.Pattern]) – Target storage container for patterns

abstract check(content)[source]

Function for counting the number of warnings in a specific text

Parameters:

content (str) – The content to parse

property cq_description_template

string.Template instance based on the configured template string

Type:

Template

property cq_findings

list of code quality findings

Type:

List[dict]

property is_sub_checker
logging_fmt = '{checker.name_repr}: {message}'
property maximum

Getter function for the maximum amount of warnings

Returns:

int – Maximum amount of warnings

property minimum

Getter function for the minimum amount of warnings

Returns:

int – Minimum amount of warnings

name = 'checker'
property name_repr
parse_config(config)[source]
return_check_limits()[source]

Function for checking whether the warning count is within the configured limits A checker instance with sub-checkers is responsible for printing ‘Returning error code X.’ when the exit code is not 0.

Returns:

int

0 if the amount of warnings is within limits, the count of (the sum of sub-checker) warnings otherwise

(or 1 in case of a count of 0 warnings)

return_count()[source]

Getter function for the amount of warnings found

Returns:

int – Number of warnings found

exception mlx.warnings.WarningsConfigError[source]

Bases: Exception

class mlx.warnings.WarningsPlugin(cq_enabled=False)[source]

Bases: object

activate_checker(checker_type, *logging_args)[source]

Activate additional checkers after initialization

Parameters:

checker_type (WarningsChecker) – checker class

Returns:

WarningsChecker – activated checker object

activate_checker_name(name, *args)[source]

Activates checker by name

Parameters:

name (str) – checker name

Returns:

WarningsChecker – activated checker object, or None when no checker with the given name exists

check(content)[source]

Count the number of warnings in a specified content

Parameters:

content (str) – The content to parse

check_logfile(file)[source]

Count the number of warnings in a specified content

Parameters:

content (_io.TextIOWrapper) – The open file to parse

config_parser(config, *logging_args)[source]

Parsing configuration dict extracted by previously opened JSON or YAML file

Parameters:

config (dict/Path) – Content or path of configuration file

configure_maximum(maximum)[source]

Configure the maximum amount of warnings for each activated checker

Parameters:

maximum (int) – maximum amount of warnings allowed

configure_minimum(minimum)[source]

Configure the minimum amount of warnings for each activated checker

Parameters:

minimum (int) – minimum amount of warnings allowed

get_checker(name)[source]

Get checker by name

Parameters:

name (str) – checker name

Returns:

checker object (WarningsChecker)

return_check_limits(name=None)[source]

Function for determining the return value of the script

If the name parameter is set, this function will check (and return) the return value of that checker. If not, this function checks whether the warnings for each registered checker are within the configured limits.

Parameters:

name (WarningsChecker) – The checker for which to check the return value

Returns:

int

0 if the amount of warnings is within limits, the count of warnings otherwise

(or 1 in case of a count of 0 warnings)

return_count(name=None)[source]

Getter function for the amount of found warnings

If the name parameter is set, this function will return the amount of warnings found by that checker. If not, the function will return the sum of the warnings found by all registered checkers.

Parameters:

name (WarningsChecker) – The checker for which to return the amount of warnings (if set)

Returns:

int – Amount of found warnings

toggle_printout(printout)[source]

Toggle printout of all the parsed content

Useful for command input where we want to print content as well

Parameters:

printout (bool) – True enables the printout, False provides more silent mode

write_code_quality_report(out_file)[source]

Generates the Code Quality report artifact as a JSON file that implements a subset of the Code Climate spec

Parameters:

out_file (str) – Location for the output file

class mlx.warnings.XMLRunnerChecker(verbose, output)[source]

Bases: RegexChecker

name = 'xmlrunner'
pattern = re.compile('(\\s*(?P<severity1>ERROR|FAILED) (\\[\\d+\\.\\d{3}s\\]: \\s*(?P<description1>.+)))\\n?')
mlx.warnings.warnings_wrapper(args)[source]