from __future__ import annotations import uuid from sqlalchemy import String, TypeDecorator from sqlalchemy.dialects.postgresql import UUID as PG_UUID from sqlalchemy.orm import DeclarativeBase class GUID(TypeDecorator): """Platform-independent UUID type. PostgreSQL keeps native UUID columns; SQLite test databases store canonical UUID strings so bind/result behavior stays consistent. """ impl = String cache_ok = True def load_dialect_impl(self, dialect): if dialect.name == "sqlite": return dialect.type_descriptor(String(36)) return dialect.type_descriptor(PG_UUID(as_uuid=True)) def process_bind_param(self, value, dialect): if value is None: return None if dialect.name == "sqlite": return str(value) return value def process_result_value(self, value, dialect): if value is None: return None if dialect.name == "sqlite" and isinstance(value, str): return uuid.UUID(value) return value class Base(DeclarativeBase): type_annotation_map = { uuid.UUID: GUID(), } pass