mafw.db.migration.runtime

Runtime helpers used by generated migration scripts.

Generated migration scripts import from this module so that the script body stays compact and readable for a reviewing scientist. The helpers wrap the small amount of playhouse.migrate and peewee boilerplate needed to create a new table or add a nullable column, which are the additive operations the differ currently supports.

They also expose temporary_trigger_removal() (a context manager, and its underlying remove_all_triggers() / restore_all_triggers() primitives), which a reviewed destructive migration should bracket its operations with on SQLite. Several ALTER-limited backends (SQLite in particular) implement a column drop/rename/type change by rebuilding the table (create a temporary table, copy the data, drop the original, rename the temporary one). The backend refuses to drop the original table while a trigger still points at it, and MAFw triggers are a MAFw extension that playhouse.migrate knows nothing about. Dropping every MAFw trigger before the operations and recreating them afterwards removes that clash; this is exactly what TriggerRefresher does, so it is safe. The context manager restores the triggers in a finally clause, so they are never left dropped even if the migration body raises.

Added in version 2.4.

author:

Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)

Functions

create_table(database, table_name)

Create a table for a model by resolving it from the model register.

nullable_field(field_type)

Build a nullable peewee field of the requested logical type.

remove_all_triggers(database)

Drop every database trigger and return the affected (trigger, table) pairs.

restore_all_triggers(database)

Recreate every MAFw trigger after a destructive migration.

temporary_trigger_removal(database)

Context manager that drops MAFw triggers for the duration of a migration.

mafw.db.migration.runtime._trigger_dialect(database: Database) → TriggerDialect[source]

Return the MAFw trigger dialect for the live database.

Parameters:

database (peewee.Database) – The live database (possibly a proxy).

Returns:

The matching trigger dialect.

Return type:

TriggerDialect

Raises:

UnsupportedDatabaseError – for an unsupported backend.

mafw.db.migration.runtime._unwrap(database: Database) → Database[source]

Return the concrete database, unwrapping a proxy when necessary.

Parameters:

database (peewee.Database) – The database or proxy to unwrap.

Returns:

The concrete database instance.

Return type:

peewee.Database

mafw.db.migration.runtime.create_table(database: Database, table_name: str) → None[source]

Create a table for a model by resolving it from the model register.

The table is created with safe=True so that an already-existing table (for example one created by TableCreator) is not an error.

Parameters:
  • database (peewee.Database) – The live database the migration runs against.

  • table_name (str) – The name of the table to create.

mafw.db.migration.runtime.nullable_field(field_type: str) → Field[source]

Build a nullable peewee field of the requested logical type.

Parameters:

field_type (str) – The peewee field_type token (for example VARCHAR).

Returns:

A nullable field instance suitable for migrator.add_column.

Return type:

peewee.Field

mafw.db.migration.runtime.remove_all_triggers(database: Database) → list[tuple[str, str]][source]

Drop every database trigger and return the affected (trigger, table) pairs.

Call this inside a reviewed destructive migration before the migrator.migrate(...) operations, and pair it with restore_all_triggers() afterwards. It removes the clash between a table-rebuild operation (common on SQLite, which refuses to drop a table a trigger points at) and MAFw’s triggers, which playhouse.migrate does not manage. Dropping and recreating MAFw triggers is safe because they are regenerable from the model register, mirroring TriggerRefresher.

Parameters:

database (peewee.Database) – The live database to operate on.

Returns:

The list of (trigger_name, table_name) pairs that were dropped.

Return type:

list[tuple[str, str]]

mafw.db.migration.runtime.restore_all_triggers(database: Database) → None[source]

Recreate every MAFw trigger after a destructive migration.

Call this inside a reviewed destructive migration after the migrator.migrate(...) operations, to recreate the triggers that remove_all_triggers() dropped. Triggers are recreated by re-running the (idempotent, safe=True) table creation for every registered model, which regenerates the model’s declared triggers via create_table() without touching existing data.

Parameters:

database (peewee.Database) – The live database to operate on.

mafw.db.migration.runtime.temporary_trigger_removal(database: Database) → Iterator[list[tuple[str, str]]][source]

Context manager that drops MAFw triggers for the duration of a migration.

Enter drops every database trigger (via remove_all_triggers()) and yields the dropped (trigger, table) pairs; exit recreates every registered model’s triggers (via restore_all_triggers()) in a finally clause, so the triggers are always restored — on normal exit and when the body raises. This is the recommended way to bracket a reviewed destructive migration on an ALTER-limited backend (SQLite), where a table rebuild fails while a trigger still points at the table.

Note

The MAFw applier runs the whole migration inside a single database.atomic() on transactional backends (SQLite, PostgreSQL); the per-operation playhouse.migrate runner does not open its own transaction. On those backends a failure therefore rolls back the trigger drops together with the schema change, and this context manager’s finally recreation runs within the same (about-to-roll-back) transaction, which is harmless. On a non-transactional backend (MySQL) the finally recreation is what actually guarantees the triggers are not left dropped after a mid-migration failure.

Example inside a generated migration script:

def migrate(migrator, database):
    operations = [migrator.drop_column('widget', 'gone')]
    with temporary_trigger_removal(database):
        migrator.migrate(*operations)
Parameters:

database (peewee.Database) – The live database to operate on.

Returns:

A context manager yielding the list of dropped (trigger, table) pairs.

Return type:

Iterator[list[tuple[str, str]]]

mafw.db.migration.runtime._FIELD_FACTORIES: dict[str, type[Field]] = {'AUTO': <class 'peewee.IntegerField'>, 'BIGINT': <class 'peewee.BigIntegerField'>, 'BLOB': <class 'peewee.BlobField'>, 'BOOL': <class 'peewee.BooleanField'>, 'CHAR': <class 'peewee.CharField'>, 'DATE': <class 'peewee.DateField'>, 'DATETIME': <class 'peewee.DateTimeField'>, 'DECIMAL': <class 'peewee.DecimalField'>, 'DOUBLE': <class 'peewee.DoubleField'>, 'FLOAT': <class 'peewee.FloatField'>, 'INT': <class 'peewee.IntegerField'>, 'REAL': <class 'peewee.FloatField'>, 'SMALLINT': <class 'peewee.SmallIntegerField'>, 'TEXT': <class 'peewee.TextField'>, 'TIME': <class 'peewee.TimeField'>, 'VARCHAR': <class 'peewee.CharField'>}

Mapping from the peewee field_type token to a nullable field factory. Only the common additive types are mapped; unknown types fall back to a nullable peewee.TextField.