Skip to content

topmark.presentation.shared.diagnostic

topmark / presentation / shared / diagnostic

Shared diagnostic preparation for human-facing CLI emitters.

This module contains Click-free helpers and small data shapes that convert internal diagnostic objects into a presentation-friendly form for human output formats (TEXT / MARKDOWN).

Scope
  • Prepare stable, minimal "human" diagnostics (counts + rendered lines).
  • Avoid depending on machine-format schemas/payloads: those belong under topmark/**/machine/* and are used by JSON/NDJSON emitters.
Design
  • The resulting shapes (HumanDiagnosticCounts, HumanDiagnosticLine) are used by both TEXT and Markdown emitters.
  • Helpers here do not print or perform Click I/O. They may normalize text, map levels, and count diagnostics.
Notes

If you need to change the machine diagnostic schema, do so in the topmark.diagnostic.machine package instead.

HumanDiagnosticLine dataclass

HumanDiagnosticLine(*, level, message)

A human-facing diagnostic line (Click-free).

This is intentionally not a machine schema type. It exists so TEXT and MARKDOWN output can share a stable presentation model without depending on machine-format payload schemas.

Attributes:

Name Type Description
level str

Diagnostic level as a lowercase string (e.g. "info", "warning", "error").

message str

Diagnostic message text.

HumanDiagnosticCounts dataclass

HumanDiagnosticCounts(*, info, warning, error)

Aggregated per-level counts for human-facing config output.

Attributes:

Name Type Description
info int

Number of info-level diagnostics.

warning int

Number of warning-level diagnostics.

error int

Number of error-level diagnostics.

HumanDiagnostics dataclass

HumanDiagnostics(*, counts, lines)

Prepared human-facing diagnostics for presentation emitters.

Attributes:

Name Type Description
counts HumanDiagnosticCounts

Aggregated diagnostic counts grouped by severity.

lines list[HumanDiagnosticLine]

Prepared human-facing diagnostic lines.

prepare_human_diagnostics

prepare_human_diagnostics(diagnostics)

Convert internal diagnostics into human-facing counts and lines.

Parameters:

Name Type Description Default
diagnostics Iterable[Diagnostic]

Iterable of internal Diagnostic objects.

required

Returns:

Type Description
HumanDiagnostics

Structured human-facing diagnostic preparation result.

Source code in src/topmark/presentation/shared/diagnostic.py
def prepare_human_diagnostics(
    diagnostics: Iterable[Diagnostic],
) -> HumanDiagnostics:
    """Convert internal diagnostics into human-facing counts and lines.

    Args:
        diagnostics: Iterable of internal Diagnostic objects.

    Returns:
        Structured human-facing diagnostic preparation result.
    """
    info = 0
    warning = 0
    error = 0
    lines: list[HumanDiagnosticLine] = []

    for d in diagnostics:
        level: str = _level_to_str(getattr(d, "level", "")).lower()
        msg: str = str(getattr(d, "message", ""))

        if level == "error":
            error += 1
        elif level == "warning":
            warning += 1
        else:
            # Treat unknown levels as "info" for human output stability.
            info += 1
            if not level:
                level = "info"

        lines.append(
            HumanDiagnosticLine(
                level=level,
                message=msg,
            )
        )

    return HumanDiagnostics(
        counts=HumanDiagnosticCounts(
            info=info,
            warning=warning,
            error=error,
        ),
        lines=lines,
    )