Exemple #1
0
 def test_default_init_after_instance_creation(self):
     enum_type = CEnum("EnumT", values=["A", "B", "C"])
     mcl = CMetaclass(attributes={"e1": enum_type, "e2": enum_type})
     cl = CClass(mcl, "C")
     e2 = mcl.get_attribute("e2")
     e2.default = "A"
     eq_(cl.get_value("e1"), None)
     eq_(cl.get_value("e2"), "A")
Exemple #2
0
 def test_attribute_get_name_and_classifier(self):
     m = CMetaclass("M", attributes={"isBoolean": True})
     a = m.get_attribute("isBoolean")
     eq_(a.name, "isBoolean")
     eq_(a.classifier, m)
     m.delete()
     eq_(a.name, None)
     eq_(a.classifier, None)
Exemple #3
0
 def test_enum_type_attribute_values(self):
     enum_type = CEnum("EnumT", values=["A", "B", "C"])
     mcl = CMetaclass(attributes={"e1": enum_type, "e2": enum_type})
     e2 = mcl.get_attribute("e2")
     e2.default = "A"
     cl = CClass(mcl, "C")
     eq_(cl.get_value("e1"), None)
     eq_(cl.get_value("e2"), "A")
     cl.set_value("e1", "B")
     cl.set_value("e2", "C")
     eq_(cl.get_value("e1"), "B")
     eq_(cl.get_value("e2"), "C")
     try:
         cl.set_value("e1", "X")
         exception_expected_()
     except CException as e:
         eq_(e.value, "value 'X' is not element of enumeration")
Exemple #4
0
    def test_primitive_type_attributes(self):
        cl = CMetaclass("MCL", attributes={
            "isBoolean": True,
            "intVal": 1,
            "floatVal": 1.1,
            "string": "abc",
            "list": ["a", "b"]})
        eq_(len(cl.attributes), 5)
        eq_(len(cl.attribute_names), 5)

        ok_({"isBoolean", "intVal", "floatVal", "string", "list"}.issubset(cl.attribute_names))

        a1 = cl.get_attribute("isBoolean")
        a2 = cl.get_attribute("intVal")
        a3 = cl.get_attribute("floatVal")
        a4 = cl.get_attribute("string")
        a5 = cl.get_attribute("list")
        ok_({a1, a2, a3, a4}.issubset(cl.attributes))
        eq_(None, cl.get_attribute("X"))

        eq_(a1.type, bool)
        eq_(a2.type, int)
        eq_(a3.type, float)
        eq_(a4.type, str)
        eq_(a5.type, list)

        d1 = a1.default
        d2 = a2.default
        d3 = a3.default
        d4 = a4.default
        d5 = a5.default

        ok_(isinstance(d1, bool))
        ok_(isinstance(d2, int))
        ok_(isinstance(d3, float))
        ok_(isinstance(d4, str))
        ok_(isinstance(d5, list))

        eq_(d1, True)
        eq_(d2, 1)
        eq_(d3, 1.1)
        eq_(d4, "abc")
        eq_(d5, ["a", "b"])
Exemple #5
0
 def test_type_object_attribute_class_is_none(self):
     m = CMetaclass("M", attributes={"ac": None})
     ac = m.get_attribute("ac")
     eq_(ac.default, None)
     eq_(ac.type, None)
