Skip to content

Precheck

precheck

Pure in-memory static checks over a parsed batch_edit operation set.

Every function here is side-effect free and never touches the filesystem: file contents are supplied by the caller as file -> lines mappings. The operation schemas are imported from :mod:axm_edit.models.operations — this module declares no parallel schema of its own.

StaticOperation = ReplaceOp | CreateOp | DeleteOp | RewriteOp module-attribute

Any already-parsed batch operation accepted by the static checks.

anchor_excerpt(old)

Render an anchor as a bounded, single-line excerpt for a diagnostic.

Invisible characters are named by :func:~axm_edit.core.diagnostics.render_invisibles — a line feed becomes <LF>, so the excerpt never carries a raw newline — and the result is clamped by the single truncation rule of that same module, ellipsis marker included.

Parameters:

Name Type Description Default
old str

The anchor text to echo back to the caller.

required

Returns:

Type Description
str

The rendered anchor, at most MAX_ANCHOR_EXCERPT_CHARS characters.

Source code in packages/axm-edit/src/axm_edit/core/precheck.py
Python
def anchor_excerpt(old: str) -> str:
    """Render an anchor as a bounded, single-line excerpt for a diagnostic.

    Invisible characters are named by
    :func:`~axm_edit.core.diagnostics.render_invisibles` — a line feed becomes
    ``<LF>``, so the excerpt never carries a raw newline — and the result is
    clamped by the single truncation rule of that same module, ellipsis
    marker included.

    Args:
        old: The anchor text to echo back to the caller.

    Returns:
        The rendered anchor, at most ``MAX_ANCHOR_EXCERPT_CHARS`` characters.
    """
    return _truncate(render_invisibles(old), MAX_ANCHOR_EXCERPT_CHARS)

check_anchor_quotes(op_index, file, old, edit_index=None)

Report an anchor containing a triple-quote delimiter.

Parameters:

Name Type Description Default
op_index int

0-indexed position of the operation in the batch.

required
file str

Relative path targeted by the operation.

required
old str

The anchor text to inspect.

required
edit_index int | None

0-indexed position of the edit inside that operation, echoed back on the diagnostic; None when unknown.

None

Returns:

Type Description
list[CheckDiagnostic]

A single ANCHOR_TRIPLE_QUOTE diagnostic, or [].

Source code in packages/axm-edit/src/axm_edit/core/precheck.py
Python
def check_anchor_quotes(
    op_index: int,
    file: str,
    old: str,
    edit_index: int | None = None,
) -> list[CheckDiagnostic]:
    """Report an anchor containing a triple-quote delimiter.

    Args:
        op_index: 0-indexed position of the operation in the batch.
        file: Relative path targeted by the operation.
        old: The anchor text to inspect.
        edit_index: 0-indexed position of the edit inside that operation,
            echoed back on the diagnostic; ``None`` when unknown.

    Returns:
        A single ``ANCHOR_TRIPLE_QUOTE`` diagnostic, or ``[]``.
    """
    if not any(quote in old for quote in _TRIPLE_QUOTES):
        return []
    return [
        CheckDiagnostic(
            op_index=op_index,
            file=file,
            severity="error",
            code="ANCHOR_TRIPLE_QUOTE",
            message="the anchor contains a triple-quote delimiter",
            hint="Anchor on a quote-free line instead of a docstring body.",
            edit_index=edit_index,
            anchor_excerpt=anchor_excerpt(old),
        )
    ]

check_anchor_whole_line(op_index, file, lines, old, edit_index=None)

Report a multi-line anchor that does not span whole lines.

Parameters:

Name Type Description Default
op_index int

0-indexed position of the operation in the batch.

required
file str

Relative path targeted by the operation.

required
lines Sequence[str]

In-memory content of file, one entry per line.

required
old str

The anchor text to inspect.

required
edit_index int | None

0-indexed position of the edit inside that operation, echoed back on the diagnostic; None when unknown.

None

Returns:

Type Description
list[CheckDiagnostic]

A single ANCHOR_NOT_WHOLE_LINE diagnostic, or []. A

list[CheckDiagnostic]

single-line anchor never yields this code.

Source code in packages/axm-edit/src/axm_edit/core/precheck.py
Python
def check_anchor_whole_line(
    op_index: int,
    file: str,
    lines: Sequence[str],
    old: str,
    edit_index: int | None = None,
) -> list[CheckDiagnostic]:
    """Report a multi-line anchor that does not span whole lines.

    Args:
        op_index: 0-indexed position of the operation in the batch.
        file: Relative path targeted by the operation.
        lines: In-memory content of ``file``, one entry per line.
        old: The anchor text to inspect.
        edit_index: 0-indexed position of the edit inside that operation,
            echoed back on the diagnostic; ``None`` when unknown.

    Returns:
        A single ``ANCHOR_NOT_WHOLE_LINE`` diagnostic, or ``[]``.  A
        single-line anchor never yields this code.
    """
    if "\n" not in old:
        return []
    text = "\n".join(lines)
    positions = list(_occurrences(text, old))
    aligned = any(_falls_on_line_boundaries(text, pos, old) for pos in positions)
    if not positions or aligned:
        return []
    return [
        CheckDiagnostic(
            op_index=op_index,
            file=file,
            severity="error",
            code="ANCHOR_NOT_WHOLE_LINE",
            message=(
                "the multi-line anchor starts or ends mid-line in the target file"
            ),
            hint="Extend the anchor to full lines, from column 0 to end of line.",
            edit_index=edit_index,
            anchor_excerpt=anchor_excerpt(old),
        )
    ]

check_edit_keys(op_index, file, raw_edit)

Report keys of raw_edit that are not part of the Edit schema.

Parameters:

Name Type Description Default
op_index int

0-indexed position of the operation in the batch.

