Files
DumiFlex-ComfyUI-Wildcard-P…/engine/migrations/__init__.py
T
DumiFlex 39529a669b feat(engine): migrate library v1->v2 (multi-tag) + bump schema version
engine/migrations/v1_to_v2.py: option sub_category->sub_categories[]; sub-category name slugify (whitespace/grammar chars->_, reserved suffixed, de-duped) cascaded to options + tag_groups; instance category_filter list->boolean-expr string + exclude_null flag; nested @{uuid:a,b,null} refs->@{uuid:a or b!null}. Idempotent. Two entry points share one core: envelope migrate_v1_to_v2 (import/export, registered in _CHAIN) + per-row migrate_module/bundle_v1_to_v2 (lazy/bulk DB path).

Register _CHAIN[1] + bump engine CURRENT_SCHEMA_VERSION 1->2. New SQL migration 016 marches stale DB rows 1->2 at boot via run_bulk_lazy + the per-row migrators (014's documented bump pattern). TS mirror (migrations.ts) + client CURRENT bump follow next (no cross-language version assertion couples them). Update version/entity-count assertions in payload-migration, migration-runner, and export-build tests.
2026-06-07 01:40:53 +03:00

66 lines
2.5 KiB
Python

"""Versioned payload migration chain. Mirror of TypeScript
`src/manager/import-export/migrations.ts`.
Used by `engine/importer.py` on server-side parse paths (re-validate
on commit). Client-side migration is the source of truth for what
the user saw in the picker; server re-runs as defense in depth.
"""
from __future__ import annotations
from typing import Any
from engine.migrations.v0_to_v1 import migrate_v0_to_v1
from engine.migrations.v1_to_v2 import migrate_v1_to_v2
CURRENT_SCHEMA_VERSION = 2
_CHAIN = {
0: migrate_v0_to_v1,
1: migrate_v1_to_v2,
}
def migrate_payload(payload: dict[str, Any]) -> dict[str, Any]:
"""Walk the migration chain from `payload.schema_version` up to current.
Returns one of:
- {"ok": True, "migrated": <dict>, "migrated_entity_count": int}
where migrated_entity_count is the cumulative entity count across
all migration steps (total bundles+wildcards+fixed_values+combines+
derivations+constraints+categories that passed through any step).
Matches TS `migratedEntityCount`.
- {"ok": False, "reason": str}
"""
version = payload.get("schema_version")
if not isinstance(version, int):
return {"ok": False, "reason": "payload missing schema_version field"}
if version > CURRENT_SCHEMA_VERSION:
return {
"ok": False,
"reason": f"future schema version {version} (current: {CURRENT_SCHEMA_VERSION})",
}
current = {
"schema_version": version,
"bundles": payload.get("bundles", []),
"wildcards": payload.get("wildcards", []),
"fixed_values": payload.get("fixed_values", []),
"combines": payload.get("combines", []),
"derivations": payload.get("derivations", []),
"constraints": payload.get("constraints", []),
"categories": payload.get("categories", []),
}
migrated_entity_count = 0
while current["schema_version"] < CURRENT_SCHEMA_VERSION:
fn = _CHAIN.get(current["schema_version"])
if fn is None:
ver = current["schema_version"]
return {"ok": False, "reason": f"no migration registered for v{ver}"}
before = sum(
len(current[k])
for k in ("bundles", "wildcards", "fixed_values", "combines",
"derivations", "constraints", "categories")
)
current = fn(current)
migrated_entity_count += before
return {"ok": True, "migrated": current, "migrated_entity_count": migrated_entity_count}