Exemple #6
0
class TestMetaClassAttributes:
    def setup(self):
        self.mcl = CMetaclass("MCL")

    def test_primitive_empty_input(self):
        cl = CMetaclass("MCL", attributes={})
        eq_(len(cl.attributes), 0)
        eq_(len(cl.attribute_names), 0)

    def test_primitive_none_input(self):
        cl = CMetaclass("MCL", attributes=None)
        eq_(len(cl.attributes), 0)
        eq_(len(cl.attribute_names), 0)

    def test_primitive_type_attributes(self):
        cl = CMetaclass("MCL", attributes={
            "isBoolean": True,
            "intVal": 1,
            "floatVal": 1.1,
            "string": "abc",
            "list": ["a", "b"]})
        eq_(len(cl.attributes), 5)
        eq_(len(cl.attribute_names), 5)

        ok_({"isBoolean", "intVal", "floatVal", "string", "list"}.issubset(cl.attribute_names))

        a1 = cl.get_attribute("isBoolean")
        a2 = cl.get_attribute("intVal")
        a3 = cl.get_attribute("floatVal")
        a4 = cl.get_attribute("string")
        a5 = cl.get_attribute("list")
        ok_({a1, a2, a3, a4}.issubset(cl.attributes))
        eq_(None, cl.get_attribute("X"))

        eq_(a1.type, bool)
        eq_(a2.type, int)
        eq_(a3.type, float)
        eq_(a4.type, str)
        eq_(a5.type, list)

        d1 = a1.default
        d2 = a2.default
        d3 = a3.default
        d4 = a4.default
        d5 = a5.default

        ok_(isinstance(d1, bool))
        ok_(isinstance(d2, int))
        ok_(isinstance(d3, float))
        ok_(isinstance(d4, str))
        ok_(isinstance(d5, list))

        eq_(d1, True)
        eq_(d2, 1)
        eq_(d3, 1.1)
        eq_(d4, "abc")
        eq_(d5, ["a", "b"])

    def test_attribute_get_name_and_classifier(self):
        m = CMetaclass("M", attributes={"isBoolean": True})
        a = m.get_attribute("isBoolean")
        eq_(a.name, "isBoolean")
        eq_(a.classifier, m)
        m.delete()
        eq_(a.name, None)
        eq_(a.classifier, None)

    def test_primitive_attributes_no_default(self):
        self.mcl.attributes = {"a": bool, "b": int, "c": str, "d": float, "e": list}
        a1 = self.mcl.get_attribute("a")
        a2 = self.mcl.get_attribute("b")
        a3 = self.mcl.get_attribute("c")
        a4 = self.mcl.get_attribute("d")
        a5 = self.mcl.get_attribute("e")
        ok_({a1, a2, a3, a4, a5}.issubset(self.mcl.attributes))
        eq_(a1.default, None)
        eq_(a1.type, bool)
        eq_(a2.default, None)
        eq_(a2.type, int)
        eq_(a3.default, None)
        eq_(a3.type, str)
        eq_(a4.default, None)
        eq_(a4.type, float)
        eq_(a5.default, None)
        eq_(a5.type, list)

    def test_get_attribute_not_found(self):
        eq_(self.mcl.get_attribute("x"), None)
        self.mcl.attributes = {"a": bool, "b": int, "c": str, "d": float}
        eq_(self.mcl.get_attribute("x"), None)

    def test_same_named_arguments_c_attributes(self):
        a1 = CAttribute(default="")
        a2 = CAttribute(type=str)
        n1 = "a"
        self.mcl.attributes = {n1: a1, "a": a2}
        eq_(set(self.mcl.attributes), {a2})
        eq_(self.mcl.attribute_names, ["a"])

    def test_same_named_arguments_defaults(self):
        n1 = "a"
        self.mcl.attributes = {n1: "", "a": 1}
        ok_(len(self.mcl.attributes), 1)
        eq_(self.mcl.get_attribute("a").default, 1)
        eq_(self.mcl.attribute_names, ["a"])

    def test_object_type_attribute(self):
        attribute_type = CClass(self.mcl, "AttrType")
        attribute_value = CObject(attribute_type, "attribute_value")
        self.mcl.attributes = {"attrTypeObj": attribute_value}
        object_attribute = self.mcl.get_attribute("attrTypeObj")
        attributes = self.mcl.attributes
        eq_(set(attributes), {object_attribute})

        bool_attr = CAttribute(default=True)
        self.mcl.attributes = {"attrTypeObj": object_attribute, "isBoolean": bool_attr}
        attributes = self.mcl.attributes
        eq_(set(attributes), {object_attribute, bool_attr})
        eq_(self.mcl.attribute_names, ["attrTypeObj", "isBoolean"])
        object_attribute = self.mcl.get_attribute("attrTypeObj")
        eq_(object_attribute.type, attribute_type)
        default = object_attribute.default
        ok_(isinstance(default, CObject))
        eq_(default, attribute_value)

        self.mcl.attributes = {"attrTypeObj": attribute_value, "isBoolean": bool_attr}
        eq_(self.mcl.attribute_names, ["attrTypeObj", "isBoolean"])
        # using the CObject in attributes causes a new CAttribute to be created != object_attribute
        neq_(self.mcl.get_attribute("attrTypeObj"), object_attribute)

    def test_class_type_attribute(self):
        attribute_type = CMetaclass("AttrType")
        attribute_value = CClass(attribute_type, "attribute_value")
        self.mcl.attributes = {"attrTypeCl": attribute_type}
        class_attribute = self.mcl.get_attribute("attrTypeCl")
        class_attribute.default = attribute_value
        attributes = self.mcl.attributes
        eq_(set(attributes), {class_attribute})

        bool_attr = CAttribute(default=True)
        self.mcl.attributes = {"attrTypeCl": class_attribute, "isBoolean": bool_attr}
        attributes = self.mcl.attributes
        eq_(set(attributes), {class_attribute, bool_attr})
        eq_(self.mcl.attribute_names, ["attrTypeCl", "isBoolean"])
        class_attribute = self.mcl.get_attribute("attrTypeCl")
        eq_(class_attribute.type, attribute_type)
        default = class_attribute.default
        ok_(isinstance(default, CClass))
        eq_(default, attribute_value)

        self.mcl.attributes = {"attrTypeCl": attribute_value, "isBoolean": bool_attr}
        eq_(self.mcl.attribute_names, ["attrTypeCl", "isBoolean"])
        # using the CClass in attributes causes a new CAttribute to be created != class_attribute
        neq_(self.mcl.get_attribute("attrTypeCl"), class_attribute)

    def test_use_enum_type_attribute(self):
        enum_values = ["A", "B", "C"]
        enum_obj = CEnum("ABCEnum", values=enum_values)
        ea1 = CAttribute(type=enum_obj, default="A")
        ea2 = CAttribute(type=enum_obj)
        self.mcl.attributes = {"letters1": ea1, "letters2": ea2}
        eq_(set(self.mcl.attributes), {ea1, ea2})
        ok_(isinstance(ea1.type, CEnum))

        self.mcl.attributes = {"letters1": ea1, "isBool": True, "letters2": ea2}
        bool_attr = self.mcl.get_attribute("isBool")
        l1 = self.mcl.get_attribute("letters1")
        eq_(set(self.mcl.attributes), {l1, ea2, bool_attr})
        eq_(l1.default, "A")
        eq_(ea2.default, None)

    def test_unknown_attribute_type(self):
        try:
            self.mcl.attributes = {"x": CEnum, "b": bool}
            exception_expected_()
        except CException as e:
            ok_(re.match("^(unknown attribute type: '<class ).*(CEnum'>')$", e.value))

    def test_set_attribute_default_value(self):
        enum_obj = CEnum("ABCEnum", values=["A", "B", "C"])
        self.mcl.attributes = {"letters": enum_obj, "b": bool}
        letters = self.mcl.get_attribute("letters")
        b = self.mcl.get_attribute("b")
        eq_(letters.default, None)
        eq_(b.default, None)
        letters.default = "B"
        b.default = False
        eq_(letters.default, "B")
        eq_(b.default, False)
        eq_(letters.type, enum_obj)
        eq_(b.type, bool)

    def test_cclass_vs_cobject(self):
        cl_a = CClass(self.mcl, "A")
        cl_b = CClass(self.mcl, "B")
        obj_b = CObject(cl_b, "obj_b")

        self.mcl.attributes = {"a": cl_a, "b": obj_b}
        a = self.mcl.get_attribute("a")
        b = self.mcl.get_attribute("b")
        eq_(a.type, cl_a)
        eq_(a.default, None)
        eq_(b.type, cl_b)
        eq_(b.default, obj_b)

    testMetaclass = CMetaclass("A")
    testEnum = CEnum("AEnum", values=[1, 2])
    testClass = CClass(testMetaclass, "CL")

    @parameterized.expand([
        (bool, testMetaclass),
        (bool, 1.1),
        (int, testMetaclass),
        (int, "abc"),
        (float, "1"),
        (float, testMetaclass),
        (str, 1),
        (str, testMetaclass),
        (testEnum, "1"),
        (testEnum, testMetaclass),
        (testClass, "1"),
        (testClass, testMetaclass)])
    def test_attribute_type_check(self, type_to_check, wrong_default):
        self.mcl.attributes = {"a": type_to_check}
        attr = self.mcl.get_attribute("a")
        try:
            attr.default = wrong_default
            exception_expected_()
        except CException as e:
            eq_(f"default value '{wrong_default!s}' incompatible with attribute's type '{type_to_check!s}'", e.value)

    def test_delete_attributes(self):
        self.mcl.attributes = {
            "isBoolean": True,
            "intVal": 1,
            "floatVal": 1.1,
            "string": "abc"}
        eq_(len(set(self.mcl.attributes)), 4)
        self.mcl.attributes = {}
        eq_(set(self.mcl.attributes), set())
        self.mcl.attributes = {
            "isBoolean": True,
            "intVal": 1,
            "floatVal": 1.1,
            "string": "abc"}
        eq_(len(set(self.mcl.attributes)), 4)
        self.mcl.attributes = {}
        eq_(set(self.mcl.attributes), set())

    def test_type_object_attribute_class_is_deleted_in_constructor(self):
        attribute_class = CClass(self.mcl, "AC")
        attribute_class.delete()
        try:
            CMetaclass("M", attributes={"ac": attribute_class})
            exception_expected_()
        except CException as e:
            eq_(e.value, "cannot access named element that has been deleted")

    def test_type_object_attribute_class_is_none(self):
        m = CMetaclass("M", attributes={"ac": None})
        ac = m.get_attribute("ac")
        eq_(ac.default, None)
        eq_(ac.type, None)

    def test_default_object_attribute_is_deleted_in_constructor(self):
        attribute_class = CClass(self.mcl, "AC")
        default_object = CObject(attribute_class)
        default_object.delete()
        try:
            CMetaclass("M", attributes={"ac": default_object})
            exception_expected_()
        except CException as e:
            eq_(e.value, "cannot access named element that has been deleted")
