Skip to content

symfonic.devtools.archcheck.matrix

matrix

Parse the allowed dependency matrix (repository-owned source of truth).

The matrix file is T1.2.1's dependency-matrix.md; LAY-ADR SS2/SS7 make it the machine-checked source of truth from which this checker derives its import-boundary configuration. This module intentionally re-parses the markdown table rather than duplicating it as code.

MatrixError

Bases: ValueError

The dependency-matrix file is missing, incomplete, or invalid.

layer_graph_cycles

layer_graph_cycles(matrix: dict[str, dict[str, str]]) -> list[list[str]]

Return cycles in the allowed-dependency layer digraph (should be none).

Edges are every yes/port/root cell; self is excluded.

Source code in src/symfonic/devtools/archcheck/matrix.py
def layer_graph_cycles(matrix: dict[str, dict[str, str]]) -> list[list[str]]:
    """Return cycles in the allowed-dependency layer digraph (should be none).

    Edges are every ``yes``/``port``/``root`` cell; ``self`` is excluded.
    """
    edges = {
        importer: sorted(
            imported
            for imported, cell in row.items()
            if imported != importer and cell in ("yes", "port", "root")
        )
        for importer, row in matrix.items()
    }
    from symfonic.devtools.archcheck.cycles import strongly_connected_components

    return [sorted(scc) for scc in strongly_connected_components(edges) if len(scc) > 1]

parse_matrix_file

parse_matrix_file(path: Path) -> dict[str, dict[str, str]]

Parse dependency-matrix.md into {importer: {imported: cell}}.

Raises :class:MatrixError on any structural gap so a corrupted matrix can never silently weaken enforcement.

Source code in src/symfonic/devtools/archcheck/matrix.py
def parse_matrix_file(path: Path) -> dict[str, dict[str, str]]:
    """Parse ``dependency-matrix.md`` into ``{importer: {imported: cell}}``.

    Raises :class:`MatrixError` on any structural gap so a corrupted matrix
    can never silently weaken enforcement.
    """
    if not path.is_file():
        raise MatrixError(f"dependency matrix not found: {path}")
    matrix: dict[str, dict[str, str]] = {}
    for line in path.read_text(encoding="utf-8").splitlines():
        if not line.startswith("|"):
            continue
        cells = [c.strip().strip("`") for c in line.strip().strip("|").split("|")]
        if not cells or cells[0] not in LAYERS:
            continue
        row_name, values = cells[0], cells[1:]
        if len(values) != len(LAYERS):
            raise MatrixError(
                f"matrix row {row_name!r}: expected {len(LAYERS)} cells, got {len(values)}"
            )
        matrix[row_name] = dict(zip(LAYERS, values, strict=True))
    missing = [layer for layer in LAYERS if layer not in matrix]
    if missing:
        raise MatrixError(f"matrix rows missing: {missing}")
    for importer, row in matrix.items():
        for imported, cell in row.items():
            if cell not in VALID_CELLS:
                raise MatrixError(
                    f"matrix cell [{importer} -> {imported}] has invalid value {cell!r}"
                )
        if row[importer] != "self":
            raise MatrixError(f"matrix diagonal [{importer}] must be 'self', got {row[importer]!r}")
    return matrix