aeat.application.wizard._persistence module

Persistence adapter for wizard answers.

Serialises a typed answers model back to canonical-token strings, then persists profile facts through canonical user-profile orchestration. The reverse projection (project_answers) builds the typed answers model from a raw canonical-token dict.

persist_answers distinguishes the two wizard verbs. create registers a fresh profile from the full answer set. edit is a true patch: only the questions the operator explicitly supplied on the command line are written, so editing one field never reverts the rest of a populated profile to its descriptor defaults.

WizardPersistMode

Which wizard verb is persisting — create registers a new profile, edit upserts facts on an existing one. The verb is the authority for the create-vs-edit branch; it is never re-derived at runtime.

alias of Literal[‘create’, ‘edit’]

serialise_answers(flow, answers, *, only_question_ids=None)[source]

Project a typed answers model into the canonical-token dict.

Only profile-bound questions contribute a key. When only_question_ids is supplied, the projection is restricted to those question ids — the patch behaviour the edit verb relies on so an unsupplied field is never written back at its default.

Return type:

dict[str, str]

Parameters:
persist_answers(flow, answers, *, state, profile_name, profile_id, mode, supplied_question_ids=None, routing_profile_id=None)[source]

Persist answers into the profile bucket and return updated state.

profile_id is the immutable UUID profile identity; profile_name is the operator-chosen display label.

mode is the create-vs-edit discriminator and is the wizard verb itself, not a runtime-detected fact. "create" routes to register_active_profile(), which delegates the whole cross-store create — bucket directory, manifest, encrypted record, and the active-profile pointer — to ProfileRepository as one unit of work and refuses a label already carried by a live profile. "edit" routes to set_active_fields(), which upserts facts on the active profile.

supplied_question_ids names the questions the operator explicitly supplied on the command line. On the "edit" path it scopes the write to exactly those questions: edit is a patch, so a field the operator did not name is left untouched. It must be supplied for "edit"; it is ignored for "create", which always registers the full set.

Returns the updated WorkflowState after persisting the answers.

Return type:

WorkflowState

Parameters:
profile_values_from_patch(flow, supplied)[source]

Project a non-interactive edit patch to schema-path keyed values.

Return type:

dict[str, str]

Parameters:
persist_patch(flow, supplied, *, state)[source]

Patch the active profile with only the explicitly supplied flags and return the updated WorkflowState.

supplied is the canonical-token dict keyed by question id, carrying exactly the flags the operator named on a non-interactive edit (--quiet / --accept-defaults). This is the true patch path: it never constructs the full SetupAnswers model — which would demand every required field — and never seeds a descriptor default for an unsupplied question. Each supplied value is re-validated through its widget validator, mapped to its profile_key, and upserted via set_active_fields(). A question with no profile_key is not a profile fact and is skipped.

Return type:

WorkflowState

Parameters:
project_answers(flow, values)[source]

Reverse projection: build the typed answers model from canonical tokens.

Values absent from values fall back to the descriptor’s default or the answers model’s own field default; the answers model then runs its strict validation.

Return type:

BaseModel

Parameters: