Skip to content

ump_spec.rules.contract

module ump-spec

Check new input against a workflow’s InputContract (feature workflow-bundles S3).

check_input reads a FrameProfile (built by the caller, babelfin with pandas) and never the rows. Rules, reported in this order:

  1. every required var, the time column, every categorical dim and every explicit key column is a column (exact names, order free), else INPUT_REQUIRED_MISSING (refuse); the target is required only to refit. An optional var that is absent gives INPUT_OPTIONAL_MISSING (warn).
  2. the caller’s cast result to the contract dtype (the time column’s is TIME_DTYPE; on a refit the target’s is target_dtype and it counts as required): coerced gives INPUT_DTYPE_COERCED (warn, column listed in coerce); failed gives INPUT_DTYPE_FAILED, refuse on a required column, warn on an optional var (the optional column is listed in drop_columns).
  3. a var with missing: forbid and nulls (and, on a refit, a target with nulls) gives INPUT_MISSING_VALUES (warn; the caller drops or fills per its policy, never silently). Nulls in the time column, a categorical dim or an explicit key column give INPUT_MISSING_VALUES (exclude): a row with no time or category cannot be placed, so those rows are excluded (the column is listed in exclude_nulls).
  4. duplicate keys give INPUT_DUPLICATE_KEYS (refuse).
  5. a time dim with policy extend that is not regular or has gaps gives INPUT_IRREGULAR_TIME (warn; a score routes to refit).
  6. a fixed categorical dim whose level set differs from the trained one. With per-level hashes on both sides, levels not trained give NEW_LEVEL_EXCLUDED (exclude; their hashes are listed in exclude_levels so the caller drops those rows), and trained levels that are absent give INPUT_LEVELS_CHANGED (warn). Without per-level hashes (a contract written before them) only the set hash and count are compared: more levels than trained gives NEW_LEVEL_EXCLUDED with nothing listed (the rows cannot be picked out), any other difference INPUT_LEVELS_CHANGED.
  7. fewer rows than min_rows (proposed) gives INPUT_BELOW_MIN_ROWS (warn).
  8. columns the contract does not name (vars, dims, time, target, key): extra: drop gives INPUT_EXTRA_DROPPED (info, listed in drop_columns); allow passes them silently.

Score continuity (mode score with a time column and history_end): the new input must start one step after the history ends. Frequencies W and W-<DAY> are seven days, D one day; any other gives INPUT_HISTORY_UNCHECKED. Starting on or before the history end is INPUT_HISTORY_OVERLAP, later than one step after it INPUT_HISTORY_GAP. All three warn and route to refit. Refit mode adds INPUT_ROWS_GREW (info) when there are more rows than the workflow was trained on.

The route is not_available when any note refuses, refit in refit mode or when a note routes there, else score.

function

def input_key(contract: InputContract) -> list[str]

The columns that identify a row: the contract’s key, or the time column plus the categorical dims.

Source: packages/ump-spec/src/ump_spec/rules/contract.py, line 65

function

def freq_days(freq: str | None) -> int | None

Days per step for the frequencies the continuity check understands (W, W-<DAY>, D), else None.

Source: packages/ump-spec/src/ump_spec/rules/contract.py, line 74

function

def check_input(
contract: InputContract,
profile: FrameProfile,
*,
mode: InputMode = 'score',
history_end: str | None = None,
trained_rows: int | None = None,
) -> InputReport

Check a frame’s profile against contract; see the module docstring for the rules and their order.

Source: packages/ump-spec/src/ump_spec/rules/contract.py, line 91

NameTypeValueDescription
REFIT_CODESfrozenset[str]frozenset({'INPUT_IRREGULAR_TIME', 'INPUT_HISTORY_GAP', 'INPUT_HISTORY_OVERLA...Note codes that send a score to refit.
TIME_DTYPE'datetime64[ns]'The dtype the time column is cast to.