Skip to main content

migrations

Migration for scan_metadata v1 -> v2: normalise scan_datetime.

A data migration, not a schema one — v2's ORM is column-for-column v1's, so there is no DDL here and gen_migration would render an empty body. What changes is the column's contents.

v1 stored whatever the vendor path handed over, stringified and unparsed (bitfount.cache.types.scan_metadata.timestamps has the full account), so one column held ISO-8601, DICOM DT and DICOM DA values side by side and could neither be sorted as text nor compared as time without detecting each row's format first. This hop rewrites every row into the one spelling normalise_scan_datetime produces.

Why a migration rather than letting the writer converge the column. scan_metadata re-parses a file only when its content hash changes (bitfount.runtimes.scan_metadata.tasks), so an unchanged file's row is never rewritten. Without this hop a customer's existing rows would keep their old spellings indefinitely, and the column would stay uncomparable for exactly the datasources that have been running longest.

No downgrade. The normalisation is lossy in two directions a reverse hop could not undo: a value that would not parse is cleared to NULL, and a DICOM DA gains a midnight time it did not carry. v2 is v1's ORM — the version package re-exports it — so a cache rolled back to an older SDK reads these rows without complaint; the values are simply already normalised.

Module​

Functions​

upgrade​

def upgrade(op: Operations) ‑> None:

Rewrite every scan_datetime into ISO-8601 UTC (see the module docstring).

Idempotent: a row already in the target spelling normalises to itself and is not rewritten, so replaying the hop by hand is safe.

Arguments

  • op: The bound Alembic operations handle; its connection is the one the caller's per-hop transaction runs in, so the rewrite commits or rolls back with the version bump.