ump_spec.rules.recipes
module ump-spec
Transform recipes on the catalogue side (POC blueprint TRANSFORM-RECIPES §6 and §7). Pure functions.
describe_steps: one plain line per recorded step (“Dropped 2 rows: 156 to 154”, “Added spend_net”).recipe_badgesandrecipe_plain: the catalogue’s words for aRecipeRef(“Made from Northwind raw delivery and promo_calendar.csv (not in the catalogue) in 5 steps. Reproduced on the analyst’s machine on Oct 27, 2026 (self-reported).”).to_openlineageandto_prov: the recipe in existing wire formats (load-bearing decision 9).recipe_for_agent: the recipe without notebook cells or step code, for agent principals. Cell source and step code are recorded as the analyst wrote them, so they can hold anything; steps, counts and hashes cannot.
The client package (finprint) keeps its own copy of the describe and export logic because analysts install
it without ump_spec. packages/finprint/tests/test_spec_alignment.py checks that both give the same
step words, OpenLineage event and PROV document for the same recipe. Nothing here runs recipe code: a recipe is
data, and the catalogue never executes it.
Functions
Section titled “Functions”as_recipe
Section titled “as_recipe”function
def as_recipe(recipe: TransformRecipe | Mapping[str, Any]) -> TransformRecipeSource: packages/ump-spec/src/ump_spec/rules/recipes.py, line 45
column_origins
Section titled “column_origins”function
def column_origins( recipe: TransformRecipe,) -> tuple[dict[str, set[Origin]], dict[str, str]]For each output column, the input columns it came from, and a note for columns of unknown origin.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 430
describe_step
Section titled “describe_step”function
def describe_step(step: RecipeStep, names: dict[str, str], *, tags: bool = True) -> strOne step in words. tags adds the terminal’s [cell N] and [not replayable] markers; a page that
shows the cell and replayability on their own leaves them off.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 257
describe_steps
Section titled “describe_steps”function
def describe_steps(recipe: TransformRecipe | Mapping[str, Any]) -> list[str]The step list in words, one line per step (the same words as finprint show).
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 281
divergent_step_number
Section titled “divergent_step_number”function
def divergent_step_number(ref: Mapping[str, Any]) -> int | str | NoneStep number (1-based) where a replay first differed, "output" when only the file differed.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 309
recipe_badges
Section titled “recipe_badges”function
def recipe_badges(ref: Mapping[str, Any] | None) -> list[str]Badges for a dataset’s recipe. When the recipe’s output is not the uploaded file, “Describes a different file” leads and a “Reproduced” replay is dropped (it reproduced another file). Then one of Reproduced, Not checked, Didn’t reproduce at step N, Can’t be replayed, Inputs missing; plus Partly recorded.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 330
recipe_for_agent
Section titled “recipe_for_agent”function
def recipe_for_agent(recipe: Mapping[str, Any]) -> dict[str, Any]The recipe without notebook cells, named-step code or the globals that code reads (agents read steps,
counts and hashes). Still a valid TransformRecipe, so the exporters take it.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 397
recipe_plain
Section titled “recipe_plain”function
def recipe_plain( ref: Mapping[str, Any] | None, titles: Mapping[str, str] | None = None,) -> str | NoneA few sentences for the catalogue: “Made from <inputs> in N steps. Reproduced on the analyst’s machine on
Oct 27, 2026 (self-reported).” Matched inputs are named by their catalogue title (titles: dataset id to
title), else the recipe’s own input name, else “a catalogued dataset” (never a raw id); a drifted match
adds “(changed since it was catalogued)”; other inputs keep the recipe’s name with “(not in the
catalogue)”. When the recipe’s output is not the uploaded file, that sentence comes before the replay
result. Every replay result is the analyst’s own report, so it says self-reported.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 357
step_names
Section titled “step_names”function
def step_names(recipe: TransformRecipe) -> dict[str, str]Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 99
step_rows
Section titled “step_rows”function
def step_rows( recipe: TransformRecipe | Mapping[str, Any], *, with_code: bool = True,) -> list[dict[str, Any]]The steps for a page: number, words, row counts, column changes and (unless with_code is off) the
named step’s code. Arguments stay out: they are in the recipe for replay, not for reading.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 288
to_openlineage
Section titled “to_openlineage”function
def to_openlineage( recipe: TransformRecipe | Mapping[str, Any], *, producer: str = DEFAULT_PRODUCER, matched: Mapping[str, str] | None = None, output_dataset_id: str | None = None,) -> dict[str, Any]An OpenLineage 2-0-2 RunEvent (eventType COMPLETE) for the recipe, with schema and columnLineage facets.
matched (input id to catalogue dataset id) names matched inputs in the ump-catalogue namespace, and
output_dataset_id names the output the same way; without them the event is the client package’s.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 493
to_prov
Section titled “to_prov”function
def to_prov( recipe: TransformRecipe | Mapping[str, Any], *, matched: Mapping[str, str] | None = None, output_dataset_id: str | None = None,) -> dict[str, Any]W3C PROV-JSON: inputs, intermediate frames and the output as entities, steps as activities. matched and
output_dataset_id add ump:dataset_id to the catalogued entities.
Source: packages/ump-spec/src/ump_spec/rules/recipes.py, line 539
Constants
Section titled “Constants”| Name | Type | Value | Description |
|---|---|---|---|
DEFAULT_PRODUCER | 'urn:ump:ump-data' | ||
RECIPE_SCHEMA_ID | 'https://schemas.ump.dev/v1/transform-recipe.json' | ||
STATUS_WORDS | {'not_checked': 'Not checked', 'reproduced': 'Reproduced', 'not_reproduced': ... |