diff --git a/clive/__private/storage/migrations/base.py b/clive/__private/storage/migrations/base.py index 525897f1b5371775d69fcfcbc766336b4c4f2004..d02846af8098db3e045a8e10580d6b6ea7eb0734 100644 --- a/clive/__private/storage/migrations/base.py +++ b/clive/__private/storage/migrations/base.py @@ -82,7 +82,19 @@ class ProfileStorageBase(PreconfiguredBaseModel): @classmethod def get_this_revision(cls) -> Revision: assert cls is not ProfileStorageBase, "This method should be called on subclass." - return sha256(cls._get_revision_seed().encode()).hexdigest()[:8] + return sha256(cls.get_model_for_schema_json()._get_revision_seed().encode()).hexdigest()[:8] + + @classmethod + def get_model_for_schema_json(cls) -> type[ProfileStorageBase]: + schema = cls._get_model_for_schema_json() + cls._REGISTERED_MODELS.remove( + schema + ) # Remove unnecessary duplication of the model schema due to __init_subclass__ being called by defstruct + return schema + + @classmethod + def _get_model_for_schema_json(cls) -> type[ProfileStorageBase]: + raise NotImplementedError("This method should be overridden in subclasses to provide a model for schema JSON.") @classmethod def get_this_version(cls) -> Version: diff --git a/clive/__private/storage/migrations/v0.py b/clive/__private/storage/migrations/v0.py index 46e0ce3386ac0f66ae4e362f562b63730a460da6..e6a958436fce99a4fb11601199fcb2f8dc6f82e7 100644 --- a/clive/__private/storage/migrations/v0.py +++ b/clive/__private/storage/migrations/v0.py @@ -2,7 +2,9 @@ from __future__ import annotations from collections.abc import Sequence # noqa: TC003 from pathlib import Path # noqa: TC003 -from typing import Any, Self +from typing import Any, Self, cast + +import msgspec from clive.__private.core.alarms.specific_alarms import ( ChangingRecoveryAccountInProgress, @@ -102,6 +104,23 @@ class ProfileStorageModel(ProfileStorageBase, kw_only=True): def upgrade(cls, old: ProfileStorageBase) -> Self: raise NotImplementedError("Upgrade is not not possible for first revision.") + @classmethod + def _get_model_for_schema_json(cls) -> type[ProfileStorageBase]: + transaction_core_storage_model = msgspec.defstruct( + "TransactionCoreStorageModel", [("operations", list[Any])], bases=(cls.TransactionCoreStorageModel,) + ) + + transaction_storage_model = msgspec.defstruct( + "TransactionStorageModel", + [("transaction_core", transaction_core_storage_model)], + bases=(cls.TransactionStorageModel,), + ) + + return cast( + "type[ProfileStorageBase]", + msgspec.defstruct("ProfileStorageModel", [("transaction", transaction_storage_model)], bases=(cls,)), + ) + @classmethod def _preprocess_data(cls, data: dict[str, Any]) -> dict[str, Any]: cls._ensure_non_negative_tapos_fields(data) diff --git a/tests/unit/storage/test_storage_revision.py b/tests/unit/storage/test_storage_revision.py index 28220775cdee84860901f3848ce44d83aa5f1db2..7e008a4c5d6275c8a896536518537a498bfc6bec 100644 --- a/tests/unit/storage/test_storage_revision.py +++ b/tests/unit/storage/test_storage_revision.py @@ -5,7 +5,7 @@ from typing import Final from clive.__private.storage import ProfileStorageModel from clive.__private.storage.storage_history import StorageHistory -REVISIONS: Final[list[str]] = ["0313f118", "aaae09eb", "b52dcff7"] +REVISIONS: Final[list[str]] = ["9a0f921d", "8ea8b44e", "5c607c43"] LATEST_REVISION: Final[str] = REVISIONS[-1]