required
file str

Relative path targeted by the operation.

required
raw_edit Mapping[str, object]

Mapping as authored, before validation.

required

Returns:

Type Description
list[CheckDiagnostic]

A single UNKNOWN_EDIT_KEY diagnostic, or [] when every key

list[CheckDiagnostic]

belongs to :class:~axm_edit.models.operations.Edit.

Source code in packages/axm-edit/src/axm_edit/core/precheck.py
Python
def check_edit_keys(
    op_index: int,
    file: str,
    raw_edit: Mapping[str, object],
) -> list[CheckDiagnostic]:
    """Report keys of ``raw_edit`` that are not part of the ``Edit`` schema.

    Args:
        op_index: 0-indexed position of the operation in the batch.
        file: Relative path targeted by the operation.
        raw_edit: Mapping as authored, before validation.

    Returns:
        A single ``UNKNOWN_EDIT_KEY`` diagnostic, or ``[]`` when every key
        belongs to :class:`~axm_edit.models.operations.Edit`.
    """
    allowed = tuple(Edit.model_fields)
    unknown = sorted(key for key in raw_edit if key not in allowed)
    if not unknown:
        return []
    return [
        CheckDiagnostic(
            op_index=op_index,
            file=file,
            severity="error",
            code="UNKNOWN_EDIT_KEY",
            message=(
                f"unknown edit key(s): {', '.join(unknown)} — "
                f"allowed keys are: {', '.join(allowed)}"
            ),
            hint="An edit accepts only the Edit schema keys; drop the extras.",
        )
    ]

check_rewrite_keys(op_index, file, raw_op)

Report the payload-shape faults of a raw rewrite operation.

Pure by construction: the mapping is inspected exactly as authored, no path is resolved and no file is read. The on-disk verdict belongs to :func:~axm_edit.core.precheck_fs.check_rewrite_targets.

Parameters:

Name Type Description Default
op_index int

0-indexed position of the operation in the batch.

required
file str

Relative path targeted by the operation.

required
raw_op Mapping[str, object]

Rewrite mapping as authored, before validation.

required

Returns:

Type Description
list[CheckDiagnostic]

A rewrite_unknown_key diagnostic naming every out-of-schema key,

list[CheckDiagnostic]

a rewrite_checksum_required one when no checksum is declared, and

list[CheckDiagnostic]

[] when the payload holds exactly file, content and

list[CheckDiagnostic]

checksum.

Source code in packages/axm-edit/src/axm_edit/core/precheck.py
Python
def check_rewrite_keys(
    op_index: int,
    file: str,
    raw_op: Mapping[str, object],
) -> list[CheckDiagnostic]:
    """Report the payload-shape faults of a raw ``rewrite`` operation.

    Pure by construction: the mapping is inspected exactly as authored, no
    path is resolved and no file is read. The on-disk verdict belongs to
    :func:`~axm_edit.core.precheck_fs.check_rewrite_targets`.

    Args:
        op_index: 0-indexed position of the operation in the batch.
        file: Relative path targeted by the operation.
        raw_op: Rewrite mapping as authored, before validation.

    Returns:
        A ``rewrite_unknown_key`` diagnostic naming every out-of-schema key,
        a ``rewrite_checksum_required`` one when no checksum is declared, and
        ``[]`` when the payload holds exactly ``file``, ``content`` and
        ``checksum``.
    """
    diagnostics: list[CheckDiagnostic] = []
    unknown = sorted(key for key in raw_op if key not in _REWRITE_ALLOWED_KEYS)
    if unknown:
        diagnostics.append(
            CheckDiagnostic(
                op_index=op_index,
                file=file,
                severity="error",
                code=REWRITE_UNKNOWN_KEY,
                message=(
                    f"unknown rewrite key(s): {', '.join(unknown)} — "
                    f"allowed keys are: {', '.join(_REWRITE_DECLARED_KEYS)}"
                ),
                hint=(
                    "A `rewrite` accepts only `file`, `content` and "
                    "`checksum`; drop the extras."
                ),
            )
        )
    if not _declared_checksum(raw_op):
        diagnostics.append(
            CheckDiagnostic(
                op_index=op_index,
                file=file,
                severity="error",
                code=REWRITE_CHECKSUM_REQUIRED,
                message=(
                    "a `rewrite` must declare `checksum`, the sha256 hex "
                    "digest of the file bytes it read"
                ),
                hint=(
                    "Read the file, digest its bytes and pass the result as "
                    "`checksum`: a stale digest is a hard refusal and there "
                    "is no overwrite escape hatch."
                ),
            )
        )
    return diagnostics

run_static_checks(operations, contents)

Aggregate every static check over an already-parsed operation set.

Parameters:

Name Type Description Default
operations Sequence[StaticOperation]

Parsed operations, in batch order.

required
contents Mapping[str, Sequence[str]]

In-memory file -> lines mapping; no file is read here.

required

Returns:

Type Description
list[CheckDiagnostic]

Every diagnostic found, sorted by increasing op_index.

Source code in packages/axm-edit/src/axm_edit/core/precheck.py
Python
def run_static_checks(
    operations: Sequence[StaticOperation],
    contents: Mapping[str, Sequence[str]],
) -> list[CheckDiagnostic]:
    """Aggregate every static check over an already-parsed operation set.

    Args:
        operations: Parsed operations, in batch order.
        contents: In-memory ``file -> lines`` mapping; no file is read here.

    Returns:
        Every diagnostic found, sorted by increasing ``op_index``.
    """
    diagnostics = [
        diagnostic
        for index, op in enumerate(operations)
        if isinstance(op, ReplaceOp)
        for diagnostic in _check_replace(index, op, contents)
    ]
    return sorted(diagnostics, key=lambda diagnostic: diagnostic.op_index)