ok serialize
This commit is contained in:
@@ -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
37
test/test_debug.py
Normal 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"]
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user