angee.integrate.runtime_migrations.integration_lifecycle_values
Rewrite integration lifecycle rows to the connection-focused vocabulary.
LEGACY_MARKERS
Values only the pre-split vocabulary had — their presence is what this applies to.
CURRENT_MARKERS
Values only the connection-focused vocabulary has — their presence means done.
applies
def applies(project_state: ProjectState) -> boolReturn whether Integration still carries the legacy lifecycle vocabulary.
Keyed on the marker values each vocabulary owns exclusively, never on the exact choice tuple: a project that adds a fourth lifecycle value later still has :data:CURRENT_MARKERS and no :data:LEGACY_MARKERS, so it reads as already-migrated instead of failing every angee build forever. Only a genuinely mixed vocabulary — both marker sets, or neither — is unresolvable.
FORWARD_VALUES
Legacy value → current value. Not injective: disconnected has two sources.
BACKWARD_VALUES
Current value → legacy value — the lossy inverse of :data:FORWARD_VALUES.
disconnected collapses to draft because the disabled it may also have come from is unrecoverable; paused is unchanged in both vocabularies. Lossy, but every value it writes fits the max_length=8 column the paired AlterField restores — which is what makes a backwards migrate work.
rewrite_lifecycle_values
def rewrite_lifecycle_values(apps, schema_editor) -> NoneMap every legacy lifecycle value onto the connection-focused vocabulary.
restore_lifecycle_values
def restore_lifecycle_values(apps, schema_editor) -> NoneMap every current lifecycle value back onto the legacy vocabulary, lossily.
Migration
class Migration(migrations.Migration)Widen the lifecycle column, record its new choices, then rewrite data.
Reversible, lossily: operations reverse last-first, so :func:restore_lifecycle_values returns the column to legacy values before the AlterField narrows it back to max_length=8. A noop reverse would leave disconnected (12 chars) in a column being shrunk to 8 — Postgres fails the reverse with "value too long", SQLite accepts it and every row then fails the legacy StateField's to_python. The loss is real (:data:BACKWARD_VALUES) and preferred to either outcome.