Skip to content

Tautology triage

tautology_triage

Triage for tautology findings.

Implements the v4 decision tree steps that decide whether a tautology finding should be deleted or strengthened. Both the delete-side steps and the full STRENGTHEN-side tree (steps 2/3/4/4b/4c/4d/4e/4f) are ported here.

Verdict dataclass

Result of triaging one tautology finding.

Source code in packages/axm-audit/src/axm_audit/core/rules/test_quality/tautology_triage.py
Python
@dataclass
class Verdict:
    """Result of triaging one tautology finding."""

    action: str
    rule: str
    reason: str

    @property
    def decision(self) -> str:
        """Alias for :attr:`action` (triage decision)."""
        return self.action

    @property
    def verdict(self) -> str:
        """Alias for :attr:`action` (triage verdict)."""
        return self.action

    @property
    def step(self) -> str:
        """Alias for :attr:`rule` (triage step that fired)."""
        return self.rule
decision property

Alias for :attr:action (triage decision).

step property

Alias for :attr:rule (triage step that fired).

verdict property

Alias for :attr:action (triage verdict).

triage(finding, *, tree, func, enclosing_class, helpers, pkg_symbols, contracts, test_file, source_text='')

Return the verdict for finding inside func.

Source code in packages/axm-audit/src/axm_audit/core/rules/test_quality/tautology_triage.py
Python
def triage(  # noqa: PLR0913
    finding: Finding,
    *,
    tree: ast.Module,
    func: ast.FunctionDef,
    enclosing_class: str | None,
    helpers: list[ast.FunctionDef],
    pkg_symbols: set[str],
    contracts: set[str],
    test_file: Path,
    source_text: str = "",
) -> Verdict:
    """Return the verdict for *finding* inside *func*."""
    helper_names = {h.name for h in helpers}

    siblings = _collect_siblings(
        tree, func.name, enclosing_class, helper_names, pkg_symbols
    )

    if (
        verdict := _classify_early_exits(
            finding,
            func=func,
            tree=tree,
            test_file=test_file,
            contracts=contracts,
            enclosing_class=enclosing_class,
            siblings=siblings,
        )
    ) is not None:
        return verdict

    my_dominant = _dominant_call(func.body, helper_names, pkg_symbols)
    my_calls = set(_extract_calls(func.body, helper_names))

    if (
        verdict := _classify_uniqueness(
            finding,
            func=func,
            tree=tree,
            enclosing_class=enclosing_class,
            helper_names=helper_names,
            pkg_symbols=pkg_symbols,
            siblings=siblings,
            my_dominant=my_dominant,
            my_calls=my_calls,
            source_text=source_text,
        )
    ) is not None:
        return verdict

    if (
        verdict := _classify_constructor_duplication(
            finding,
            func=func,
            tree=tree,
            helpers=helpers,
            helper_names=helper_names,
            pkg_symbols=pkg_symbols,
            siblings=siblings,
            enclosing_class=enclosing_class,
        )
    ) is not None:
        return verdict

    reason = (
        f"`{my_dominant}` tested elsewhere but ambiguity remains"
        if my_dominant
        else "no decisive signal — requires human review"
    )
    return Verdict("UNKNOWN", "step5_default_unknown", reason)