123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- # 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()
|