Files
dabmodel/test/test_model.py
2025-09-05 23:04:16 +02:00

1182 lines
56 KiB
Python

# 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 <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
import unittest
import sys
import subprocess
from os import chdir, environ
from pathlib import Path
import textwrap
from typing import List, Optional, Dict, Union, Tuple, Set, FrozenSet, TypeVar, Generic, Any, Annotated
from pprint import pprint
print(__name__)
print(__package__)
from src import dabmodel as dm
testdir_path = Path(__file__).parent.resolve()
chdir(testdir_path.parent.resolve())
def test_initializer_safe_testfc():
eval("print('hi')")
class TestConfigWithoutEnabledFlag(unittest.TestCase):
def setUp(self):
print("\n->", unittest.TestCase.id(self))
def immutable_vars__test_field(self, obj: Any, name: str, default_value: Any, test_value: Any):
# field is not in the class
self.assertNotIn(name, dir(obj.__class__))
# field is in the object
self.assertIn(name, dir(obj))
# field is in the schema
self.assertIn(name, obj.__DABSchema__.keys())
# field is readable
self.assertEqual(getattr(obj, name), default_value)
# field is read only
with self.assertRaises(dm.ReadOnlyField):
setattr(obj, name, test_value)
def test_immutable_fields(self):
"""Testing first appliance level, and Field types (simple)"""
# class can be created
class Appliance1(dm.BaseAppliance):
StrVar: str = "default value"
StrVar2: str = "default value2"
VarInt: int = 12
VarInt2: int = 21
VarFloat: float = 12.1
VarFloat2: float = 21.2
VarComplex: complex = complex(3, 5)
VarComplex2: complex = complex(8, 6)
VarBool: bool = True
VarBool2: bool = False
VarBytes: bytes = bytes.fromhex("2Ef0 F1f2 ")
VarBytes2: bytes = bytes.fromhex("2ff0 F7f2 ")
app1 = Appliance1()
self.immutable_vars__test_field(app1, "StrVar", "default value", "test")
self.immutable_vars__test_field(app1, "StrVar2", "default value2", "test2")
self.immutable_vars__test_field(app1, "VarInt", 12, 13)
self.immutable_vars__test_field(app1, "VarInt2", 21, 22)
self.immutable_vars__test_field(app1, "VarFloat", 12.1, 32)
self.immutable_vars__test_field(app1, "VarFloat2", 21.2, 42)
self.immutable_vars__test_field(app1, "VarComplex", complex(3, 5), complex(1, 2))
self.immutable_vars__test_field(app1, "VarComplex2", complex(8, 6), complex(3, 2))
self.immutable_vars__test_field(app1, "VarBool", True, False)
self.immutable_vars__test_field(app1, "VarBool2", False, True)
self.immutable_vars__test_field(app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("11f0 F1f2 "))
self.immutable_vars__test_field(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("11f0 F1e2 "))
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: str = 12
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: int = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: float = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: complex = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: bool = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: bytes = "value"
def test_annotation(self):
"""Testing first appliance level, and Field types (simple annotations)"""
# class can be created if annotation is a string
class Appliance1(dm.BaseAppliance):
StrVar: "str" = "default value"
StrVar2: "str" = "default value2"
VarInt: "int" = 12
VarInt2: "int" = 21
VarFloat: "float" = 12.1
VarFloat2: "float" = 21.2
VarComplex: "complex" = complex(3, 5)
VarComplex2: "complex" = complex(8, 6)
VarBool: "bool" = True
VarBool2: "bool" = False
VarBytes: "bytes" = bytes.fromhex("2Ef0 F1f2 ")
VarBytes2: "bytes" = bytes.fromhex("2ff0 F7f2 ")
app1 = Appliance1()
self.immutable_vars__test_field(app1, "StrVar", "default value", "test")
self.immutable_vars__test_field(app1, "StrVar2", "default value2", "test2")
self.immutable_vars__test_field(app1, "VarInt", 12, 13)
self.immutable_vars__test_field(app1, "VarInt2", 21, 22)
self.immutable_vars__test_field(app1, "VarFloat", 12.1, 32)
self.immutable_vars__test_field(app1, "VarFloat2", 21.2, 42)
self.immutable_vars__test_field(app1, "VarComplex", complex(3, 5), complex(1, 2))
self.immutable_vars__test_field(app1, "VarComplex2", complex(8, 6), complex(3, 2))
self.immutable_vars__test_field(app1, "VarBool", True, False)
self.immutable_vars__test_field(app1, "VarBool2", False, True)
self.immutable_vars__test_field(app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("11f0 F1f2 "))
self.immutable_vars__test_field(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("11f0 F1e2 "))
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "str" = 12
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "int" = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "float" = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "complex" = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "bool" = "value"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "bytes" = "value"
# class cannot be created if not annotated field
with self.assertRaises(dm.NotAnnotatedField):
class _(dm.BaseAppliance):
_ = "default value"
def test_optionnal(self):
"""Testing first appliance level, and Field types (Optionnal annotations)"""
# class can be created with Optionnal (and variant)
class Appliance1(dm.BaseAppliance):
StrVar: Optional[str] = "default value"
StrVar2: Optional[str]
StrVar3: Union[None | str] = "default value"
StrVar4: Union[None | str]
StrVar5: None | str = "default value"
StrVar6: None | str
app1 = Appliance1()
self.immutable_vars__test_field(app1, "StrVar", "default value", "123")
self.immutable_vars__test_field(app1, "StrVar2", None, "123")
self.immutable_vars__test_field(app1, "StrVar3", "default value", "123")
self.immutable_vars__test_field(app1, "StrVar4", None, "123")
self.immutable_vars__test_field(app1, "StrVar5", "default value", "123")
self.immutable_vars__test_field(app1, "StrVar6", None, "123")
# class can be created with Optionnal (and variant), as string annotation
class Appliance2(dm.BaseAppliance):
StrVar: "Optional[str]" = "default value"
StrVar2: "Optional[str]"
StrVar3: "Union[None | str]" = "default value"
StrVar4: "Union[None | str]"
StrVar5: "None | str" = "default value"
StrVar6: "None | str"
app2 = Appliance2()
self.immutable_vars__test_field(app2, "StrVar", "default value", "123")
self.immutable_vars__test_field(app2, "StrVar2", None, "123")
self.immutable_vars__test_field(app2, "StrVar3", "default value", "123")
self.immutable_vars__test_field(app2, "StrVar4", None, "123")
self.immutable_vars__test_field(app2, "StrVar5", "default value", "123")
self.immutable_vars__test_field(app2, "StrVar6", None, "123")
# @unittest.skip
def test_containers__set(self):
"""Testing first appliance level, and Field types (Set)"""
# class can be created with set
class Appliance1(dm.BaseAppliance):
testVar: Set[int] = {1, 2}
testVar2: Set[str] = {"a", "b"}
testVar3: Set[float] = {0.5, 0.456, 12}
testVar4: "Set[str]" = {"a", "c"}
testVar5: set[str] = {"a", "b"}
testVar6: "set[str]" = {"a", "b"}
testVar7: set[int | str] = {1, 2, "abcd", "efg"}
app1 = Appliance1()
self.immutable_vars__test_field(app1, "testVar", {1, 2}, {1, 5})
self.assertEqual(app1.testVar, {2, 1})
self.immutable_vars__test_field(app1, "testVar2", {"a", "b"}, {"h", "c"})
self.assertEqual(app1.testVar2, {"b", "a"})
self.immutable_vars__test_field(app1, "testVar3", {0.5, 0.456, 12}, {0.9, 0.4156, 11})
self.assertEqual(app1.testVar3, {0.456, 0.5, 12})
self.immutable_vars__test_field(app1, "testVar4", {"a", "c"}, {"h", "e"})
self.immutable_vars__test_field(app1, "testVar5", {"a", "b"}, {"h", "c"})
self.immutable_vars__test_field(app1, "testVar6", {"a", "b"}, {"h", "c"})
self.immutable_vars__test_field(app1, "testVar7", {1, 2, "abcd", "efg"}, {"h", "c"})
# must work
sorted(app1.testVar)
with self.assertRaises(AttributeError):
app1.testVar.add(3)
with self.assertRaises(AttributeError):
app1.testVar4.add("coucou")
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: Set[int] = {"a"}
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "Set[int]" = {"a"}
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: Set = {1, 2}
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: "Set" = {1, 2}
# Hacky part !
# set() are randomly ordered, and typeguard can be configured to only check 1st element of containers.
# we need to make sure it is properly configured, so we are expecting it to detect wrong type at any element
# this is why we need to run the code multiple time with a new interpreter that will use a different random seed
code = textwrap.dedent(
r"""
from src import dabmodel as dm
from typing import Set
try:
class Yours(dm.BaseAppliance):
My1: Set[int] = {99, 1, 3, "a", 5,6}
except dm.InvalidFieldValue as ex:
raise SystemExit(2)
raise SystemExit(0)
"""
)
for i in range(15):
env = environ.copy()
env["PYTHONHASHSEED"] = str(i)
res = subprocess.run([sys.executable, "-c", code], env=env)
self.assertEqual(res.returncode, 2)
# @unittest.skip
def test_containers__frozenset(self):
"""Testing first appliance level, and Field types (FrozenSet)"""
# class can be created with set
class Appliance1(dm.BaseAppliance):
testVar: frozenset[int] = frozenset({1, 2})
testVar2: frozenset[str] = frozenset({"a", "b"})
testVar3: frozenset[float] = frozenset({0.5, 0.456, 12})
testVar4: "frozenset[str]" = frozenset({"a", "c"})
testVar5: FrozenSet[int] = frozenset({1, 2})
testVar6: "FrozenSet[int]" = frozenset({1, 2})
testVar7: FrozenSet[int | str] = frozenset({1, 2, "abcd", "efg"})
app1 = Appliance1()
self.immutable_vars__test_field(app1, "testVar", {1, 2}, {1, 5})
self.assertEqual(app1.testVar, {2, 1})
self.immutable_vars__test_field(app1, "testVar2", {"a", "b"}, {"h", "c"})
self.assertEqual(app1.testVar2, {"b", "a"})
self.immutable_vars__test_field(app1, "testVar3", {0.5, 0.456, 12}, {0.9, 0.4156, 11})
self.assertEqual(app1.testVar3, {0.456, 0.5, 12})
self.immutable_vars__test_field(app1, "testVar4", {"a", "c"}, {"h", "e"})
self.immutable_vars__test_field(app1, "testVar5", {1, 2}, {1, 5})
self.immutable_vars__test_field(app1, "testVar6", {1, 2}, {1, 5})
self.immutable_vars__test_field(app1, "testVar7", {1, 2, "abcd", "efg"}, {1, 5})
# must work
sorted(app1.testVar)
with self.assertRaises(AttributeError):
app1.testVar.add(3)
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: FrozenSet[int] = {"a"}
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "FrozenSet[int]" = {"a"}
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: FrozenSet = {1, 2}
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: "FrozenSet" = {1, 2}
# Hacky part !
# set() are randomly ordered, and typeguard can be configured to only check 1st element of containers.
# we need to make sure it is properly configured, so we are expecting it to detect wrong type at any element
# this is why we need to run the code multiple time with a new interpreter that will use a different random seed
code = textwrap.dedent(
r"""
from src import dabmodel as dm
from typing import FrozenSet
try:
class Yours(dm.BaseAppliance):
My1: FrozenSet[int] = frozenset({99, 1, 3, "a", 5,6})
except dm.InvalidFieldValue as ex:
raise SystemExit(2)
raise SystemExit(0)
"""
)
for i in range(15):
env = environ.copy()
env["PYTHONHASHSEED"] = str(i)
res = subprocess.run([sys.executable, "-c", code], env=env)
self.assertEqual(res.returncode, 2)
def test_containers__list(self):
"""Testing first appliance level, and Field types (List)"""
# class can be created with list
class Appliance1(dm.BaseAppliance):
testVar: List[int] = [1, 2]
testVar2: List[str] = ["a", "b"]
testVar3: List[float] = [0.5, 0.456, 12]
testVar4: "List[str]" = ["a", "c"]
testVar5: list[str] = ["a", "b"]
testVar6: "list[str]" = ["a", "b"]
testVar7: List[Union[int, str]] = [1, 2, 3, "one", "two", "three"]
app1 = Appliance1()
# Note: lists are converted to tuples
self.immutable_vars__test_field(app1, "testVar", (1, 2), [1, 5])
self.immutable_vars__test_field(app1, "testVar2", ("a", "b"), ["h", "c"])
self.immutable_vars__test_field(app1, "testVar3", (0.5, 0.456, 12), [0.9, 0.4156, 11])
self.immutable_vars__test_field(app1, "testVar4", ("a", "c"), ["h", "e"])
self.immutable_vars__test_field(app1, "testVar5", ("a", "b"), ["h", "c"])
self.immutable_vars__test_field(app1, "testVar6", ("a", "b"), ["h", "c"])
self.immutable_vars__test_field(app1, "testVar7", (1, 2, 3, "one", "two", "three"), ["h", "c"])
# must work
sorted(app1.testVar)
with self.assertRaises(AttributeError):
app1.testVar.append(3)
with self.assertRaises(AttributeError):
app1.testVar.pop()
with self.assertRaises(AttributeError):
app1.testVar.sort()
with self.assertRaises(AttributeError):
app1.testVar4.append("coucou")
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: List[int] = ["a"]
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "List[int]" = ["a"]
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: List = [1, 2]
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: "List" = [1, 2]
def test_containers__dict(self):
"""Testing first appliance level, and Field types (Dict)"""
# class can be created with dict
class Appliance1(dm.BaseAppliance):
testVar: Dict[int, str] = {1: "a", 2: "b"}
testVar2: "Dict[int, str]" = {1: "c", 99: "d"}
app1 = Appliance1()
self.immutable_vars__test_field(app1, "testVar", {1: "a", 2: "b"}, {1: "", 99: "i"})
self.immutable_vars__test_field(app1, "testVar2", {1: "c", 99: "d"}, {10: "", 50: "i"})
# TODO: wrap exception type
with self.assertRaises(TypeError):
app1.testVar[58] = "aaa"
# TODO: wrap exception type
with self.assertRaises(TypeError):
app1.testVar[1] = "ggg"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: Dict[int, str] = {1: 64, 2: "b"}
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "Dict[int, str]" = {1: 64, 2: "b"}
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: Dict = {1: 64, 2: "b"}
# annotation is parsed before the library can do anything, so the exception can only be TypeError
with self.assertRaises(TypeError):
class _(dm.BaseAppliance):
_: Dict[int] = {1: 64, 2: "b"}
# annotation is parsed before the library can do anything, so the exception can only be TypeError
with self.assertRaises(TypeError):
class _(dm.BaseAppliance):
_: "Dict[int]" = {1: 64, 2: "b"}
def test_containers__tuple(self):
"""Testing first appliance level, and Field types (Tuple)"""
# class can be created with list
class Appliance1(dm.BaseAppliance):
testVar: Tuple[int, ...] = (1, 2)
testVar2: Tuple[str, ...] = ("a", "b")
testVar3: Tuple[float, ...] = (0.5, 0.456, 12)
testVar4: "Tuple[str,...]" = ("a", "c")
testVar5: tuple[str, ...] = ("a", "b")
testVar6: "tuple[str,...]" = ("a", "b")
testVar7: Tuple[int, str] = (1, "b")
# testVar7: Tuple[Union[int, str]] = (1, 2, 3, "one", "two", "three")
app1 = Appliance1()
self.immutable_vars__test_field(app1, "testVar", (1, 2), (1, 5))
self.immutable_vars__test_field(app1, "testVar2", ("a", "b"), ("h", "c"))
self.immutable_vars__test_field(app1, "testVar3", (0.5, 0.456, 12), (0.9, 0.4156, 11))
self.immutable_vars__test_field(app1, "testVar4", ("a", "c"), ("h", "e"))
self.immutable_vars__test_field(app1, "testVar5", ("a", "b"), ("h", "c"))
self.immutable_vars__test_field(app1, "testVar6", ("a", "b"), ("h", "c"))
self.immutable_vars__test_field(app1, "testVar7", (1, "b"), (7, "h"))
# must work
sorted(app1.testVar)
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: Tuple[int] = "a"
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "Tuple[int]" = "a"
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: Tuple = (1, 2)
with self.assertRaises(dm.IncompletelyAnnotatedField):
class _(dm.BaseAppliance):
_: "Tuple" = (1, 2)
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "Tuple[int,...]" = (1, "a")
with self.assertRaises(dm.InvalidFieldValue):
class _(dm.BaseAppliance):
_: "tuple[int,...]" = (1, "a")
def check_immutable_fields_schema(
self, appliance: dm.BaseAppliance, field_name: str, expected_value: str, 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.assertEqual(appliance.__DABSchema__[field_name].default_value, expected_default_value)
self.assertIn("constraints", dir(appliance.__DABSchema__[field_name]))
self.assertEqual(appliance.__DABSchema__[field_name].constraints, ())
def test_immutable_fields_schema(self):
"""Testing first appliance level, and Field types (annotated)"""
# class can be created
class Appliance1(dm.BaseAppliance):
StrVar: "str" = "default value"
StrVar2: "str" = "default value2"
VarInt: "int" = 12
VarInt2: "int" = 21
VarFloat: "float" = 12.1
VarFloat2: "float" = 21.2
VarComplex: "complex" = complex(3, 5)
VarComplex2: "complex" = complex(8, 6)
VarBool: "bool" = True
VarBool2: "bool" = False
VarBytes: "bytes" = bytes.fromhex("2Ef0 F1f2 ")
VarBytes2: "bytes" = bytes.fromhex("2ff0 F7f2 ")
app1 = Appliance1()
self.assertIn("__DABSchema__", dir(app1))
self.assertIn("__DABSchema__", app1.__dict__)
self.check_immutable_fields_schema(app1, "StrVar", "default value", "default value", str)
self.check_immutable_fields_schema(app1, "StrVar2", "default value2", "default value2", str)
self.check_immutable_fields_schema(app1, "VarInt", 12, 12, int)
self.check_immutable_fields_schema(app1, "VarInt2", 21, 21, int)
self.check_immutable_fields_schema(app1, "VarFloat", 12.1, 12.1, float)
self.check_immutable_fields_schema(app1, "VarFloat2", 21.2, 21.2, float)
self.check_immutable_fields_schema(app1, "VarComplex", complex(3, 5), complex(3, 5), complex)
self.check_immutable_fields_schema(app1, "VarComplex2", complex(8, 6), complex(8, 6), complex)
self.check_immutable_fields_schema(app1, "VarBool", True, True, bool)
self.check_immutable_fields_schema(app1, "VarBool2", False, False, bool)
self.check_immutable_fields_schema(app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("2Ef0 F1f2 "), bytes)
self.check_immutable_fields_schema(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("2ff0 F7f2 "), bytes)
def test_container_field_schema(self):
"""Testing first appliance level, and Field types (annotated)"""
# class can be created
class Appliance1(dm.BaseAppliance):
ListStr: list[str] = ["val1", "val2"]
ListStr2: "list[str]" = ["val3", "val4"]
Dict1: dict[int, float] = {1: 1.1, 4: 7.6, 91: 23.6}
Dict2: "dict[str, str]" = {"1": "1.1", "4": "7.6", "91": "23.6"}
Tuple1: "tuple[str,...]" = ("a", "c")
Tuple2: tuple[str, ...] = ("a", "b")
FrozenSet1: frozenset[int] = frozenset({1, 2})
FrozenSet2: "frozenset[int]" = frozenset({1, 2})
Set1: set[int] = set({1, 2})
Set2: "set[int]" = set({1, 2})
app1 = Appliance1()
self.assertIn("__DABSchema__", dir(app1))
self.assertIn("__DABSchema__", app1.__dict__)
self.check_immutable_fields_schema(app1, "ListStr", ("val1", "val2"), ("val1", "val2"), list[str])
self.check_immutable_fields_schema(app1, "ListStr2", ("val3", "val4"), ("val3", "val4"), list[str])
self.check_immutable_fields_schema(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, dict[int, float])
self.check_immutable_fields_schema(
app1, "Dict2", {"1": "1.1", "4": "7.6", "91": "23.6"}, {"1": "1.1", "4": "7.6", "91": "23.6"}, dict[str, str]
)
self.check_immutable_fields_schema(app1, "Tuple1", ("a", "c"), ("a", "c"), tuple[str, ...])
self.check_immutable_fields_schema(app1, "Tuple2", ("a", "b"), ("a", "b"), tuple[str, ...])
self.check_immutable_fields_schema(app1, "FrozenSet1", frozenset({1, 2}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app1, "FrozenSet2", frozenset({1, 2}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app1, "Set1", frozenset({1, 2}), frozenset({1, 2}), set[int])
self.check_immutable_fields_schema(app1, "Set2", frozenset({1, 2}), frozenset({1, 2}), set[int])
# same test with Typing types (list -> List ...)
# class can be created
class Appliance1(dm.BaseAppliance):
ListStr: List[str] = ["val1", "val2"]
ListStr2: "List[str]" = ["val3", "val4"]
Dict1: Dict[int, float] = {1: 1.1, 4: 7.6, 91: 23.6}
Dict2: "Dict[str, str]" = {"1": "1.1", "4": "7.6", "91": "23.6"}
Tuple1: "Tuple[str,...]" = ("a", "c")
Tuple2: Tuple[str, ...] = ("a", "b")
FrozenSet1: FrozenSet[int] = frozenset({1, 2})
FrozenSet2: "FrozenSet[int]" = frozenset({1, 2})
Set1: Set[int] = set({1, 2})
Set2: "Set[int]" = set({1, 2})
app1 = Appliance1()
self.assertIn("__DABSchema__", dir(app1))
self.assertIn("__DABSchema__", app1.__dict__)
self.check_immutable_fields_schema(app1, "ListStr", ("val1", "val2"), ("val1", "val2"), List[str])
self.check_immutable_fields_schema(app1, "ListStr2", ("val3", "val4"), ("val3", "val4"), List[str])
self.check_immutable_fields_schema(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, Dict[int, float])
self.check_immutable_fields_schema(
app1, "Dict2", {"1": "1.1", "4": "7.6", "91": "23.6"}, {"1": "1.1", "4": "7.6", "91": "23.6"}, Dict[str, str]
)
self.check_immutable_fields_schema(app1, "Tuple1", ("a", "c"), ("a", "c"), Tuple[str, ...])
self.check_immutable_fields_schema(app1, "Tuple2", ("a", "b"), ("a", "b"), Tuple[str, ...])
self.check_immutable_fields_schema(app1, "FrozenSet1", frozenset({1, 2}), frozenset({1, 2}), FrozenSet[int])
self.check_immutable_fields_schema(app1, "FrozenSet2", frozenset({1, 2}), frozenset({1, 2}), FrozenSet[int])
self.check_immutable_fields_schema(app1, "Set1", frozenset({1, 2}), frozenset({1, 2}), Set[int])
self.check_immutable_fields_schema(app1, "Set2", frozenset({1, 2}), frozenset({1, 2}), Set[int])
def test_immutable_fields_annotated(self):
"""Testing first appliance level, and Field types (annotated)"""
# class can be created
class Appliance1(dm.BaseAppliance):
StrVar: Annotated[str, dm.DABFieldInfo(doc="foo1")] = "default value"
StrVar2: Annotated[str, dm.DABFieldInfo(doc="foo2")] = "default value2"
VarInt: Annotated[int, dm.DABFieldInfo(doc="foo3")] = 12
VarInt2: Annotated[int, dm.DABFieldInfo(doc="foo4")] = 21
VarFloat: Annotated[float, dm.DABFieldInfo(doc="foo5")] = 12.1
VarFloat2: Annotated[float, dm.DABFieldInfo(doc="foo6")] = 21.2
VarComplex: Annotated[complex, dm.DABFieldInfo(doc="foo7")] = complex(3, 5)
VarComplex2: Annotated[complex, dm.DABFieldInfo(doc="foo8")] = complex(8, 6)
VarBool: Annotated[bool, dm.DABFieldInfo(doc="foo9")] = True
VarBool2: Annotated[bool, dm.DABFieldInfo(doc="foo10")] = False
VarBytes: Annotated[bytes, dm.DABFieldInfo(doc="foo11")] = bytes.fromhex("2Ef0 F1f2 ")
VarBytes2: Annotated[bytes, dm.DABFieldInfo(doc="foo12")] = bytes.fromhex("2ff0 F7f2 ")
app1 = Appliance1()
self.immutable_vars__test_field(app1, "StrVar", "default value", "test")
self.assertEqual(app1.__DABSchema__["StrVar"].doc, "foo1")
self.immutable_vars__test_field(app1, "StrVar2", "default value2", "test2")
self.assertEqual(app1.__DABSchema__["StrVar2"].doc, "foo2")
self.immutable_vars__test_field(app1, "VarInt", 12, 13)
self.assertEqual(app1.__DABSchema__["VarInt"].doc, "foo3")
self.immutable_vars__test_field(app1, "VarInt2", 21, 22)
self.assertEqual(app1.__DABSchema__["VarInt2"].doc, "foo4")
self.immutable_vars__test_field(app1, "VarFloat", 12.1, 32)
self.assertEqual(app1.__DABSchema__["VarFloat"].doc, "foo5")
self.immutable_vars__test_field(app1, "VarFloat2", 21.2, 42)
self.assertEqual(app1.__DABSchema__["VarFloat2"].doc, "foo6")
self.immutable_vars__test_field(app1, "VarComplex", complex(3, 5), complex(1, 2))
self.assertEqual(app1.__DABSchema__["VarComplex"].doc, "foo7")
self.immutable_vars__test_field(app1, "VarComplex2", complex(8, 6), complex(3, 2))
self.assertEqual(app1.__DABSchema__["VarComplex2"].doc, "foo8")
self.immutable_vars__test_field(app1, "VarBool", True, False)
self.assertEqual(app1.__DABSchema__["VarBool"].doc, "foo9")
self.immutable_vars__test_field(app1, "VarBool2", False, True)
self.assertEqual(app1.__DABSchema__["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.immutable_vars__test_field(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("11f0 F1e2 "))
self.assertEqual(app1.__DABSchema__["VarBytes2"].doc, "foo12")
with self.assertRaises(dm.InvalidFieldAnnotation):
class _(dm.BaseAppliance):
_: Annotated[str, "foo2"] = "default value2"
# annotation is parsed before the library can do anything, so the exception can only be TypeError
with self.assertRaises(TypeError):
class _(dm.BaseAppliance):
_: Annotated[str] = "default value2"
def test_immutable_fields_inheritance(self):
"""Testing first appliance level, and Field types (simple)"""
# class can be created
class Appliance1(dm.BaseAppliance):
StrVar: str = "default value"
StrVar2: str = "default value2"
VarInt: int = 12
VarInt2: int = 21
VarFloat: float = 12.1
VarFloat2: float = 21.2
VarComplex: complex = complex(3, 5)
VarComplex2: complex = complex(8, 6)
VarBool: bool = True
VarBool2: bool = False
VarBytes: bytes = bytes.fromhex("2Ef0 F1f2 ")
VarBytes2: bytes = bytes.fromhex("2ff0 F7f2 ")
class Appliance2(Appliance1):
StrVar = "moded value"
StrVar2 = "moded value2"
VarInt = 54
VarInt2 = 23
VarFloat = 2.6
VarFloat2 = 1.5
VarComplex = complex(7, 1)
VarComplex2 = complex(3, 0)
VarBool = False
VarBool2 = True
VarBytes = bytes.fromhex("21f0 e1f2 ")
VarBytes2 = bytes.fromhex("2df0 F672 ")
app1 = Appliance1()
self.immutable_vars__test_field(app1, "StrVar", "default value", "test")
self.immutable_vars__test_field(app1, "StrVar2", "default value2", "test2")
self.immutable_vars__test_field(app1, "VarInt", 12, 13)
self.immutable_vars__test_field(app1, "VarInt2", 21, 22)
self.immutable_vars__test_field(app1, "VarFloat", 12.1, 32)
self.immutable_vars__test_field(app1, "VarFloat2", 21.2, 42)
self.immutable_vars__test_field(app1, "VarComplex", complex(3, 5), complex(1, 2))
self.immutable_vars__test_field(app1, "VarComplex2", complex(8, 6), complex(3, 2))
self.immutable_vars__test_field(app1, "VarBool", True, False)
self.immutable_vars__test_field(app1, "VarBool2", False, True)
self.immutable_vars__test_field(app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("11f0 F1f2 "))
self.immutable_vars__test_field(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("11f0 F1e2 "))
self.check_immutable_fields_schema(app1, "StrVar", "default value", "default value", str)
self.check_immutable_fields_schema(app1, "StrVar2", "default value2", "default value2", str)
self.check_immutable_fields_schema(app1, "VarInt", 12, 12, int)
self.check_immutable_fields_schema(app1, "VarInt2", 21, 21, int)
self.check_immutable_fields_schema(app1, "VarFloat", 12.1, 12.1, float)
self.check_immutable_fields_schema(app1, "VarFloat2", 21.2, 21.2, float)
self.check_immutable_fields_schema(app1, "VarComplex", complex(3, 5), complex(3, 5), complex)
self.check_immutable_fields_schema(app1, "VarComplex2", complex(8, 6), complex(8, 6), complex)
self.check_immutable_fields_schema(app1, "VarBool", True, True, bool)
self.check_immutable_fields_schema(app1, "VarBool2", False, False, bool)
self.check_immutable_fields_schema(app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("2Ef0 F1f2 "), bytes)
self.check_immutable_fields_schema(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("2ff0 F7f2 "), bytes)
app2 = Appliance2()
self.immutable_vars__test_field(app2, "StrVar", "moded value", "test")
self.immutable_vars__test_field(app2, "StrVar2", "moded value2", "test2")
self.immutable_vars__test_field(app2, "VarInt", 54, 13)
self.immutable_vars__test_field(app2, "VarInt2", 23, 22)
self.immutable_vars__test_field(app2, "VarFloat", 2.6, 32)
self.immutable_vars__test_field(app2, "VarFloat2", 1.5, 42)
self.immutable_vars__test_field(app2, "VarComplex", complex(7, 1), complex(1, 2))
self.immutable_vars__test_field(app2, "VarComplex2", complex(3, 0), complex(3, 2))
self.immutable_vars__test_field(app2, "VarBool", False, False)
self.immutable_vars__test_field(app2, "VarBool2", True, True)
self.immutable_vars__test_field(app2, "VarBytes", bytes.fromhex("21f0 e1f2 "), bytes.fromhex("11f0 F1f2 "))
self.immutable_vars__test_field(app2, "VarBytes2", bytes.fromhex("2df0 F672 "), bytes.fromhex("11f0 F1e2 "))
self.check_immutable_fields_schema(app2, "StrVar", "moded value", "default value", str)
self.check_immutable_fields_schema(app2, "StrVar2", "moded value2", "default value2", str)
self.check_immutable_fields_schema(app2, "VarInt", 54, 12, int)
self.check_immutable_fields_schema(app2, "VarInt2", 23, 21, int)
self.check_immutable_fields_schema(app2, "VarFloat", 2.6, 12.1, float)
self.check_immutable_fields_schema(app2, "VarFloat2", 1.5, 21.2, float)
self.check_immutable_fields_schema(app2, "VarComplex", complex(7, 1), complex(3, 5), complex)
self.check_immutable_fields_schema(app2, "VarComplex2", complex(3, 0), complex(8, 6), complex)
self.check_immutable_fields_schema(app2, "VarBool", False, True, bool)
self.check_immutable_fields_schema(app2, "VarBool2", True, False, bool)
self.check_immutable_fields_schema(app2, "VarBytes", bytes.fromhex("21f0 e1f2 "), bytes.fromhex("2Ef0 F1f2 "), bytes)
self.check_immutable_fields_schema(app2, "VarBytes2", bytes.fromhex("2df0 F672 "), bytes.fromhex("2ff0 F7f2 "), bytes)
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__)
app3 = Appliance3()
self.immutable_vars__test_field(app3, "StrVar", "moded value", "test")
self.immutable_vars__test_field(app3, "StrVar2", "moded value2", "test2")
self.immutable_vars__test_field(app3, "VarInt", 54, 13)
self.immutable_vars__test_field(app3, "VarInt2", 23, 22)
self.immutable_vars__test_field(app3, "VarFloat", 2.6, 32)
self.immutable_vars__test_field(app3, "VarFloat2", 1.5, 42)
self.immutable_vars__test_field(app3, "VarComplex", complex(7, 1), complex(1, 2))
self.immutable_vars__test_field(app3, "VarComplex2", complex(3, 0), complex(3, 2))
self.immutable_vars__test_field(app3, "VarBool", False, False)
self.immutable_vars__test_field(app3, "VarBool2", True, True)
self.immutable_vars__test_field(app3, "VarBytes", bytes.fromhex("21f0 e1f2 "), bytes.fromhex("11f0 F1f2 "))
self.immutable_vars__test_field(app3, "VarBytes2", bytes.fromhex("2df0 F672 "), bytes.fromhex("11f0 F1e2 "))
self.immutable_vars__test_field(app3, "NewValue", "newval", "test")
self.check_immutable_fields_schema(app3, "StrVar", "moded value", "default value", str)
self.check_immutable_fields_schema(app3, "StrVar2", "moded value2", "default value2", str)
self.check_immutable_fields_schema(app3, "VarInt", 54, 12, int)
self.check_immutable_fields_schema(app3, "VarInt2", 23, 21, int)
self.check_immutable_fields_schema(app3, "VarFloat", 2.6, 12.1, float)
self.check_immutable_fields_schema(app3, "VarFloat2", 1.5, 21.2, float)
self.check_immutable_fields_schema(app3, "VarComplex", complex(7, 1), complex(3, 5), complex)
self.check_immutable_fields_schema(app3, "VarComplex2", complex(3, 0), complex(8, 6), complex)
self.check_immutable_fields_schema(app3, "VarBool", False, True, bool)
self.check_immutable_fields_schema(app3, "VarBool2", True, False, bool)
self.check_immutable_fields_schema(app3, "VarBytes", bytes.fromhex("21f0 e1f2 "), bytes.fromhex("2Ef0 F1f2 "), bytes)
self.check_immutable_fields_schema(app3, "VarBytes2", bytes.fromhex("2df0 F672 "), bytes.fromhex("2ff0 F7f2 "), bytes)
self.check_immutable_fields_schema(app3, "NewValue", "newval", "newval", str)
self.immutable_vars__test_field(app1, "StrVar", "default value", "test")
self.immutable_vars__test_field(app1, "StrVar2", "default value2", "test2")
self.immutable_vars__test_field(app1, "VarInt", 12, 13)
self.immutable_vars__test_field(app1, "VarInt2", 21, 22)
self.immutable_vars__test_field(app1, "VarFloat", 12.1, 32)
self.immutable_vars__test_field(app1, "VarFloat2", 21.2, 42)
self.immutable_vars__test_field(app1, "VarComplex", complex(3, 5), complex(1, 2))
self.immutable_vars__test_field(app1, "VarComplex2", complex(8, 6), complex(3, 2))
self.immutable_vars__test_field(app1, "VarBool", True, False)
self.immutable_vars__test_field(app1, "VarBool2", False, True)
self.immutable_vars__test_field(app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("11f0 F1f2 "))
self.immutable_vars__test_field(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("11f0 F1e2 "))
self.check_immutable_fields_schema(app1, "StrVar", "default value", "default value", str)
self.check_immutable_fields_schema(app1, "StrVar2", "default value2", "default value2", str)
self.check_immutable_fields_schema(app1, "VarInt", 12, 12, int)
self.check_immutable_fields_schema(app1, "VarInt2", 21, 21, int)
self.check_immutable_fields_schema(app1, "VarFloat", 12.1, 12.1, float)
self.check_immutable_fields_schema(app1, "VarFloat2", 21.2, 21.2, float)
self.check_immutable_fields_schema(app1, "VarComplex", complex(3, 5), complex(3, 5), complex)
self.check_immutable_fields_schema(app1, "VarComplex2", complex(8, 6), complex(8, 6), complex)
self.check_immutable_fields_schema(app1, "VarBool", True, True, bool)
self.check_immutable_fields_schema(app1, "VarBool2", False, False, bool)
self.check_immutable_fields_schema(app1, "VarBytes", bytes.fromhex("2Ef0 F1f2 "), bytes.fromhex("2Ef0 F1f2 "), bytes)
self.check_immutable_fields_schema(app1, "VarBytes2", bytes.fromhex("2ff0 F7f2 "), bytes.fromhex("2ff0 F7f2 "), bytes)
self.immutable_vars__test_field(app2, "StrVar", "moded value", "test")
self.immutable_vars__test_field(app2, "StrVar2", "moded value2", "test2")
self.immutable_vars__test_field(app2, "VarInt", 54, 13)
self.immutable_vars__test_field(app2, "VarInt2", 23, 22)
self.immutable_vars__test_field(app2, "VarFloat", 2.6, 32)
self.immutable_vars__test_field(app2, "VarFloat2", 1.5, 42)
self.immutable_vars__test_field(app2, "VarComplex", complex(7, 1), complex(1, 2))
self.immutable_vars__test_field(app2, "VarComplex2", complex(3, 0), complex(3, 2))
self.immutable_vars__test_field(app2, "VarBool", False, False)
self.immutable_vars__test_field(app2, "VarBool2", True, True)
self.immutable_vars__test_field(app2, "VarBytes", bytes.fromhex("21f0 e1f2 "), bytes.fromhex("11f0 F1f2 "))
self.immutable_vars__test_field(app2, "VarBytes2", bytes.fromhex("2df0 F672 "), bytes.fromhex("11f0 F1e2 "))
self.check_immutable_fields_schema(app2, "StrVar", "moded value", "default value", str)
self.check_immutable_fields_schema(app2, "StrVar2", "moded value2", "default value2", str)
self.check_immutable_fields_schema(app2, "VarInt", 54, 12, int)
self.check_immutable_fields_schema(app2, "VarInt2", 23, 21, int)
self.check_immutable_fields_schema(app2, "VarFloat", 2.6, 12.1, float)
self.check_immutable_fields_schema(app2, "VarFloat2", 1.5, 21.2, float)
self.check_immutable_fields_schema(app2, "VarComplex", complex(7, 1), complex(3, 5), complex)
self.check_immutable_fields_schema(app2, "VarComplex2", complex(3, 0), complex(8, 6), complex)
self.check_immutable_fields_schema(app2, "VarBool", False, True, bool)
self.check_immutable_fields_schema(app2, "VarBool2", True, False, bool)
self.check_immutable_fields_schema(app2, "VarBytes", bytes.fromhex("21f0 e1f2 "), bytes.fromhex("2Ef0 F1f2 "), bytes)
self.check_immutable_fields_schema(app2, "VarBytes2", bytes.fromhex("2df0 F672 "), bytes.fromhex("2ff0 F7f2 "), bytes)
with self.assertRaises(dm.ReadOnlyFieldAnnotation):
class _(Appliance1):
StrVar: int = 12
with self.assertRaises(dm.ReadOnlyFieldAnnotation):
class _(Appliance3):
NewValue: int = 12
with self.assertRaises(dm.ReadOnlyFieldAnnotation):
class _(Appliance3):
StrVar: int = 12
def test_containers_field_inheritance(self):
"""Testing first appliance level, and Field types (annotated)"""
# class can be created
class Appliance1(dm.BaseAppliance):
ListStr: list[str] = ["val1", "val2"]
Dict1: dict[int, float] = {1: 1.1, 4: 7.6, 91: 23.6}
Tuple1: "tuple[str,...]" = ("a", "c")
FrozenSet1: frozenset[int] = frozenset({1, 2})
Set1: set[int] = set({1, 2})
# class can be created
class Appliance2(Appliance1):
ListStr = ["mod val1", "mod val2"]
Dict1 = {4: 1.1, 9: 7.6, 51: 23.6}
Tuple1 = ("aa", "cc")
FrozenSet1 = frozenset({14, 27})
Set1 = set({1, 20})
app1 = Appliance1()
self.immutable_vars__test_field(app1, "ListStr", ("val1", "val2"), ["val2", "val3"])
self.immutable_vars__test_field(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6})
self.immutable_vars__test_field(app1, "Tuple1", ("a", "c"), ("h", "r"))
self.immutable_vars__test_field(app1, "FrozenSet1", frozenset({1, 2}), frozenset({4, 0}))
self.immutable_vars__test_field(app1, "Set1", frozenset({1, 2}), set({4, 0}))
self.check_immutable_fields_schema(app1, "ListStr", ("val1", "val2"), ("val1", "val2"), list[str])
self.check_immutable_fields_schema(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, dict[int, float])
self.check_immutable_fields_schema(app1, "Tuple1", ("a", "c"), ("a", "c"), tuple[str, ...])
self.check_immutable_fields_schema(app1, "FrozenSet1", frozenset({1, 2}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app1, "Set1", frozenset({1, 2}), frozenset({1, 2}), set[int])
app2 = Appliance2()
self.immutable_vars__test_field(app2, "ListStr", ("mod val1", "mod val2"), ["val2", "val3"])
self.immutable_vars__test_field(app2, "Dict1", {4: 1.1, 9: 7.6, 51: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6})
self.immutable_vars__test_field(app2, "Tuple1", ("aa", "cc"), ("h", "r"))
self.immutable_vars__test_field(app2, "FrozenSet1", frozenset({14, 27}), frozenset({4, 0}))
self.immutable_vars__test_field(app2, "Set1", frozenset({1, 20}), set({4, 0}))
self.check_immutable_fields_schema(app2, "ListStr", ("mod val1", "mod val2"), ("val1", "val2"), list[str])
self.check_immutable_fields_schema(app2, "Dict1", {4: 1.1, 9: 7.6, 51: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, dict[int, float])
self.check_immutable_fields_schema(app2, "Tuple1", ("aa", "cc"), ("a", "c"), tuple[str, ...])
self.check_immutable_fields_schema(app2, "FrozenSet1", frozenset({14, 27}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app2, "Set1", frozenset({1, 20}), frozenset({1, 2}), set[int])
self.immutable_vars__test_field(app1, "ListStr", ("val1", "val2"), ["val2", "val3"])
self.immutable_vars__test_field(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6})
self.immutable_vars__test_field(app1, "Tuple1", ("a", "c"), ("h", "r"))
self.immutable_vars__test_field(app1, "FrozenSet1", frozenset({1, 2}), frozenset({4, 0}))
self.immutable_vars__test_field(app1, "Set1", frozenset({1, 2}), set({4, 0}))
self.check_immutable_fields_schema(app1, "ListStr", ("val1", "val2"), ("val1", "val2"), list[str])
self.check_immutable_fields_schema(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, dict[int, float])
self.check_immutable_fields_schema(app1, "Tuple1", ("a", "c"), ("a", "c"), tuple[str, ...])
self.check_immutable_fields_schema(app1, "FrozenSet1", frozenset({1, 2}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app1, "Set1", frozenset({1, 2}), frozenset({1, 2}), set[int])
# class can be created
class Appliance3(Appliance2):
ListStr2: list[str] = ["mod val3", "mod val3"]
Dict2: dict[int, float] = {9: 8.1, 5: 98.6, 551: 3.6}
Tuple2: "tuple[str,...]" = ("aaa", "ccc")
FrozenSet2: frozenset[int] = frozenset({114, 127})
Set2: set[int] = set({10, 250})
app3 = Appliance3()
self.immutable_vars__test_field(app3, "ListStr", ("mod val1", "mod val2"), ["val2", "val3"])
self.immutable_vars__test_field(app3, "Dict1", {4: 1.1, 9: 7.6, 51: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6})
self.immutable_vars__test_field(app3, "Tuple1", ("aa", "cc"), ("h", "r"))
self.immutable_vars__test_field(app3, "FrozenSet1", frozenset({14, 27}), frozenset({4, 0}))
self.immutable_vars__test_field(app3, "Set1", frozenset({1, 20}), set({4, 0}))
self.immutable_vars__test_field(app3, "ListStr2", ("mod val3", "mod val3"), ["mod val3", "mod val3"])
self.immutable_vars__test_field(app3, "Dict2", {9: 8.1, 5: 98.6, 551: 3.6}, {9: 8.1, 5: 98.6, 551: 3.6})
self.immutable_vars__test_field(app3, "Tuple2", ("aaa", "ccc"), ("aaa", "ccc"))
self.immutable_vars__test_field(app3, "FrozenSet2", frozenset({114, 127}), frozenset({114, 127}))
self.immutable_vars__test_field(app3, "Set2", frozenset({10, 250}), set({10, 250}))
self.check_immutable_fields_schema(app3, "ListStr", ("mod val1", "mod val2"), ("val1", "val2"), list[str])
self.check_immutable_fields_schema(app3, "Dict1", {4: 1.1, 9: 7.6, 51: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, dict[int, float])
self.check_immutable_fields_schema(app3, "Tuple1", ("aa", "cc"), ("a", "c"), tuple[str, ...])
self.check_immutable_fields_schema(app3, "FrozenSet1", frozenset({14, 27}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app3, "Set1", frozenset({1, 20}), frozenset({1, 2}), set[int])
self.check_immutable_fields_schema(app3, "ListStr2", ("mod val3", "mod val3"), ("mod val3", "mod val3"), list[str])
self.check_immutable_fields_schema(app3, "Dict2", {9: 8.1, 5: 98.6, 551: 3.6}, {9: 8.1, 5: 98.6, 551: 3.6}, dict[int, float])
self.check_immutable_fields_schema(app3, "Tuple2", ("aaa", "ccc"), ("aaa", "ccc"), tuple[str, ...])
self.check_immutable_fields_schema(app3, "FrozenSet2", frozenset({114, 127}), frozenset({114, 127}), frozenset[int])
self.check_immutable_fields_schema(app3, "Set2", frozenset({10, 250}), frozenset({10, 250}), set[int])
self.immutable_vars__test_field(app2, "ListStr", ("mod val1", "mod val2"), ["val2", "val3"])
self.immutable_vars__test_field(app2, "Dict1", {4: 1.1, 9: 7.6, 51: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6})
self.immutable_vars__test_field(app2, "Tuple1", ("aa", "cc"), ("h", "r"))
self.immutable_vars__test_field(app2, "FrozenSet1", frozenset({14, 27}), frozenset({4, 0}))
self.immutable_vars__test_field(app2, "Set1", frozenset({1, 20}), set({4, 0}))
self.check_immutable_fields_schema(app2, "ListStr", ("mod val1", "mod val2"), ("val1", "val2"), list[str])
self.check_immutable_fields_schema(app2, "Dict1", {4: 1.1, 9: 7.6, 51: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, dict[int, float])
self.check_immutable_fields_schema(app2, "Tuple1", ("aa", "cc"), ("a", "c"), tuple[str, ...])
self.check_immutable_fields_schema(app2, "FrozenSet1", frozenset({14, 27}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app2, "Set1", frozenset({1, 20}), frozenset({1, 2}), set[int])
self.immutable_vars__test_field(app1, "ListStr", ("val1", "val2"), ["val2", "val3"])
self.immutable_vars__test_field(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6})
self.immutable_vars__test_field(app1, "Tuple1", ("a", "c"), ("h", "r"))
self.immutable_vars__test_field(app1, "FrozenSet1", frozenset({1, 2}), frozenset({4, 0}))
self.immutable_vars__test_field(app1, "Set1", frozenset({1, 2}), set({4, 0}))
self.check_immutable_fields_schema(app1, "ListStr", ("val1", "val2"), ("val1", "val2"), list[str])
self.check_immutable_fields_schema(app1, "Dict1", {1: 1.1, 4: 7.6, 91: 23.6}, {1: 1.1, 4: 7.6, 91: 23.6}, dict[int, float])
self.check_immutable_fields_schema(app1, "Tuple1", ("a", "c"), ("a", "c"), tuple[str, ...])
self.check_immutable_fields_schema(app1, "FrozenSet1", frozenset({1, 2}), frozenset({1, 2}), frozenset[int])
self.check_immutable_fields_schema(app1, "Set1", frozenset({1, 2}), frozenset({1, 2}), set[int])
def test_initializer(self):
"""Testing first appliance level, and Field types (simple)"""
# class can be created
class Appliance1(dm.BaseAppliance):
VarInt: int = 12
VarInt2: int = 21
list1: list[int] = [1]
set1: set[float] = {1.43}
set2: set[float] = {5.43}
VarStr1: str = "abcd"
@classmethod
def __initializer(cls):
cls.VarInt2 = cls.VarInt + 1
cls.list1.append(2)
cls.set2 = cls.set1 | {1234}
cls.set1 = {0}
cls.VarStr1 = cls.VarStr1.upper()
app1 = Appliance1()
self.assertEquals(app1.VarInt, 12)
self.assertEquals(app1.VarInt2, 13)
self.assertEquals(app1.set1, frozenset({0}))
self.assertEquals(app1.set2, frozenset((1.43, 1234)))
self.assertEquals(app1.VarStr1, "ABCD")
# class can be created
class _(dm.BaseAppliance):
VarInt: int = 41
@classmethod
def __initializer(cls):
cls.VarInt = cls.VarInt + 1
app2 = _()
self.assertEquals(app2.VarInt, 42)
def test_initializer_safe(self):
with self.assertRaises(dm.ImportForbidden):
class test(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
import pprint
with self.assertRaises(NameError):
class _(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
eval("2 ** 8")
with self.assertRaises(NameError):
class _(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
open("foo")
with self.assertRaises(NameError):
class _(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
exec("exit()")
with self.assertRaises(NameError):
class _(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
compile("print(55)", "test", "eval")
with self.assertRaises(NameError):
class _(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
compile("print(55)", "test", "eval")
with self.assertRaises(dm.FunctionForbidden):
def testfc():
eval("print('test')")
class _(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
testfc()
# class can be created
class Appliance2(dm.BaseAppliance):
VarInt: int = -56
VarInt2: int = 0
VarInt3: int = 0
VarInt4: int = 0
VarInt5: int = 0
VarFloat: float = 1.23
list1: list[int] = [1, 2, 0, 4]
list2: Optional[list[int]] = None
list3: Optional[list[int]] = None
set1: set[float] = {1.43}
set2: set[float] = {5.43}
@classmethod
def __initializer(cls):
cls.VarInt2 = abs(cls.VarInt)
cls.VarFloat = round(cls.VarFloat)
cls.VarInt = min(cls.list1)
cls.VarInt3 = max(cls.list1)
cls.VarInt4 = sum(cls.list1)
cls.VarInt5 = len(cls.list1)
cls.list2 = sorted(cls.list1)
cls.list3 = []
for i in range(5):
cls.list3.append(i)
cls.set2 = {math.ceil(list(cls.set1)[0])}
app2 = Appliance2()
self.assertEquals(app2.VarInt2, 56)
self.assertEquals(app2.VarFloat, 1)
self.assertEquals(app2.VarInt, 0)
self.assertEquals(app2.VarInt3, 4)
self.assertEquals(app2.VarInt4, 7)
self.assertEquals(app2.VarInt5, 4)
self.assertEquals(app2.list2, (0, 1, 2, 4))
self.assertEquals(app2.list3, (0, 1, 2, 3, 4))
self.assertEquals(app2.set2, {2})
with self.assertRaises(NameError):
class _(dm.BaseAppliance):
_: int = 0
@classmethod
def __initializer(cls):
test_initializer_safe_testfc()
# ---------- main ----------
if __name__ == "__main__":
unittest.main()