Exemple #7
0
class TestClassAttributeValues:
    def setup(self):
        self.mcl = CMetaclass("MCL")

    def test_values_on_primitive_type_attributes(self):
        mcl = CMetaclass("M",
                         attributes={
                             "isBoolean": True,
                             "intVal": 1,
                             "floatVal": 1.1,
                             "string": "abc",
                             "list": ["a", "b"]
                         })
        cl = CClass(mcl, "C")

        eq_(cl.get_value("isBoolean"), True)
        eq_(cl.get_value("intVal"), 1)
        eq_(cl.get_value("floatVal"), 1.1)
        eq_(cl.get_value("string"), "abc")
        eq_(cl.get_value("list"), ["a", "b"])

        cl.set_value("isBoolean", False)
        cl.set_value("intVal", 2)
        cl.set_value("floatVal", 2.1)
        cl.set_value("string", "y")

        eq_(cl.get_value("isBoolean"), False)
        eq_(cl.get_value("intVal"), 2)
        eq_(cl.get_value("floatVal"), 2.1)
        eq_(cl.get_value("string"), "y")

        cl.set_value("list", [])
        eq_(cl.get_value("list"), [])
        cl.set_value("list", [1, 2, 3])
        eq_(cl.get_value("list"), [1, 2, 3])

    def test_attribute_of_value_unknown(self):
        cl = CClass(self.mcl, "C")
        try:
            cl.get_value("x")
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'x' unknown for 'C'")

        self.mcl.attributes = {"isBoolean": True, "intVal": 1}
        try:
            cl.set_value("x", 1)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'x' unknown for 'C'")

    def test_integers_as_floats(self):
        mcl = CMetaclass("C", attributes={"floatVal": float})
        cl = CClass(mcl, "C")
        cl.set_value("floatVal", 15)
        eq_(cl.get_value("floatVal"), 15)

    def test_attribute_defined_after_instance(self):
        mcl = CMetaclass("C")
        cl = CClass(mcl, "C")
        mcl.attributes = {"floatVal": float}
        cl.set_value("floatVal", 15)
        eq_(cl.get_value("floatVal"), 15)

    def test_object_type_attribute_values(self):
        attr_type = CClass(self.mcl, "AttrType")
        attr_value = CObject(attr_type, "attribute_value")
        self.mcl.attributes = {"attrTypeObj": attr_value}
        obj_attr = self.mcl.get_attribute("attrTypeObj")
        eq_(obj_attr.type, attr_type)
        cl = CClass(self.mcl, "C")
        eq_(cl.get_value("attrTypeObj"), attr_value)

        non_attr_value = CObject(CClass(self.mcl), "non_attribute_value")
        try:
            cl.set_value("attrTypeObj", non_attr_value)
            exception_expected_()
        except CException as e:
            eq_(
                e.value,
                "type of 'non_attribute_value' is not matching type of attribute 'attrTypeObj'"
            )

    def test_class_type_attribute_values(self):
        attr_type = CMetaclass("AttrType")
        attr_value = CClass(attr_type, "attribute_value")
        self.mcl.attributes = {"attrTypeCl": attr_type}
        cl_attr = self.mcl.get_attribute("attrTypeCl")
        cl_attr.default = attr_value
        eq_(cl_attr.type, attr_type)
        cl = CClass(self.mcl, "C")
        eq_(cl.get_value("attrTypeCl"), attr_value)

        non_attr_value = CClass(CMetaclass("MX"), "non_attribute_value")
        try:
            cl.set_value("attrTypeCl", non_attr_value)
            exception_expected_()
        except CException as e:
            eq_(
                e.value,
                "type of 'non_attribute_value' is not matching type of attribute 'attrTypeCl'"
            )

    def test_add_object_attribute_get_set_value(self):
        attr_type = CClass(self.mcl, "AttrType")
        attr_value = CObject(attr_type, "attribute_value")
        cl = CClass(self.mcl)
        self.mcl.attributes = {
            "attrTypeObj1": attr_type,
            "attrTypeObj2": attr_value
        }
        eq_(cl.get_value("attrTypeObj1"), None)
        eq_(cl.get_value("attrTypeObj2"), attr_value)

    def test_object_attribute_of_superclass_type(self):
        attr_super_type = CClass(self.mcl, "AttrSuperType")
        attr_type = CClass(self.mcl, "AttrType", superclasses=attr_super_type)
        attr_value = CObject(attr_type, "attribute_value")
        cl = CClass(self.mcl)
        self.mcl.attributes = {
            "attrTypeObj1": attr_super_type,
            "attrTypeObj2": attr_value
        }
        cl.set_value("attrTypeObj1", attr_value)
        cl.set_value("attrTypeObj2", attr_value)
        eq_(cl.get_value("attrTypeObj1"), attr_value)
        eq_(cl.get_value("attrTypeObj2"), attr_value)

    def test_values_on_attributes_with_no_default_values(self):
        attr_type = CClass(self.mcl, "AttrType")
        enum_type = CEnum("EnumT", values=["A", "B", "C"])
        mcl = CMetaclass("M",
                         attributes={
                             "b": bool,
                             "i": int,
                             "f": float,
                             "s": str,
                             "l": list,
                             "C": attr_type,
                             "e": enum_type
                         })
        cl = CClass(mcl, "C")
        for n in ["b", "i", "f", "s", "l", "C", "e"]:
            eq_(cl.get_value(n), None)

    def test_values_defined_in_constructor(self):
        obj_val_type = CClass(CMetaclass())
        obj_val = CObject(obj_val_type, "object_value")

        mcl = CMetaclass("M",
                         attributes={
                             "isBoolean": True,
                             "intVal": 1,
                             "floatVal": 1.1,
                             "string": "abc",
                             "list": ["a", "b"],
                             "obj": obj_val_type
                         })
        cl = CClass(mcl,
                    "C",
                    values={
                        "isBoolean": False,
                        "intVal": 2,
                        "floatVal": 2.1,
                        "string": "y",
                        "list": [],
                        "obj": obj_val
                    })

        eq_(cl.get_value("isBoolean"), False)
        eq_(cl.get_value("intVal"), 2)
        eq_(cl.get_value("floatVal"), 2.1)
        eq_(cl.get_value("string"), "y")
        eq_(cl.get_value("list"), [])
        eq_(cl.get_value("obj"), obj_val)

        eq_(
            cl.values, {
                "isBoolean": False,
                "intVal": 2,
                "floatVal": 2.1,
                "string": "y",
                "list": [],
                "obj": obj_val
            })

    def test_values_setter_overwrite(self):
        mcl = CMetaclass("M", attributes={"isBoolean": True, "intVal": 1})
        cl = CClass(mcl, "C", values={"isBoolean": False, "intVal": 2})
        cl.values = {"isBoolean": True, "intVal": 20}
        eq_(cl.get_value("isBoolean"), True)
        eq_(cl.get_value("intVal"), 20)
        eq_(cl.values, {'isBoolean': True, 'intVal': 20})
        cl.values = {}
        # values should not delete existing values
        eq_(cl.values, {"isBoolean": True, "intVal": 20})

    def test_values_setter_with_superclass(self):
        mcl_super = CMetaclass("S_MCL",
                               attributes={
                                   "intVal": 20,
                                   "intVal2": 30
                               })
        mcl = CMetaclass("M",
                         superclasses=mcl_super,
                         attributes={
                             "isBoolean": True,
                             "intVal": 1
                         })
        cl = CClass(mcl, "C", values={"isBoolean": False})
        eq_(cl.values, {"isBoolean": False, "intVal": 1, "intVal2": 30})
        cl.set_value("intVal", 12, mcl_super)
        cl.set_value("intVal", 15, mcl)
        cl.set_value("intVal2", 16, mcl_super)
        eq_(cl.values, {"isBoolean": False, "intVal": 15, "intVal2": 16})
        eq_(cl.get_value("intVal", mcl_super), 12)
        eq_(cl.get_value("intVal", mcl), 15)

    def test_values_setter_malformed_description(self):
        mcl = CMetaclass("M", attributes={"isBoolean": True, "intVal": 1})
        cl = CClass(mcl, "C")
        try:
            cl.values = [1, 2, 3]
            exception_expected_()
        except CException as e:
            eq_(e.value, "malformed attribute values description: '[1, 2, 3]'")

    def test_enum_type_attribute_values(self):
        enum_type = CEnum("EnumT", values=["A", "B", "C"])
        mcl = CMetaclass(attributes={"e1": enum_type, "e2": enum_type})
        e2 = mcl.get_attribute("e2")
        e2.default = "A"
        cl = CClass(mcl, "C")
        eq_(cl.get_value("e1"), None)
        eq_(cl.get_value("e2"), "A")
        cl.set_value("e1", "B")
        cl.set_value("e2", "C")
        eq_(cl.get_value("e1"), "B")
        eq_(cl.get_value("e2"), "C")
        try:
            cl.set_value("e1", "X")
            exception_expected_()
        except CException as e:
            eq_(e.value, "value 'X' is not element of enumeration")

    def test_default_init_after_instance_creation(self):
        enum_type = CEnum("EnumT", values=["A", "B", "C"])
        mcl = CMetaclass(attributes={"e1": enum_type, "e2": enum_type})
        cl = CClass(mcl, "C")
        e2 = mcl.get_attribute("e2")
        e2.default = "A"
        eq_(cl.get_value("e1"), None)
        eq_(cl.get_value("e2"), "A")

    def test_attribute_value_type_check_bool1(self):
        self.mcl.attributes = {"t": bool}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", self.mcl)
            exception_expected_()
        except CException as e:
            eq_(f"value for attribute 't' is not a known attribute type",
                e.value)

    def test_attribute_value_type_check_bool2(self):
        self.mcl.attributes = {"t": bool}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", 1)
            exception_expected_()
        except CException as e:
            eq_(f"value type for attribute 't' does not match attribute type",
                e.value)

    def test_attribute_value_type_check_int(self):
        self.mcl.attributes = {"t": int}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", True)
            exception_expected_()
        except CException as e:
            eq_(f"value type for attribute 't' does not match attribute type",
                e.value)

    def test_attribute_value_type_check_float(self):
        self.mcl.attributes = {"t": float}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", True)
            exception_expected_()
        except CException as e:
            eq_(f"value type for attribute 't' does not match attribute type",
                e.value)

    def test_attribute_value_type_check_str(self):
        self.mcl.attributes = {"t": str}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", True)
            exception_expected_()
        except CException as e:
            eq_(f"value type for attribute 't' does not match attribute type",
                e.value)

    def test_attribute_value_type_check_list(self):
        self.mcl.attributes = {"t": list}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", True)
            exception_expected_()
        except CException as e:
            eq_(f"value type for attribute 't' does not match attribute type",
                e.value)

    def test_attribute_value_type_check_object(self):
        attr_type = CMetaclass("AttrType")
        self.mcl.attributes = {"t": attr_type}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", True)
            exception_expected_()
        except CException as e:
            eq_(f"value type for attribute 't' does not match attribute type",
                e.value)

    def test_attribute_value_type_check_enum(self):
        enum_type = CEnum("EnumT", values=["A", "B", "C"])
        self.mcl.attributes = {"t": enum_type}
        cl = CClass(self.mcl, "C")
        try:
            cl.set_value("t", True)
            exception_expected_()
        except CException as e:
            eq_(f"value type for attribute 't' does not match attribute type",
                e.value)

    def test_attribute_deleted(self):
        mcl = CMetaclass(attributes={"isBoolean": True, "intVal": 15})
        cl = CClass(mcl, "C")
        eq_(cl.get_value("intVal"), 15)
        mcl.attributes = {"isBoolean": False}
        eq_(cl.get_value("isBoolean"), True)
        try:
            cl.get_value("intVal")
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'intVal' unknown for 'C'")
        try:
            cl.set_value("intVal", 1)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'intVal' unknown for 'C'")

    def test_attribute_deleted_no_default(self):
        mcl = CMetaclass(attributes={"isBoolean": bool, "intVal": int})
        mcl.attributes = {"isBoolean": bool}
        cl = CClass(mcl, "C")
        eq_(cl.get_value("isBoolean"), None)
        try:
            cl.get_value("intVal")
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'intVal' unknown for 'C'")
        try:
            cl.set_value("intVal", 1)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'intVal' unknown for 'C'")

    def test_attributes_overwrite(self):
        mcl = CMetaclass(attributes={"isBoolean": True, "intVal": 15})
        cl = CClass(mcl, "C")
        eq_(cl.get_value("intVal"), 15)
        try:
            cl.get_value("floatVal")
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'floatVal' unknown for 'C'")
        cl.set_value("intVal", 18)
        mcl.attributes = {"isBoolean": False, "intVal": 19, "floatVal": 25.1}
        eq_(cl.get_value("isBoolean"), True)
        eq_(cl.get_value("floatVal"), 25.1)
        eq_(cl.get_value("intVal"), 18)
        cl.set_value("floatVal", 1.2)
        eq_(cl.get_value("floatVal"), 1.2)

    def test_attributes_overwrite_no_defaults(self):
        mcl = CMetaclass(attributes={"isBoolean": bool, "intVal": int})
        cl = CClass(mcl, "C")
        eq_(cl.get_value("isBoolean"), None)
        cl.set_value("isBoolean", False)
        mcl.attributes = {"isBoolean": bool, "intVal": int, "floatVal": float}
        eq_(cl.get_value("isBoolean"), False)
        eq_(cl.get_value("floatVal"), None)
        eq_(cl.get_value("intVal"), None)
        cl.set_value("floatVal", 1.2)
        eq_(cl.get_value("floatVal"), 1.2)

    def test_attributes_deleted_on_subclass(self):
        mcl = CMetaclass("M", attributes={"isBoolean": True, "intVal": 1})
        mcl2 = CMetaclass("M2",
                          attributes={"isBoolean": False},
                          superclasses=mcl)

        cl = CClass(mcl2, "C")

        eq_(cl.get_value("isBoolean"), False)
        eq_(cl.get_value("isBoolean", mcl), True)
        eq_(cl.get_value("isBoolean", mcl2), False)

        mcl2.attributes = {}

        eq_(cl.get_value("isBoolean"), True)
        eq_(cl.get_value("intVal"), 1)
        eq_(cl.get_value("isBoolean", mcl), True)
        try:
            cl.get_value("isBoolean", mcl2)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'isBoolean' unknown for 'M2'")

    def test_attributes_deleted_on_subclass_no_defaults(self):
        mcl = CMetaclass("M", attributes={"isBoolean": bool, "intVal": int})
        mcl2 = CMetaclass("M2",
                          attributes={"isBoolean": bool},
                          superclasses=mcl)

        cl = CClass(mcl2, "C")

        eq_(cl.get_value("isBoolean"), None)
        eq_(cl.get_value("isBoolean", mcl), None)
        eq_(cl.get_value("isBoolean", mcl2), None)

        mcl2.attributes = {}

        eq_(cl.get_value("isBoolean"), None)
        eq_(cl.get_value("intVal"), None)
        eq_(cl.get_value("isBoolean", mcl), None)
        try:
            cl.get_value("isBoolean", mcl2)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'isBoolean' unknown for 'M2'")

    def test_attribute_values_inheritance(self):
        t1 = CMetaclass("T1")
        t2 = CMetaclass("T2")
        c = CMetaclass("C", superclasses=[t1, t2])
        sc = CMetaclass("C", superclasses=c)

        t1.attributes = {"i0": 0}
        t2.attributes = {"i1": 1}
        c.attributes = {"i2": 2}
        sc.attributes = {"i3": 3}

        cl = CClass(sc, "C")

        for name, value in {"i0": 0, "i1": 1, "i2": 2, "i3": 3}.items():
            eq_(cl.get_value(name), value)

        eq_(cl.get_value("i0", t1), 0)
        eq_(cl.get_value("i1", t2), 1)
        eq_(cl.get_value("i2", c), 2)
        eq_(cl.get_value("i3", sc), 3)

        for name, value in {"i0": 10, "i1": 11, "i2": 12, "i3": 13}.items():
            cl.set_value(name, value)

        for name, value in {"i0": 10, "i1": 11, "i2": 12, "i3": 13}.items():
            eq_(cl.get_value(name), value)

        eq_(cl.get_value("i0", t1), 10)
        eq_(cl.get_value("i1", t2), 11)
        eq_(cl.get_value("i2", c), 12)
        eq_(cl.get_value("i3", sc), 13)

    def test_attribute_values_inheritance_after_delete_superclass(self):
        t1 = CMetaclass("T1")
        t2 = CMetaclass("T2")
        c = CMetaclass("C", superclasses=[t1, t2])
        sc = CMetaclass("C", superclasses=c)

        t1.attributes = {"i0": 0}
        t2.attributes = {"i1": 1}
        c.attributes = {"i2": 2}
        sc.attributes = {"i3": 3}

        cl = CClass(sc, "C")

        t2.delete()

        for name, value in {"i0": 0, "i2": 2, "i3": 3}.items():
            eq_(cl.get_value(name), value)
        try:
            cl.get_value("i1")
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'i1' unknown for 'C'")

        eq_(cl.get_value("i0", t1), 0)
        try:
            cl.get_value("i1", t2)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'i1' unknown for ''")
        eq_(cl.get_value("i2", c), 2)
        eq_(cl.get_value("i3", sc), 3)

        for name, value in {"i0": 10, "i2": 12, "i3": 13}.items():
            cl.set_value(name, value)
        try:
            cl.set_value("i1", 11)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'i1' unknown for 'C'")

        for name, value in {"i0": 10, "i2": 12, "i3": 13}.items():
            eq_(cl.get_value(name), value)
        try:
            cl.get_value("i1")
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'i1' unknown for 'C'")

        eq_(cl.get_value("i0", t1), 10)
        try:
            cl.get_value("i1", t2)
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'i1' unknown for ''")
        eq_(cl.get_value("i2", c), 12)
        eq_(cl.get_value("i3", sc), 13)

    def test_attribute_values_same_name_inheritance(self):
        t1 = CMetaclass("T1")
        t2 = CMetaclass("T2")
        c = CMetaclass("C", superclasses=[t1, t2])
        sc = CMetaclass("C", superclasses=c)

        t1.attributes = {"i": 0}
        t2.attributes = {"i": 1}
        c.attributes = {"i": 2}
        sc.attributes = {"i": 3}

        cl1 = CClass(sc)
        cl2 = CClass(c)
        cl3 = CClass(t1)

        eq_(cl1.get_value("i"), 3)
        eq_(cl2.get_value("i"), 2)
        eq_(cl3.get_value("i"), 0)

        eq_(cl1.get_value("i", sc), 3)
        eq_(cl1.get_value("i", c), 2)
        eq_(cl1.get_value("i", t2), 1)
        eq_(cl1.get_value("i", t1), 0)
        eq_(cl2.get_value("i", c), 2)
        eq_(cl2.get_value("i", t2), 1)
        eq_(cl2.get_value("i", t1), 0)
        eq_(cl3.get_value("i", t1), 0)

        cl1.set_value("i", 10)
        cl2.set_value("i", 11)
        cl3.set_value("i", 12)

        eq_(cl1.get_value("i"), 10)
        eq_(cl2.get_value("i"), 11)
        eq_(cl3.get_value("i"), 12)

        eq_(cl1.get_value("i", sc), 10)
        eq_(cl1.get_value("i", c), 2)
        eq_(cl1.get_value("i", t2), 1)
        eq_(cl1.get_value("i", t1), 0)
        eq_(cl2.get_value("i", c), 11)
        eq_(cl2.get_value("i", t2), 1)
        eq_(cl2.get_value("i", t1), 0)
        eq_(cl3.get_value("i", t1), 12)

        cl1.set_value("i", 130, sc)
        cl1.set_value("i", 100, t1)
        cl1.set_value("i", 110, t2)
        cl1.set_value("i", 120, c)

        eq_(cl1.get_value("i"), 130)

        eq_(cl1.get_value("i", sc), 130)
        eq_(cl1.get_value("i", c), 120)
        eq_(cl1.get_value("i", t2), 110)
        eq_(cl1.get_value("i", t1), 100)

    def test_values_multiple_inheritance(self):
        t1 = CMetaclass("T1")
        t2 = CMetaclass("T2")
        st_a = CMetaclass("STA", superclasses=[t1, t2])
        sub_a = CMetaclass("SubA", superclasses=[st_a])
        st_b = CMetaclass("STB", superclasses=[t1, t2])
        sub_b = CMetaclass("SubB", superclasses=[st_b])
        st_c = CMetaclass("STC")
        sub_c = CMetaclass("SubC", superclasses=[st_c])

        mcl = CMetaclass("M", superclasses=[sub_a, sub_b, sub_c])
        cl = CClass(mcl, "C")

        t1.attributes = {"i0": 0}
        t2.attributes = {"i1": 1}
        st_a.attributes = {"i2": 2}
        sub_a.attributes = {"i3": 3}
        st_b.attributes = {"i4": 4}
        sub_b.attributes = {"i5": 5}
        st_c.attributes = {"i6": 6}
        sub_c.attributes = {"i7": 7}

        eq_(cl.get_value("i0"), 0)
        eq_(cl.get_value("i1"), 1)
        eq_(cl.get_value("i2"), 2)
        eq_(cl.get_value("i3"), 3)
        eq_(cl.get_value("i4"), 4)
        eq_(cl.get_value("i5"), 5)
        eq_(cl.get_value("i6"), 6)
        eq_(cl.get_value("i7"), 7)

        eq_(cl.get_value("i0", t1), 0)
        eq_(cl.get_value("i1", t2), 1)
        eq_(cl.get_value("i2", st_a), 2)
        eq_(cl.get_value("i3", sub_a), 3)
        eq_(cl.get_value("i4", st_b), 4)
        eq_(cl.get_value("i5", sub_b), 5)
        eq_(cl.get_value("i6", st_c), 6)
        eq_(cl.get_value("i7", sub_c), 7)

        cl.set_value("i0", 10)
        cl.set_value("i1", 11)
        cl.set_value("i2", 12)
        cl.set_value("i3", 13)
        cl.set_value("i4", 14)
        cl.set_value("i5", 15)
        cl.set_value("i6", 16)
        cl.set_value("i7", 17)

        eq_(cl.get_value("i0"), 10)
        eq_(cl.get_value("i1"), 11)
        eq_(cl.get_value("i2"), 12)
        eq_(cl.get_value("i3"), 13)
        eq_(cl.get_value("i4"), 14)
        eq_(cl.get_value("i5"), 15)
        eq_(cl.get_value("i6"), 16)
        eq_(cl.get_value("i7"), 17)

    def test_delete_attribute_values(self):
        mcl = CMetaclass("M",
                         attributes={
                             "isBoolean": True,
                             "intVal": 1,
                             "floatVal": 1.1,
                             "string": "abc",
                             "list": ["a", "b"]
                         })
        cl = CClass(mcl, "C")
        cl.delete_value("isBoolean")
        cl.delete_value("intVal")
        value_of_list = cl.delete_value("list")
        eq_(cl.values, {'floatVal': 1.1, 'string': 'abc'})
        eq_(value_of_list, ['a', 'b'])

    def test_delete_attribute_values_with_superclass(self):
        mcl_super = CMetaclass("SCL_M",
                               attributes={
                                   "intVal": 20,
                                   "intVal2": 30
                               })
        mcl = CMetaclass("M",
                         superclasses=mcl_super,
                         attributes={
                             "isBoolean": True,
                             "intVal": 1
                         })
        cl = CClass(mcl, "C", values={"isBoolean": False})
        cl.delete_value("isBoolean")
        cl.delete_value("intVal2")
        eq_(cl.values, {"intVal": 1})

        cl.set_value("intVal", 2, mcl_super)
        cl.set_value("intVal", 3, mcl)
        eq_(cl.values, {"intVal": 3})
        cl.delete_value("intVal")
        eq_(cl.values, {"intVal": 2})

        cl.set_value("intVal", 2, mcl_super)
        cl.set_value("intVal", 3, mcl)
        cl.delete_value("intVal", mcl)
        eq_(cl.values, {"intVal": 2})

        cl.set_value("intVal", 2, mcl_super)
        cl.set_value("intVal", 3, mcl)
        cl.delete_value("intVal", mcl_super)
        eq_(cl.values, {"intVal": 3})

    def test_attribute_values_exceptional_cases(self):
        mcl = CMetaclass("M", attributes={"b": True})
        cl1 = CClass(mcl, "C")
        cl1.delete()

        try:
            cl1.get_value("b")
            exception_expected_()
        except CException as e:
            eq_(e.value, "can't get value 'b' on deleted class")

        try:
            cl1.set_value("b", 1)
            exception_expected_()
        except CException as e:
            eq_(e.value, "can't set value 'b' on deleted class")

        try:
            cl1.delete_value("b")
            exception_expected_()
        except CException as e:
            eq_(e.value, "can't delete value 'b' on deleted class")

        try:
            cl1.values = {"b": 1}
            exception_expected_()
        except CException as e:
            eq_(e.value, "can't set values on deleted class")

        try:
            # we just use list here, in order to not get a warning that cl1.values has no effect
            list(cl1.values)
            exception_expected_()
        except CException as e:
            eq_(e.value, "can't get values on deleted class")

        cl = CClass(mcl, "C")
        try:
            cl.delete_value("x")
            exception_expected_()
        except CException as e:
            eq_(e.value, "attribute 'x' unknown for 'C'")