# dabmodel (c) by chacha # # dabmodel is licensed under a # Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. # # You should have received a copy of the license along with this # work. If not, see . import unittest from os import chdir from pathlib import Path from pydantic import StrictInt, model_validator from pydantic.fields import Field print(__name__) print(__package__) from src import dabmodel from typing import Annotated, Any from uuid import uuid4 import json from uuid import UUID from datetime import datetime testdir_path = Path(__file__).parent.resolve() chdir(testdir_path.parent.resolve()) class UUIDEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, UUID): # if the obj is uuid, we simply return the value of uuid return obj.hex elif isinstance(obj, datetime): return str(obj) return json.JSONEncoder.default(self, obj) class MyAppliance(dabmodel.BaseAppliance): app_specifi_integer_arg: Annotated[StrictInt | None, dabmodel.DABField(42)] class MyFeature(dabmodel.BaseFeature): @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Feature 1") values["template_id"] = "421d61cb-e364-46d8-9b77-ec439f1fa666" values["template_short_name"] = "my-feature-1" values["template_long_name"] = "My feature template 1 !!" values["template_description"] = """A very nice FEature 1""" class MyFeature2(dabmodel.BaseFeature): @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Feature 2") values["template_id"] = "421d61cb-e364-46d8-9b77-ec439f1fa666" values["template_short_name"] = "my-feature-2" values["template_long_name"] = "My feature template 2 !!" values["template_description"] = """A very nice FEature 2""" @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Appliance 1") print(f"!!!! {values['rootfs_size']}") values["template_id"] = "421d61cb-e364-46d8-9b64-ec439f1faae8" values["template_short_name"] = "my-app- tem 1" values["template_long_name"] = "My appliance template 1 !!" values["template_description"] = """A very nice Appliance 1""" values["ram_size"] = 1024 cls.add_feature(cls.MyFeature()) cls.add_feature(cls.MyFeature2()) class MyAppliance2(MyAppliance): @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Appliance 2") print(f"!!!! {values['template_id']}") values["template_id"] = "421d61cb-e664-46d8-9b64-ec439f1fafff" values["template_short_name"] = "my-app- tem 2" values["template_long_name"] = "My appliance template 2 !!" values["template_description"] = """A very nice Appliance 2""" cls.del_feature(MyAppliance.MyFeature) # values["features"]["MyFeature2"].template_description = """Override feature desc""" class MyAppliance3(dabmodel.BaseAppliance): 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-ec439f1fa778" values["template_short_name"] = "my-feature-1-bis" values["test_integer"] = 666 class MyFeature7(dabmodel.BaseFeature): # testtt: Annotated[MyAppliance.MyFeature, Field(MyAppliance.MyFeature())] # error case test_integer_2: Annotated[int, dabmodel.DABField(759, ge=0)] @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Feature 7") values["template_id"] = "421d61cb-e364-46d8-ac55-ec439f1fa778" values["template_short_name"] = "my-feature-7" values["template_long_name"] = "My appliance template 7 !!" values["template_description"] = """A very nice Appliance 7""" values["test_integer_2"] = 3844 # testtt: Annotated[MyAppliance.MyFeature, Field(MyAppliance.MyFeature())] # error case @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Appliance 3") values["template_id"] = "421d61cb-e364-46d8-9b64-ec439f1faaaa" values["template_short_name"] = "my-app- tem 3" values["template_long_name"] = "My appliance template 3 !!" values["template_description"] = """A very nice Appliance 3""" values["ram_size"] = 3076 print("CREATE FEATURE") cls.add_feature(cls.MyFeature6()) cls.add_feature(cls.MyFeature7()) print("!!! CONFIG Appliance 3 DONE") class MyAppliance4(MyAppliance): class MyFeature8(dabmodel.BaseFeature): # testtt: Annotated[MyAppliance.MyFeature, Field(MyAppliance.MyFeature())] # error case (nested feature) # test_integer_10: Annotated[int, dabmodel.DABField(3189, ge=0, toto="tata")] # error case (extra field) test_integer_10: Annotated[int, dabmodel.DABField(3189, ge=0, toto="tata")] @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Feature 8") values["template_id"] = "421d61cb-e364-46d8-ac55-ec4398888778" values["template_short_name"] = "my-feature-8" values["template_long_name"] = "My appliance template 8 !!" values["template_description"] = """A very nice Appliance 8""" values["test_integer_10"] = 951753 # values["tete"] = 1 # error case (extra field in feature) # testtt: Annotated[MyAppliance.MyFeature, Field(MyAppliance.MyFeature())] # error case (feature not in features[] list) @dabmodel.default_values_override @classmethod def __override_config__(cls, values): print("!!! CONFIG Appliance 4") values["template_id"] = "421d1234-e364-46d8-9b64-ec439f1faaaa" values["template_short_name"] = "my-app-tem 4" values["template_long_name"] = "My appliance template 4 !!" values["template_description"] = """A very nice Appliance 4""" values["ram_size"] = 954 print("CREATE FEATURE") cls.add_feature(cls.MyFeature8()) print("!!! CONFIG Appliance 4 DONE") class TestModel(unittest.TestCase): def setUp(self) -> None: chdir(testdir_path.parent.resolve()) def test_version(self): self.assertNotEqual(dabmodel.__version__, "?.?.?") def test_model(self): feature1 = MyAppliance.MyFeature() print(feature1) print(MyAppliance.MyFeature) print(MyAppliance.MyFeature.__name__) print(MyAppliance.MyFeature.__class__) print("==") print(feature1.model_dump_json(indent=1)) app = MyAppliance(dabinst_short_name="my-app-1", app_specifi_integer_arg=123) app2 = MyAppliance2(dabinst_short_name="my-app-2", app_specifi_integer_arg=654) app3 = MyAppliance3(dabinst_short_name="my-app-3", template_description="FORCED") print(app.model_dump_json(indent=1)) print(app2.model_dump_json(indent=1)) print(app3.model_dump_json(indent=1)) app3 = MyAppliance3(dabinst_short_name="my-app-3", template_description="FORCED") tmp_json = app3.dict() tmp_json["features"]["MyFeature7"]["test_integer_2"] = 123 print(tmp_json) recreated_obj = MyAppliance3.model_validate_json(json.dumps(tmp_json, cls=UUIDEncoder)) print(recreated_obj) print(recreated_obj.model_dump_json(indent=1)) app4 = MyAppliance4(dabinst_short_name="my-app-4", template_description="FORCED2") tmp_json = app4.dict() tmp_json["features"]["MyFeature"]["template_description"] = "blablabla" tmp_json["features"]["MyFeature2"]["template_description"] = "blablabla2" print(tmp_json) recreated_obj = MyAppliance4.model_validate_json(json.dumps(tmp_json, cls=UUIDEncoder)) print(recreated_obj) print(recreated_obj.model_dump_json(indent=1)) # tmp_json["non-existing"] = "test" # error case # tmp_json["features"]["non-existing"] = "test" # error case # tmp_json["features"]["MyFeature"]["132"] = "test" # error case recreated_obj = MyAppliance4.model_validate_json(json.dumps(tmp_json, cls=UUIDEncoder)) # app3.add_feature(MyAppliance.MyFeature()) # error case (add_feature not callable from instance) for name in globals().keys(): print(name)