Skip to content

symfonic.devtools.archcheck.config

config

Repository-owned configuration for the architecture rule checks.

Configuration lives in archcheck.toml (evidence/T1.2.4). Relative paths in the file resolve against paths.repo_root, itself relative to the config file's own directory — so the checker runs identically from any CWD.

ArchcheckConfig dataclass

ArchcheckConfig(repo_root: Path, src_root: Path, matrix_path: Path, registry_path: Path, export_baseline_path: Path, layer_map: dict[str, str] = dict(), composition_roots: tuple[str, ...] = (), forbidden_kernel_imports: tuple[str, ...] = (), port_module_names: tuple[str, ...] = ('ports', 'protocol', 'protocols'), max_module_lines: int = 300, public_export_modules: tuple[str, ...] = ())

layer_of

layer_of(module: str) -> str | None

Longest-pattern layer lookup for a dotted module name.

A plain row is a dotted PREFIX: it claims the package it names and every module beneath it. A row carrying a glob metacharacter (:data:GLOB_CHARS) is matched with :func:fnmatch.fnmatchcase instead, so it claims only the names the pattern itself spells out.

The glob form exists for one shape the prefix form cannot express: a module whose dotted name is a prefix of the tree it lives in. The root re-export shim symfonic is the only such module here — a bare symfonic row would become the silent fallback owner of every future top-level package added under src/symfonic/, which would inherit a layer instead of raising layer-mapping and being ruled on its contents. symfoni[c] matches the top-level module and nothing below it, which is the same idiom the exception registry already uses for its targets.

Ties break on pattern length, longest wins, so a narrower row always overrides a broader one.

Source code in src/symfonic/devtools/archcheck/config.py
def layer_of(self, module: str) -> str | None:
    """Longest-pattern layer lookup for a dotted module name.

    A plain row is a dotted PREFIX: it claims the package it names and
    every module beneath it. A row carrying a glob metacharacter
    (:data:`GLOB_CHARS`) is matched with :func:`fnmatch.fnmatchcase`
    instead, so it claims only the names the pattern itself spells out.

    The glob form exists for one shape the prefix form cannot express: a
    module whose dotted name is a prefix of the tree it lives in. The root
    re-export shim ``symfonic`` is the only such module here — a bare
    ``symfonic`` row would become the silent fallback owner of every future
    top-level package added under ``src/symfonic/``, which would inherit a
    layer instead of raising ``layer-mapping`` and being ruled on its
    contents. ``symfoni[c]`` matches the top-level module and nothing
    below it, which is the same idiom the exception registry already uses
    for its targets.

    Ties break on pattern length, longest wins, so a narrower row always
    overrides a broader one.
    """
    best: str | None = None
    best_len = -1
    for pattern, layer in self.layer_map.items():
        if _pattern_matches(pattern, module) and len(pattern) > best_len:
            best, best_len = layer, len(pattern)
    return best

ConfigError

Bases: ValueError

archcheck.toml is missing or structurally invalid.