finprint.replay
module finprint
Replay check: rerun a recipe from its inputs and compare fingerprints step by step.
Named steps run from their recorded source, each exec’d in its own namespace holding the globals recorded with
it (modules such as pd and np, constants), so two versions of a step with the same name each replay with
their own code. Named-step code runs only when this machine recorded it (its hash is in the local trust store, see
trust) or the caller passes trust=True after reading it; otherwise replay stops before running anything.
Verbs run from the recorded op and arguments through an allowlist: public pandas methods and operators, and pure
functions from pandas, numpy, math, statistics, datetime and builtins. Nothing that runs strings as code, imports,
reads or writes files is ever called, whatever the recipe says. Every input’s hash is checked first, and the output
file beside the recipe is hashed against output.sha256. Outcomes:
reproduced: every step and the output (written and read back) match;not_reproduced: the first step whose fingerprint differs, or that raised, is named (unseeded randomness lands here, with a hint); or the output file beside the recipe no longer matches it (RECIPE_OUTPUT_MISMATCH);not_replayable: a step is a cell edit, its arguments could not be recorded, it names something replay never runs, or its code was not recorded on this machine and was not trusted;inputs_missing: an input could not be found, or its data differs from the recorded one.
The message written back into the recipe holds only file basenames and exception types (an exception’s text can
quote row values); ReplayResult.detail has the full text for the terminal.
Replay runs recorded code, so it only runs on the analyst’s machine (or a future sandboxed worker). apps/data never executes a recipe.
Classes
Section titled “Classes”InputCheck
Section titled “InputCheck”class
class InputCheckFields
| Name | Type | Default | Description |
|---|---|---|---|
input_id | str | ||
name | str | ||
status | str | ||
detail | str | '' | |
where | str | '' |
Methods and properties (1)
init constructor
InputCheck( self, input_id: str, name: str, status: str, detail: str = '', where: str = '',) -> NoneSource: packages/finprint/src/finprint/replay.py, line 63
StepCheck
Section titled “StepCheck”class
class StepCheckFields
| Name | Type | Default | Description |
|---|---|---|---|
step_id | str | ||
op | str | ||
status | str | ||
expected | str | None | None | |
got | str | None | None | |
detail | str | '' |
Methods and properties (1)
init constructor
StepCheck( self, step_id: str, op: str, status: str, expected: str | None = None, got: str | None = None, detail: str = '',) -> NoneSource: packages/finprint/src/finprint/replay.py, line 72
ReplayResult
Section titled “ReplayResult”class
class ReplayResultFields
| Name | Type | Default | Description |
|---|---|---|---|
status | str | ||
message | str | ||
first_divergent_step | str | None | None | |
inputs | list[InputCheck] | field(default_factory=list) | |
steps | list[StepCheck] | field(default_factory=list) | |
output_fingerprint | str | None | None | |
detail | str | '' | |
untrusted | list[RecipeStep] | field(default_factory=list) | |
output_mismatch | bool | False |
Methods and properties (2)
verification method
def verification(self) -> Verificationinit constructor
ReplayResult( self, status: str, message: str, first_divergent_step: str | None = None, inputs: list[InputCheck] = list(), steps: list[StepCheck] = list(), output_fingerprint: str | None = None, detail: str = '', untrusted: list[RecipeStep] = list(), output_mismatch: bool = False,) -> NoneSource: packages/finprint/src/finprint/replay.py, line 82
NamedSteps
Section titled “NamedSteps”class
class NamedStepsEach named step’s function, from its own code and recorded globals in a namespace of its own.
Methods and properties (2)
init constructor
NamedSteps(self) -> Noneget method
def get(self, step: RecipeStep) -> AnySource: packages/finprint/src/finprint/replay.py, line 160
Functions
Section titled “Functions”unsafe_step
Section titled “unsafe_step”function
def unsafe_step(recipe: TransformRecipe) -> tuple[RecipeStep, str] | NoneThe first step that passes a string as the function to apply/agg/transform/pipe/map (or an
aggfunc) that the method allowlist refuses ("to_pickle", "eval", a read_/to_ name, a private
name), with the reason. Checked before anything runs; run_step checks again as it runs.
Source: packages/finprint/src/finprint/replay.py, line 227
run_step
Section titled “run_step”function
def run_step(step: RecipeStep, ns: dict[str, Any], named: NamedSteps) -> AnySource: packages/finprint/src/finprint/replay.py, line 250
blocked_step
Section titled “blocked_step”function
def blocked_step(recipe: TransformRecipe) -> RecipeStep | NoneThe first step replay never reruns: a cell edit, or a step whose arguments were not recorded replayably.
Source: packages/finprint/src/finprint/replay.py, line 341
untrusted_steps
Section titled “untrusted_steps”function
def untrusted_steps(recipe: TransformRecipe) -> list[RecipeStep]Named steps whose code this machine did not record (see trust).
Source: packages/finprint/src/finprint/replay.py, line 346
replay
Section titled “replay”function
def replay( recipe: TransformRecipe | str | Path, *, inputs_dir: str | Path | None = None, recipe_dir: str | Path | None = None, url: str | None = None, principal: str | None = None, client: httpx.Client | None = None, trust_code: bool = False,) -> ReplayResultRerun recipe and report the outcome (nothing is written; verify writes the result back).
Named-step code that this machine did not record runs only with trust_code=True.
Source: packages/finprint/src/finprint/replay.py, line 361
apply_verification
Section titled “apply_verification”function
def apply_verification(recipe: TransformRecipe, result: ReplayResult) -> TransformRecipeSource: packages/finprint/src/finprint/replay.py, line 445
verify
Section titled “verify”function
def verify( path: str | Path, *, inputs_dir: str | Path | None = None, dry_run: bool = False, url: str | None = None, principal: str | None = None, client: httpx.Client | None = None, trust_code: bool = False,) -> ReplayResultReplay the recipe at path and, unless dry_run, write the verification back into the file.
A refusal to run untrusted named-step code is not written back (nothing was checked).
Source: packages/finprint/src/finprint/replay.py, line 459
Constants
Section titled “Constants”| Name | Type | Value | Description |
|---|---|---|---|
READERS | {'read_csv': pd.read_csv, 'read_excel': pd.read_excel, 'read_parquet': pd.rea... |