7.7.2.2. Module axivion.analysis.post_processing

Custom issue post-processing filters are registered via

analysis['MyRule'].post_processing.add_filter(callback)

or

analysis.options.global_post_processing.add_filter(callback)

See documentation of method add_filter for details.

Classes

FilterAction(value)

Used for the return value of add_filter() callbacks.

Position(value)

Describes the position of a post-processing step

PostProcessingSettings(*[, copy_from, ctx, ...])

Stores the post-processing settings (filters and sinks).

FilterAction

class axivion.analysis.post_processing.FilterAction(value)

Bases: Enum

Used for the return value of add_filter() callbacks.

normal = 1

The violation proceeds as usual.

exclude = 2

The violation is excluded: The violation is discarded as if –exclude applied to it. The following filters won’t get to see the violation, and it will not be imported into the database under any circumstances.

suppress = 3

The violation is suppressed as if AXIVION DISABLE applied to it. Whether the violation gets imported into the database is controlled by the Axivion CI configuration.

Position

class axivion.analysis.post_processing.Position(value)

Bases: IntEnum

Describes the position of a post-processing step

before_deduplication = 0

Filter in add_issue(). This means the filter is applied before the violation is deduplicated across template instances; and before commentary activators are applied.

Note: with parallel stylecheck execution, filters with this position will run in the worker processes.

before_commentary_activators = 10

Filter runs after the violation is deduplicated across template instance; before commentary activators are applied.

Note: with parallel stylecheck execution, filters with this position will run in the worker processes.

after_commentary_activators = 20

Filter runs immediately after commentary activators are applied.

This position is also used by justification_checker callbacks. Because justification_checkers are registered as filters only after all user configuration was processed, justification checkers effectively run after all other filters at the after_commentary_activators position.

Note: with parallel stylecheck execution, filters with this position will run in the worker processes.

default = 50

Default filter priority level.

Note: with parallel stylecheck execution, filters with this position will run in the worker processes.

main_process = 100

Run after the worker process has finished processing the violation, and handed it over to the main process.

Filters with this position will run in the main process. This can only be used with global filters; not with per-rule filters.

issue_aggregation = 110

Run after all main_process filters. This is intended to be used for aggregating filters like the HIS-NOMV calculation or rules like ReportUnusedComments that depend on the presence of violations reported by other rules.

Filters with this position will run in the main process. This can only be used with global filters; not with per-rule filters.

after_issue_aggregation = 120

Runs after aggregating filters (HIS-NOMV, ReportUnusedComments).

Filters with this position will run in the main process. This can only be used with global filters; not with per-rule filters.

PostProcessingSettings

class axivion.analysis.post_processing.PostProcessingSettings(*, copy_from=None, ctx=None, is_per_rule=False)

Bases: object

Stores the post-processing settings (filters and sinks).

Parameters:
copy()

Creates a copy of this object.

Return type:

axivion.analysis.post_processing.PostProcessingSettings

extend(other)

Adds all entries from the other PostProcessingSettings to self.

Parameters:

other (axivion.analysis.post_processing.PostProcessingSettings)

Return type:

None

extract(start_position=None, end_position=None)

Return a new PostProcessingSettings instance that contains only the filters between start_position (inclusive) and end_position (exclusive).

Parameters:
Return type:

axivion.analysis.post_processing.PostProcessingSettings

add_filter(f, *, inputs=(), position=Position.default)

Adds a callback that will be invoked once per reported violation.

Parameters:
  • f (typing.Callable[..., typing.Optional[axivion.analysis.post_processing.FilterAction]]) – The callback function.

  • inputs (typing.Iterable[typing.Union[axivion.style.WorkItem[typing.Any], axivion.style.InputHandleProtocol[axivion.style.WorkItem[typing.Any]]]]) – Requests for additional inputs.

  • position (axivion.analysis.post_processing.Position) – describes when the filter will be called within the normal violation-processing pipeline.

Return type:

None

The callback will be invoked as f(analysis_result, *input_values). If multiple callbacks are registered for the same position, they will be invoked in the order of the add_filter calls.

analysis_result is the violation being reported – this will be one of the message classes from bauhaus.analysis_results:

  • Architecture_Violation

  • Clone_Pair

  • Cycle_Finding

  • Dead_Entity

  • Metric

  • Style_Violation

input_values will be the values corresponding to the declared inputs. For example, inputs = [ir.Graph] will result in a call f(analysis_result, ir_graph).

The callback may mutate the violation object, and/or it may return one of the FilterAction enum values to influence further processing of the violation.

Example usage:

import axivion.config
from axivion.analysis.post_processing import FilterAction
from bauhaus import ir

def my_filter(sv, ir_graph):
    node = ir_graph.get_node(ir.Physical, sv.primary_sloc.pir_node_number)
    # Mutate violation to add more information to the message
    sv.message += f" (right is {node.Right_Operand.Value})"
    if node.Right_Operand.Value > 100:
        return FilterAction.exclude
    else:
        return FilterAction.normal

analysis = axivion.config.get_analysis()
analysis.activate('MisraC2012-10.1')
analysis['MisraC2012-10.1'].post_processing.add_filter(my_filter, inputs=[ir.Graph])
# Alternatively, enable for all rules:
# analysis.options.global_post_processing.add_filter(my_filter, inputs=[ir.Graph])
add_sink(f, *, inputs=(), position=Position.default)

Similar to add_filter(), but allows using a custom bauhaus.analysis_results.Sink implementation.

Parameters:
  • f (typing.Callable[..., _analysis_results.Sink]) – The sink-constructing callback function.

  • inputs (typing.Iterable[typing.Union[axivion.style.WorkItem[typing.Any], axivion.style.InputHandleProtocol[axivion.style.WorkItem[typing.Any]]]]) – Requests for additional inputs.

  • position (axivion.analysis.post_processing.Position) – describes when the filter will be called within the normal violation-processing pipeline.

Return type:

None

The callback will be invoked as f(next_sink, *input_values). The callback’s return value must be a sink.

All violations produced by the rule will be sent to the returned sink. It may mutate the violations and then send them on to the next sink. By not sending a violation to the next sink, it can exclude violations. Unlike the add_filter method, this also allows replacing a single violation with multiple new violations.

Caution: sinks may be used from multiple threads; make sure your sink implementation is thread-safe!

Example usage:

from bauhaus import analysis_results as ar

class DuplicatingSink(ar.Sink):
    def __init__(self, next_sink):
        self.next_sink = next_sink

    def send(self, data):
        if isinstance(data, ar.Style_Violation):
            self.next_sink.send(data)
            data.message += '!!!'
            self.next_sink.send(data)
        else:
            self.next_sink.send(data)

analysis = axivion.config.get_analysis()
analysis.activate('MisraC2012-10.1')
analysis['MisraC2012-10.1'].post_processing.add_sink(DuplicatingSink)
num_filters_and_sinks()
Return type:

int

num_inputs()

Gets the total number of inputs required by all filters+sinks added so far.

Return type:

int

get_inputs(_ctx)

Gets the inputs required for decorate_sink().

Parameters:

_ctx (axivion.style.AnalysisSchedulingContext)

Return type:

typing.Iterable[typing.Union[axivion.style.WorkItem[typing.Any], axivion.style.InputHandleProtocol[axivion.style.WorkItem[typing.Any]]]]

decorate_sink(next_sink, input_values, start_position=None, end_position=None)

Create a new sink that applies all the filters from this collection between start_position (inclusive) and end_position (exclusive) and then sends the modified violations to next_sink.

Parameters:
Return type:

_analysis_results.Sink