Welcome to mirror list, hosted at ThFree Co, Russian Federation.

bl_rna_defaults.py « python « tests - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: fc895dbddfcfed3d677cbe700e9ee6640d7a6745 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# Apache License, Version 2.0

# ./blender.bin --background -noaudio --factory-startup --python tests/python/bl_rna_defaults.py

import bpy

DUMMY_NAME = "Untitled"
DUMMY_PATH = __file__
GLOBALS = {
    "error_num": 0,
}


def as_float_32(f):
    from struct import pack, unpack
    return unpack("f", pack("f", f))[0]


def repr_float_precision(f, round_fn):
    """
    Get's the value which was most likely entered by a human in C.

    Needed since Python will show trailing precision from a 32bit float.
    """
    f_round = round_fn(f)
    f_str = repr(f)
    f_str_frac = f_str.partition(".")[2]
    if not f_str_frac:
        return f_str
    for i in range(1, len(f_str_frac)):
        f_test = round(f, i)
        f_test_round = round_fn(f_test)
        if f_test_round == f_round:
            return "%.*f" % (i, f_test)
    return f_str


def repr_float_32(f):
    return repr_float_precision(f, as_float_32)


def validate_defaults(test_id, o):

    def warning(prop_id, val_real, val_default, *, repr_fn=repr):
        print("Error %s: '%s.%s' is:%s, expected:%s" %
              (test_id, o.__class__.__name__, prop_id,
               repr_fn(val_real), repr_fn(val_default)))
        GLOBALS["error_num"] += 1

    properties = type(o).bl_rna.properties.items()
    for prop_id, prop in properties:
        if prop_id == "rna_type":
            continue
        prop_type = prop.type
        if prop_type in {'STRING', 'COLLECTION'}:
            continue

        if prop_type == 'POINTER':
            # traverse down pointers if they're set
            val_real = getattr(o, prop_id)
            if (val_real is not None) and (not isinstance(val_real, bpy.types.ID)):
                validate_defaults("%s.%s" % (test_id, prop_id), val_real)
        elif prop_type in {'INT', 'BOOL'}:
            # array_length = prop.array_length
            if not prop.is_array:
                val_real = getattr(o, prop_id)
                val_default = prop.default
                if val_real != val_default:
                    warning(prop_id, val_real, val_default)
            else:
                pass  # TODO, array defaults
        elif prop_type == 'FLOAT':
            # array_length = prop.array_length
            if not prop.is_array:
                val_real = getattr(o, prop_id)
                val_default = prop.default
                if val_real != val_default:
                    warning(prop_id, val_real, val_default, repr_fn=repr_float_32)
            else:
                pass  # TODO, array defaults
        elif prop_type == 'ENUM':
            val_real = getattr(o, prop_id)
            if prop.is_enum_flag:
                val_default = prop.default_flag
            else:
                val_default = prop.default
            if val_real != val_default:
                warning(prop_id, val_real, val_default)

        # print(prop_id, prop_type)


def _test_id_gen(data_attr, args_create=(DUMMY_NAME,), create_method="new"):
    def test_gen(test_id):
        id_collection = getattr(bpy.data, data_attr)
        create_fn = getattr(id_collection, create_method)
        o = create_fn(*args_create)
        o.user_clear()
        validate_defaults(test_id, o)
        id_collection.remove(o)
    return test_gen


test_Action = _test_id_gen("actions")
test_Armature = _test_id_gen("armatures")
test_Camera = _test_id_gen("cameras")
test_Group = _test_id_gen("groups")
test_Lattice = _test_id_gen("lattices")
test_LineStyle = _test_id_gen("linestyles")
test_Mask = _test_id_gen("masks")
test_Material = _test_id_gen("materials")
test_Mesh = _test_id_gen("meshes")
test_MetaBall = _test_id_gen("metaballs")
test_MovieClip = _test_id_gen("movieclips", args_create=(DUMMY_PATH,), create_method="load")
test_Object = _test_id_gen("objects", args_create=(DUMMY_NAME, None))
test_Palette = _test_id_gen("palettes")
test_Particle = _test_id_gen("particles")
test_Scene = _test_id_gen("scenes")
test_Sound = _test_id_gen("sounds", args_create=(DUMMY_PATH,), create_method="load")
test_Speaker = _test_id_gen("speakers")
test_Text = _test_id_gen("texts")
test_VectorFont = _test_id_gen("fonts", args_create=("<builtin>",), create_method="load")
test_World = _test_id_gen("worlds")

ns = globals()
for t in bpy.data.curves.bl_rna.functions["new"].parameters["type"].enum_items.keys():
    ns["test_Curve_%s" % t] = _test_id_gen("curves", args_create=(DUMMY_NAME, t))
for t in bpy.data.lights.bl_rna.functions["new"].parameters["type"].enum_items.keys():
    ns["test_Light_%s" % t] = _test_id_gen("lights", args_create=(DUMMY_NAME, t))
# types are a dynamic enum, have to hard-code.
for t in "ShaderNodeTree", "CompositorNodeTree", "TextureNodeTree":
    ns["test_NodeGroup_%s" % t] = _test_id_gen("node_groups", args_create=(DUMMY_NAME, t))
for t in bpy.data.textures.bl_rna.functions["new"].parameters["type"].enum_items.keys():
    ns["test_Texture_%s" % t] = _test_id_gen("textures", args_create=(DUMMY_NAME, t))
del ns


def main():
    for fn_id, fn_val in sorted(globals().items()):
        if fn_id.startswith("test_") and callable(fn_val):
            fn_val(fn_id)

    print("Error (total): %d" % GLOBALS["error_num"])


if __name__ == "__main__":
    main()