Compare commits

...

3 Commits

Author SHA1 Message Date
chacha
d20712a72f remove last references to DAB 2025-09-20 19:01:21 +02:00
chacha
2837b6439f cleaning 2025-09-20 18:57:32 +02:00
chacha
b4d6ed6130 add missing __init__ files 2025-09-20 18:48:17 +02:00
7 changed files with 75 additions and 73 deletions

Binary file not shown.

View File

View File

@@ -36,3 +36,5 @@ from .exception import (
InvalidFeatureInheritance,
FeatureNotBound,
)
__all__ = [name for name in globals() if not name.startswith("_")]

View File

View File

@@ -34,11 +34,11 @@ class _MetaAppliance(_MetaElement):
Copies the parent's `features` mapping when inheriting to keep it per-class.
"""
super().check_class(name, bases, namespace, extensions) # type: ignore[misc]
if "features" not in namespace["__DABSchema__"]:
namespace["__DABSchema__"]["features"] = {}
if "features" not in namespace["__LAMSchema__"]:
namespace["__LAMSchema__"]["features"] = {}
else:
namespace["__DABSchema__"]["features"] = copy(
namespace["__DABSchema__"]["features"]
namespace["__LAMSchema__"]["features"] = copy(
namespace["__LAMSchema__"]["features"]
)
@classmethod
@@ -78,8 +78,8 @@ class _MetaAppliance(_MetaElement):
- Else, if `_fvalue` is a Feature *class*, stage into `new_features`.
- Otherwise, it is a regular field: delegate to meta.process_new_field.
"""
if _fname in namespace["__DABSchema__"]["features"].keys():
if not issubclass(_fvalue, namespace["__DABSchema__"]["features"][_fname]):
if _fname in namespace["__LAMSchema__"]["features"].keys():
if not issubclass(_fvalue, namespace["__LAMSchema__"]["features"][_fname]):
raise InvalidFeatureInheritance(
f"Feature {_fname} is not an instance of {bases[0]}.{_fname}"
)
@@ -103,16 +103,16 @@ class _MetaAppliance(_MetaElement):
For each new/modified feature:
- bind it to `cls` (sets the feature's `_BoundAppliance`),
- register it under `cls.__DABSchema__["features"]`.
- register it under `cls.__LAMSchema__["features"]`.
"""
super().commit_fields(cls, name, bases, namespace, extensions) # type: ignore[misc]
for _ftname, _ftvalue in extensions["modified_features"].items():
_ftvalue._BoundAppliance = cls # pylint: disable=protected-access
cls.__DABSchema__["features"][_ftname] = _ftvalue
cls.__LAMSchema__["features"][_ftname] = _ftvalue
for _ftname, _ftvalue in extensions["new_features"].items():
_ftvalue._BoundAppliance = cls # pylint: disable=protected-access
cls.__DABSchema__["features"][_ftname] = _ftvalue
cls.__LAMSchema__["features"][_ftname] = _ftvalue
def finalize_instance(cls: Type, obj, extensions: dict[str, Any]):
"""
@@ -122,7 +122,7 @@ class _MetaAppliance(_MetaElement):
- Subclass replacements
- Dict overrides (class + patch dict)
"""
for fname, fdef in obj.__DABSchema__.get("features", {}).items():
for fname, fdef in obj.__LAMSchema__.get("features", {}).items():
# Case 1: plain class or subclass
if isinstance(fdef, type) and issubclass(fdef, Feature):
inst = fdef()
@@ -133,11 +133,11 @@ class _MetaAppliance(_MetaElement):
feat_cls, overrides = fdef
inst = feat_cls()
for field_name, new_val in overrides.items():
if field_name not in feat_cls.__DABSchema__:
if field_name not in feat_cls.__LAMSchema__:
raise InvalidFieldValue(
f"Feature '{fname}' has no field '{field_name}'"
)
field = feat_cls.__DABSchema__[field_name]
field = feat_cls.__LAMSchema__[field_name]
try:
check_type(
new_val,
@@ -150,7 +150,7 @@ class _MetaAppliance(_MetaElement):
f"expected {field.annotations}, got {new_val!r}"
) from exp
object.__setattr__(inst, field_name, LAMdeepfreeze(new_val))
inst.__DABSchema__[field_name] = FrozenLAMField(
inst.__LAMSchema__[field_name] = FrozenLAMField(
LAMField(field_name, new_val, field.annotations, field._info)
)
object.__setattr__(obj, fname, inst)
@@ -173,8 +173,8 @@ class _MetaAppliance(_MetaElement):
"""
# --- field overrides (unchanged) ---
for k, v in list(kwargs.items()):
if k in cls.__DABSchema__: # regular field
field = cls.__DABSchema__[k]
if k in cls.__LAMSchema__: # regular field
field = cls.__LAMSchema__[k]
try:
check_type(
v,
@@ -187,15 +187,15 @@ class _MetaAppliance(_MetaElement):
) from exp
object.__setattr__(obj, k, LAMdeepfreeze(v))
obj.__DABSchema__[k] = FrozenLAMField(
obj.__LAMSchema__[k] = FrozenLAMField(
LAMField(k, v, field.annotations, field._info)
)
kwargs.pop(k)
# --- feature overrides ---
for k, v in list(kwargs.items()):
if k in cls.__DABSchema__.get("features", {}):
base_feat_cls = cls.__DABSchema__["features"][k]
if k in cls.__LAMSchema__.get("features", {}):
base_feat_cls = cls.__LAMSchema__["features"][k]
# Case 1: subclass replacement (inheritance)
if isinstance(v, type) and issubclass(v, base_feat_cls):
@@ -205,13 +205,13 @@ class _MetaAppliance(_MetaElement):
f"Feature {v.__name__} is not bound to {cls.__name__}"
)
# record subclass into instance schema
obj.__DABSchema__["features"][k] = v
obj.__LAMSchema__["features"][k] = v
kwargs.pop(k)
# Case 2: dict override
elif isinstance(v, dict):
# store (class, override_dict) for finalize_instance
obj.__DABSchema__["features"][k] = (base_feat_cls, v)
obj.__LAMSchema__["features"][k] = (base_feat_cls, v)
kwargs.pop(k)
else:
@@ -227,7 +227,7 @@ class _MetaAppliance(_MetaElement):
raise FeatureNotBound(
f"Feature {v.__name__} is not bound to {cls.__name__}"
)
obj.__DABSchema__["features"][k] = v
obj.__LAMSchema__["features"][k] = v
kwargs.pop(k)
if kwargs:

View File

@@ -337,7 +337,7 @@ class _MetaElement(type):
modified_fields: Dict[str, Any] = {}
new_fields: Dict[str, LAMField[Any]] = {}
initializer: Optional[Callable[..., Any]] = None
__DABSchema__: dict[str, Any] = {}
__LAMSchema__: dict[str, Any] = {}
@classmethod
def check_class(
@@ -371,7 +371,7 @@ class _MetaElement(type):
"__DABSchema__ not found in base class, broken inheritance chain."
)
# copy inherited schema
namespace["__DABSchema__"] = copy(bases[0].__DABSchema__)
namespace["__DABSchema__"] = copy(bases[0].__LAMSchema__)
# force field without default value to be instantiated (with None)
if "__annotations__" in namespace:
@@ -569,7 +569,7 @@ class _MetaElement(type):
_check_initializer_safety(mcs.initializer)
init_fieldvalues = {}
init_fieldtypes = {}
for _fname, _fvalue in cls.__DABSchema__.items():
for _fname, _fvalue in cls.__LAMSchema__.items():
if isinstance(_fvalue, LAMField):
init_fieldvalues[_fname] = deepcopy(_fvalue.raw_value)
init_fieldtypes[_fname] = _fvalue.annotations
@@ -594,14 +594,14 @@ class _MetaElement(type):
try:
check_type(
_fvalue,
cls.__DABSchema__[_fname].annotations,
cls.__LAMSchema__[_fname].annotations,
collection_check_strategy=CollectionCheckStrategy.ALL_ITEMS,
)
except TypeCheckError as exp:
raise InvalidFieldValue(
f"Value of Field <{_fname}> is not of expected type {namespace['__annotations__'][_fname]}."
) from exp
cls.__DABSchema__[_fname].update_value(_fvalue)
cls.__LAMSchema__[_fname].update_value(_fvalue)
def __new__(
mcs: type["_MetaElement"],
@@ -638,12 +638,12 @@ class _MetaElement(type):
- For new fields: set the freshly built LAMField and record its source.
"""
for _fname, _fvalue in mcs.modified_fields.items():
cls.__DABSchema__[_fname] = deepcopy(bases[0].__DABSchema__[_fname])
cls.__DABSchema__[_fname].update_value(_fvalue)
cls.__LAMSchema__[_fname] = deepcopy(bases[0].__LAMSchema__[_fname])
cls.__LAMSchema__[_fname].update_value(_fvalue)
for _fname, _fvalue in mcs.new_fields.items():
_fvalue.add_source(cls)
cls.__DABSchema__[_fname] = _fvalue
cls.__LAMSchema__[_fname] = _fvalue
def __call__(cls: Type, *args: Any, **kw: Any): # intentionally untyped
"""BaseElement new instance"""
@@ -672,7 +672,7 @@ class _MetaElement(type):
Copies each LAMField.value to an instance attribute (deep-frozen view).
"""
for _fname, _fvalue in cls.__DABSchema__.items():
for _fname, _fvalue in cls.__LAMSchema__.items():
if isinstance(_fvalue, LAMField):
object.__setattr__(obj, _fname, _fvalue.value)
@@ -684,8 +684,8 @@ class _MetaElement(type):
Creates a per-instance `__DABSchema__` dict where each field is read-only.
"""
inst_schema = copy(obj.__DABSchema__)
for _fname, _fvalue in cls.__DABSchema__.items():
inst_schema = copy(obj.__LAMSchema__)
for _fname, _fvalue in cls.__LAMSchema__.items():
if isinstance(_fvalue, LAMField):
inst_schema[_fname] = FrozenLAMField(_fvalue)
@@ -735,7 +735,7 @@ class _MetaElement(type):
if key.startswith("_"): # allow private and dunder attrs
return orig_setattr(_self, key, value)
# block writes after init if key is readonly
if key in _self.__DABSchema__.keys():
if key in _self.__LAMSchema__.keys():
if key in _self.__dict__:
raise ReadOnlyField(f"{key} is read-only")
# elif key in _self.__DABSchema__["features"].keys():

View File

@@ -53,7 +53,7 @@ class MainTests(unittest.TestCase):
# field is in the object
self.assertIn(name, dir(obj))
# field is in the schema
self.assertIn(name, obj.__DABSchema__.keys())
self.assertIn(name, obj.__LAMSchema__.keys())
# field is readable
self.assertEqual(getattr(obj, name), default_value)
# field is read only
@@ -596,19 +596,19 @@ class MainTests(unittest.TestCase):
expected_default_value: str,
expected_type: type,
):
self.assertIn(field_name, appliance.__DABSchema__)
self.assertIn("doc", dir(appliance.__DABSchema__[field_name]))
self.assertEqual(appliance.__DABSchema__[field_name].doc, "")
self.assertIn("annotations", dir(appliance.__DABSchema__[field_name]))
self.assertEqual(appliance.__DABSchema__[field_name].annotations, expected_type)
self.assertIn("value", dir(appliance.__DABSchema__[field_name]))
self.assertEqual(appliance.__DABSchema__[field_name].value, expected_value)
self.assertIn("default_value", dir(appliance.__DABSchema__[field_name]))
self.assertIn(field_name, appliance.__LAMSchema__)
self.assertIn("doc", dir(appliance.__LAMSchema__[field_name]))
self.assertEqual(appliance.__LAMSchema__[field_name].doc, "")
self.assertIn("annotations", dir(appliance.__LAMSchema__[field_name]))
self.assertEqual(appliance.__LAMSchema__[field_name].annotations, expected_type)
self.assertIn("value", dir(appliance.__LAMSchema__[field_name]))
self.assertEqual(appliance.__LAMSchema__[field_name].value, expected_value)
self.assertIn("default_value", dir(appliance.__LAMSchema__[field_name]))
self.assertEqual(
appliance.__DABSchema__[field_name].default_value, expected_default_value
appliance.__LAMSchema__[field_name].default_value, expected_default_value
)
self.assertIn("constraints", dir(appliance.__DABSchema__[field_name]))
self.assertEqual(appliance.__DABSchema__[field_name].constraints, ())
self.assertIn("constraints", dir(appliance.__LAMSchema__[field_name]))
self.assertEqual(appliance.__LAMSchema__[field_name].constraints, ())
def test_immutable_fields_schema(self):
"""Testing first appliance level, and Field types (annotated)"""
@@ -809,40 +809,40 @@ class MainTests(unittest.TestCase):
app1 = Appliance1()
self.immutable_vars__test_field(app1, "StrVar", "default value", "test")
self.assertEqual(app1.__DABSchema__["StrVar"].doc, "foo1")
self.assertEqual(app1.__LAMSchema__["StrVar"].doc, "foo1")
self.immutable_vars__test_field(app1, "StrVar2", "default value2", "test2")
self.assertEqual(app1.__DABSchema__["StrVar2"].doc, "foo2")
self.assertEqual(app1.__LAMSchema__["StrVar2"].doc, "foo2")
self.immutable_vars__test_field(app1, "VarInt", 12, 13)
self.assertEqual(app1.__DABSchema__["VarInt"].doc, "foo3")
self.assertEqual(app1.__LAMSchema__["VarInt"].doc, "foo3")
self.immutable_vars__test_field(app1, "VarInt2", 21, 22)
self.assertEqual(app1.__DABSchema__["VarInt2"].doc, "foo4")
self.assertEqual(app1.__LAMSchema__["VarInt2"].doc, "foo4")
self.immutable_vars__test_field(app1, "VarFloat", 12.1, 32)
self.assertEqual(app1.__DABSchema__["VarFloat"].doc, "foo5")
self.assertEqual(app1.__LAMSchema__["VarFloat"].doc, "foo5")
self.immutable_vars__test_field(app1, "VarFloat2", 21.2, 42)
self.assertEqual(app1.__DABSchema__["VarFloat2"].doc, "foo6")
self.assertEqual(app1.__LAMSchema__["VarFloat2"].doc, "foo6")
self.immutable_vars__test_field(
app1, "VarComplex", complex(3, 5), complex(1, 2)
)
self.assertEqual(app1.__DABSchema__["VarComplex"].doc, "foo7")
self.assertEqual(app1.__LAMSchema__["VarComplex"].doc, "foo7")
self.immutable_vars__test_field(
app1, "VarComplex2", complex(8, 6), complex(3, 2)
)
self.assertEqual(app1.__DABSchema__["VarComplex2"].doc, "foo8")
self.assertEqual(app1.__LAMSchema__["VarComplex2"].doc, "foo8")
self.immutable_vars__test_field(app1, "VarBool", True, False)
self.assertEqual(app1.__DABSchema__["VarBool"].doc, "foo9")
self.assertEqual(app1.__LAMSchema__["VarBool"].doc, "foo9")
self.immutable_vars__test_field(app1, "VarBool2", False, True)
self.assertEqual(app1.__DABSchema__["VarBool2"].doc, "foo10")
self.assertEqual(app1.__LAMSchema__["VarBool2"].doc, "foo10")
self.immutable_vars__test_field(
app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("11f0 F1f2 ")
)
self.assertEqual(app1.__DABSchema__["VarBytes"].doc, "foo11")
self.assertEqual(app1.__LAMSchema__["VarBytes"].doc, "foo11")
self.immutable_vars__test_field(
app1,
"VarBytes2",
bytes.fromhex("2ff0 F7f2 "),
bytes.fromhex("11f0 F1e2 "),
)
self.assertEqual(app1.__DABSchema__["VarBytes2"].doc, "foo12")
self.assertEqual(app1.__LAMSchema__["VarBytes2"].doc, "foo12")
with self.assertRaises(dm.InvalidFieldAnnotation):
@@ -1008,10 +1008,10 @@ class MainTests(unittest.TestCase):
class Appliance3(Appliance2):
NewValue: str = "newval"
self.assertNotIn("NewValue", Appliance2.__DABSchema__)
self.assertNotIn("NewValue", app2.__DABSchema__)
self.assertNotIn("NewValue", Appliance1.__DABSchema__)
self.assertNotIn("NewValue", app1.__DABSchema__)
self.assertNotIn("NewValue", Appliance2.__LAMSchema__)
self.assertNotIn("NewValue", app2.__LAMSchema__)
self.assertNotIn("NewValue", Appliance1.__LAMSchema__)
self.assertNotIn("NewValue", app1.__LAMSchema__)
app3 = Appliance3()
self.immutable_vars__test_field(app3, "StrVar", "moded value", "test")
@@ -1638,19 +1638,19 @@ class MainTests(unittest.TestCase):
app1 = Appliance1()
self.assertIsInstance(Appliance1.__DABSchema__["VarStrOuter"], dm.LAMField)
self.assertIsInstance(app1.__DABSchema__["VarStrOuter"], dm.FrozenLAMField)
self.assertIn("Feature1", app1.__DABSchema__["features"])
self.assertIsInstance(Appliance1.__LAMSchema__["VarStrOuter"], dm.LAMField)
self.assertIsInstance(app1.__LAMSchema__["VarStrOuter"], dm.FrozenLAMField)
self.assertIn("Feature1", app1.__LAMSchema__["features"])
self.assertIn(
"VarStrInner", app1.__DABSchema__["features"]["Feature1"].__DABSchema__
"VarStrInner", app1.__LAMSchema__["features"]["Feature1"].__LAMSchema__
)
self.assertIsInstance(
app1.__DABSchema__["features"]["Feature1"].__DABSchema__["VarStrInner"],
app1.__LAMSchema__["features"]["Feature1"].__LAMSchema__["VarStrInner"],
dm.LAMField,
)
self.assertTrue(hasattr(app1, "Feature1"))
self.assertIsInstance(
app1.Feature1.__DABSchema__["VarStrInner"], dm.FrozenLAMField
app1.Feature1.__LAMSchema__["VarStrInner"], dm.FrozenLAMField
)
self.assertTrue(hasattr(app1.Feature1, "VarStrInner"))
@@ -1690,19 +1690,19 @@ class MainTests(unittest.TestCase):
app2 = Appliance2()
app3 = Appliance3()
self.assertIsInstance(Appliance1.__DABSchema__["VarStrOuter"], dm.LAMField)
self.assertIsInstance(app1.__DABSchema__["VarStrOuter"], dm.FrozenLAMField)
self.assertIn("Feature1", app1.__DABSchema__["features"])
self.assertIsInstance(Appliance1.__LAMSchema__["VarStrOuter"], dm.LAMField)
self.assertIsInstance(app1.__LAMSchema__["VarStrOuter"], dm.FrozenLAMField)
self.assertIn("Feature1", app1.__LAMSchema__["features"])
self.assertIn(
"VarStrInner", app1.__DABSchema__["features"]["Feature1"].__DABSchema__
"VarStrInner", app1.__LAMSchema__["features"]["Feature1"].__LAMSchema__
)
self.assertIsInstance(
app1.__DABSchema__["features"]["Feature1"].__DABSchema__["VarStrInner"],
app1.__LAMSchema__["features"]["Feature1"].__LAMSchema__["VarStrInner"],
dm.LAMField,
)
self.assertTrue(hasattr(app1, "Feature1"))
self.assertIsInstance(
app1.Feature1.__DABSchema__["VarStrInner"], dm.FrozenLAMField
app1.Feature1.__LAMSchema__["VarStrInner"], dm.FrozenLAMField
)
self.assertTrue(hasattr(app1.Feature1, "VarStrInner"))
self.assertEqual(app1.VarStrOuter, "testvalue APPLIANCE1")