ok serialize

This commit is contained in:
cclecle
2024-10-21 23:46:07 +01:00
parent 171a2f1617
commit 192dcc74f8
3 changed files with 96 additions and 30 deletions

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from abc import ABC, ABCMeta
from uuid import uuid4
from typing import Annotated, ClassVar, Any, Self, TypeVar, TypeAlias, Generic
from typing import Annotated, ClassVar, Any, Self, TypeVar, TypeAlias, Generic, Union
from datetime import datetime
from copy import deepcopy, copy
from typing_extensions import dataclass_transform, get_origin
@@ -128,7 +128,7 @@ class BaseElement(
IBaseElement,
ABC,
validate_assignment=True,
revalidate_instances="subclass-instances",
# revalidate_instances="subclass-instances", # pydantic issue #10681
validate_default=True,
metaclass=BaseElementMeta,
):
@@ -146,6 +146,11 @@ class BaseElement(
@model_validator(mode="before")
@classmethod
def __default_values_override_hook__(cls, values: T_BaseElement_ConfigMethod_Arg) -> T_BaseElement_ConfigMethod_Arg:
import random
r = random.randint(0, 100)
print(f"{r} __default_values_override_hook__ {cls}")
print(values)
# extracting default values that were set in model fields
cls._saved_default_value = dict()
for field_key, field_val in cls.model_fields.items():
@@ -161,9 +166,17 @@ class BaseElement(
method.__func__(cls, cls._saved_default_value)
# applying user-defined values
for key, _ in values.items():
cls._saved_default_value[key] = values[key]
print(f"{r} ??")
print(values)
for key, val in values.items():
if key == f"{r} features":
print(f"{r} HEYYYYYYYY")
print(key)
print(val)
cls._saved_default_value[key] = val
print(f"{r} __default_values_override_hook__ {cls} DONE")
return cls._saved_default_value
@@ -177,20 +190,17 @@ class BaseFeature(BaseElement, ABC): ...
T_Feature = TypeVar("T_Feature", bound=BaseFeature)
T_BaseAppliance_Feature_OrderedSet: TypeAlias = dict[type[T_Feature], T_Feature]
"""
class MySet(set):
def __init__(self, _iter, klass=None):
if klass is not None:
for item in iter:
if not isinstance(item, klass):
raise Exception("Error")
super(MySet, self).__init__(_iter)
"""
# T_BaseAppliance_Feature_OrderedSet: TypeAlias = dict[type[T_Feature], T_Feature]
# T_BaseAppliance_Feature_OrderedSet: TypeAlias = dict[str, T_Feature]
class BaseAppliance(BaseElement, ABC):
def get_discriminator_value(v: Any) -> str:
if isinstance(v, dict):
return v.get("fruit", v.get("filling"))
return getattr(v, "fruit", getattr(v, "filling", None))
class BaseAppliance(Generic[T_Feature], BaseElement, ABC):
cpu_cnt: Annotated[StrictInt, DABField(1, gt=0)]
ram_size: Annotated[ByteSize, DABField(256, gt=128)]
@@ -206,26 +216,32 @@ class BaseAppliance(BaseElement, ABC):
dabinst_description: Annotated[StrictStr | None, DABField("")]
dabinst_creationdate: Annotated[AwareDatetime | None, DABField(datetime.now(tz=pytz.utc))]
features: Annotated[SerializeAsAny[T_BaseAppliance_Feature_OrderedSet], DABField({})]
features: SerializeAsAny[dict[str, T_Feature]] = DABField({})
@field_validator("features", mode="after")
@classmethod
def __serialize_features(cls, features: T_BaseAppliance_Feature_OrderedSet) -> dict[str, BaseFeature]:
return {str(key.__name__): value for key, value in features.items()} # or __qualname__
# @field_validator("features", mode="after")
# @classmethod
# def __serialize_features(cls, features: dict[str, Any]) -> dict[str, Any]:
# print("XXXX")
# print(type(features))
# print(features)
# return {str(key): value for key, value in features.items()} # or __qualname__
@NoInstanceMethod
@classmethod
def add_feature(cls, feat: BaseFeature):
def add_feature(cls, feat: T_Feature):
print("Addfeature")
print(feat)
print(cls._saved_default_value["features"])
cls._saved_default_value["features"][type(feat)] = feat
cls._saved_default_value["features"][type(feat).__name__] = feat
print(cls._saved_default_value["features"])
print("Addfeature DONE")
@NoInstanceMethod
@classmethod
def del_feature(cls, type_feat: type[BaseFeature]):
del cls._saved_default_value["features"][type_feat]
def del_feature(cls, type_feat: type[T_Feature]):
del cls._saved_default_value["features"][type_feat.__name__]
@NoInstanceMethod
@classmethod
def get_feature(cls, type_feat: type[T_Feature]) -> T_Feature:
return cls._saved_default_value["features"][type_feat]
return cls._saved_default_value["features"][type_feat.__name__]

37
test/test_debug.py Normal file
View File

@@ -0,0 +1,37 @@
from pydantic import BaseModel, SerializeAsAny
class commonbase(
BaseModel,
revalidate_instances="subclass-instances", # toogle to generate error
): ...
class basechild(commonbase):
test_val: int = 1
class derivedchild(basechild):
test_val2: int = 2
class container(commonbase):
ct_child_1: dict[str, basechild] = {}
ct_child_2: SerializeAsAny[dict[str, basechild]] = {}
ct_child_3: dict[str, SerializeAsAny[basechild]] = {}
if __name__ == "__main__":
test_val = container(
ct_child_1={"test1": derivedchild()},
ct_child_2={"test2": derivedchild()},
ct_child_3={"test3": derivedchild()},
)
print(test_val.model_dump_json(indent=1))
print(test_val.model_dump())
assert "test_val2" not in test_val.model_dump()["ct_child_1"]["test1"]
assert "test_val2" in test_val.model_dump()["ct_child_2"]["test2"]
assert "test_val2" in test_val.model_dump()["ct_child_3"]["test3"]

View File

@@ -76,15 +76,17 @@ class MyAppliance2(MyAppliance):
class MyAppliance3(dabmodel.BaseAppliance):
class MyFeature(MyAppliance.MyFeature):
class MyFeature6(MyAppliance.MyFeature):
# testtt: Annotated[MyAppliance.MyFeature, Field(MyAppliance.MyFeature())] # error case
test_integer: Annotated[int, dabmodel.DABField(200, ge=0)]
@dabmodel.default_values_override
@classmethod
def __override_config__(cls, values):
print("!!! CONFIG Feature 1 (modified)")
values["template_id"] = "421d61cb-e364-46d8-9b77-ec439f1fa777"
values["template_id"] = "421d61cb-e364-46d8-9b77-ec439f1fa778"
values["template_short_name"] = "my-feature-1-bis"
values["test_integer"] = 666
# testtt: Annotated[MyAppliance.MyFeature, Field(MyAppliance.MyFeature())] # error case
@@ -97,7 +99,11 @@ class MyAppliance3(dabmodel.BaseAppliance):
values["template_long_name"] = "My appliance template 3 !!"
values["template_description"] = """A very nice Appliance 3"""
values["ram_size"] = 3076
cls.add_feature(cls.MyFeature())
print("CREATE FEATURE")
f = cls.MyFeature6()
# print(f)
cls.add_feature(f)
print("!!! CONFIG Appliance 3 DONE")
class TestModel(unittest.TestCase):
@@ -126,9 +132,16 @@ class TestModel(unittest.TestCase):
print(app3.model_dump_json(indent=1))
print("aaa")
app3 = MyAppliance3(dabinst_short_name="my-app-3", template_description="FORCED")
print("aaa1")
tmp_json = app3.model_dump_json(indent=1)
print("bbb")
print(tmp_json)
recreated_obj = MyAppliance3.parse_raw(tmp_json)
print("ccc")
recreated_obj = MyAppliance3.model_validate_json(tmp_json)
print("ddd")
print(recreated_obj)
print("eee")
print(recreated_obj.model_dump_json(indent=1))
# app3.add_feature(MyAppliance.MyFeature()) # error case (add_feature not callable from instance)