Skip to content

graflo.architecture.profile.runner

Profile definition, registry, and the entry points every surface calls.

A profile is a named, versioned list of assertions over a manifest. Nothing here knows what any assertion means -- that keeps adding a profile to a declaration rather than a code change in the runner.

:func:check_manifest_config is the primary entry point and takes the authored document, because two of the world-model assertions are about what the author declared and the parsed model has already normalized that away. See :mod:graflo.architecture.profile.context.

Attributes

__all__ = ['Assertion', 'Profile', 'check_manifest', 'check_manifest_config', 'get_profile', 'list_profiles', 'run_profile'] module-attribute

Classes

Assertion dataclass

One mechanically checkable claim about a manifest.

Source code in graflo/architecture/profile/runner.py
@dataclass(frozen=True, slots=True)
class Assertion:
    """One mechanically checkable claim about a manifest."""

    id: str
    title: str
    required: bool
    run: Callable[[CheckContext], AssertionResult]

Attributes

id instance-attribute
required instance-attribute
run instance-attribute
title instance-attribute

Methods:

__init__(id, title, required, run)

Profile dataclass

A named conformance level.

Source code in graflo/architecture/profile/runner.py
@dataclass(frozen=True, slots=True)
class Profile:
    """A named conformance level."""

    name: str
    version: str
    assertions: tuple[Assertion, ...]

Attributes

assertions instance-attribute
name instance-attribute
version instance-attribute

Methods:

__init__(name, version, assertions)

Functions:

check_manifest(manifest, *, profile='world-model', authored=None, waivers=None, subject=None, resolver=None)

Check an already-parsed manifest.

Prefer :func:check_manifest_config when the authored document is available: without it the declaration assertions can only warn.

Source code in graflo/architecture/profile/runner.py
def check_manifest(
    manifest: GraphManifest,
    *,
    profile: str = "world-model",
    authored: Mapping[str, Any] | None = None,
    waivers: ProfileWaivers | None = None,
    subject: str | None = None,
    resolver: VocabularyResolver | None = None,
) -> ProfileReport:
    """Check an already-parsed *manifest*.

    Prefer :func:`check_manifest_config` when the authored document is
    available: without it the declaration assertions can only warn.
    """
    context = CheckContext(manifest=manifest, authored=authored, waivers=waivers)
    if resolver is not None:
        context.resolver = resolver
    report = run_profile(get_profile(profile), context)
    return report.model_copy(update={"subject": subject})

check_manifest_config(config, *, profile='world-model', waivers=None, subject=None, resolver=None)

Check the manifest config as authored.

The primary entry point. Parses config into a manifest and keeps the original mapping alongside it, so an assertion can tell "the author did not declare this" from "the author declared the value that is also the default".

Source code in graflo/architecture/profile/runner.py
def check_manifest_config(
    config: Mapping[str, Any],
    *,
    profile: str = "world-model",
    waivers: ProfileWaivers | None = None,
    subject: str | None = None,
    resolver: VocabularyResolver | None = None,
) -> ProfileReport:
    """Check the manifest *config* as authored.

    The primary entry point. Parses *config* into a manifest and keeps the
    original mapping alongside it, so an assertion can tell "the author did not
    declare this" from "the author declared the value that is also the default".
    """
    manifest = GraphManifest.from_config(dict(config))
    manifest.finish_init()
    return check_manifest(
        manifest,
        profile=profile,
        authored=config,
        waivers=waivers,
        subject=subject,
        resolver=resolver,
    )

get_profile(name)

The profile called name.

Raises:

Type Description
KeyError

no such profile, naming the ones that exist.

Source code in graflo/architecture/profile/runner.py
def get_profile(name: str) -> Profile:
    """The profile called *name*.

    Raises:
        KeyError: no such profile, naming the ones that exist.
    """
    profiles = _registry()
    if name not in profiles:
        known = ", ".join(sorted(profiles))
        raise KeyError(f"unknown profile {name!r}; known profiles: {known}")
    return profiles[name]

list_profiles()

(name, version) for every known profile.

Source code in graflo/architecture/profile/runner.py
def list_profiles() -> list[tuple[str, str]]:
    """``(name, version)`` for every known profile."""
    return sorted((p.name, p.version) for p in _registry().values())

run_profile(profile, context)

Run every assertion of profile against context.

Source code in graflo/architecture/profile/runner.py
def run_profile(profile: Profile, context: CheckContext) -> ProfileReport:
    """Run every assertion of *profile* against *context*."""
    results: list[AssertionResult] = []
    for assertion in profile.assertions:
        result = assertion.run(context)
        waiver = (
            context.waivers.for_assertion(assertion.id)
            if context.waivers is not None
            else None
        )
        if waiver is not None and result.status in ("fail", "warn"):
            result = result.model_copy(update={"status": "waived", "waiver": waiver})
        results.append(result)
    return ProfileReport(
        profile=profile.name,
        profile_version=profile.version,
        graflo_version=_graflo_version(),
        status=roll_up([r.status for r in results]),
        assertions=results,
    )