Big i18n commit: add "reports" from bmesh/readfile/tracking/dynapaint (and a few...
[blender.git] / source / tests / bl_run_operators.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 # semi-useful script, runs all operators in a number of different
22 # contexts, cheap way to find misc small bugs but is in no way a complete test.
23 #
24 # only error checked for here is a segfault.
25
26 import bpy
27 import sys
28
29 op_blacklist = (
30     "script.reload",
31     "export*.*",
32     "import*.*",
33     "*.save_*",
34     "*.read_*",
35     "*.open_*",
36     "*.link_append",
37     "render.render",
38     "*.*_export",
39     "*.*_import",
40     "wm.blenderplayer_start",
41     "wm.url_open",
42     "wm.doc_view",
43     "wm.path_open",
44     "help.operator_cheat_sheet",
45     "wm.keyconfig_test",     # just annoying - but harmless
46     "wm.memory_statistics",  # another annoying one
47     "console.*",             # just annoying - but harmless
48     )
49
50
51 def filter_op_list(operators):
52     from fnmatch import fnmatchcase
53
54     def is_op_ok(op):
55         for op_match in op_blacklist:
56             if fnmatchcase(op, op_match):
57                 print("    skipping: %s (%s)" % (op, op_match))
58                 return False
59         return True
60
61     operators[:] = [op for op in operators if is_op_ok(op[0])]
62
63
64 def run_ops(operators, setup_func=None, reset=True):
65     print("\ncontext:", setup_func.__name__)
66     # first invoke
67     for op_id, op in operators:
68         if op.poll():
69             print("    operator:", op_id)
70             sys.stdout.flush()  # in case of crash
71
72             # disable will get blender in a bad state and crash easy!
73             if reset:
74                 bpy.ops.wm.read_factory_settings()
75
76             setup_func()
77
78             for mode in {'EXEC_DEFAULT', 'INVOKE_DEFAULT'}:
79                 try:
80                     op(mode)
81                 except:
82                     #import traceback
83                     #traceback.print_exc()
84                     pass
85
86     if not operators:
87         # run test
88         if reset:
89             bpy.ops.wm.read_factory_settings()
90         setup_func()
91
92
93 # contexts
94 def ctx_clear_scene():  # copied from batch_import.py
95     unique_obs = set()
96     for scene in bpy.data.scenes:
97         for obj in scene.objects[:]:
98             scene.objects.unlink(obj)
99             unique_obs.add(obj)
100
101     # remove obdata, for now only worry about the startup scene
102     for bpy_data_iter in (bpy.data.objects, bpy.data.meshes, bpy.data.lamps, bpy.data.cameras):
103         for id_data in bpy_data_iter:
104             bpy_data_iter.remove(id_data)
105
106
107 def ctx_editmode_mesh():
108     bpy.ops.object.mode_set(mode='EDIT')
109
110
111 def ctx_editmode_mesh_extra():
112     bpy.ops.object.vertex_group_add()
113     bpy.ops.object.shape_key_add(from_mix=False)
114     bpy.ops.object.shape_key_add(from_mix=True)
115     bpy.ops.mesh.uv_texture_add()
116     bpy.ops.mesh.vertex_color_add()
117     bpy.ops.object.material_slot_add()
118     # editmode last!
119     bpy.ops.object.mode_set(mode='EDIT')
120
121
122 def ctx_editmode_mesh_empty():
123     bpy.ops.object.mode_set(mode='EDIT')
124     bpy.ops.mesh.select_all(action='SELECT')
125     bpy.ops.mesh.delete()
126
127
128 def ctx_editmode_curves():
129     bpy.ops.curve.primitive_nurbs_circle_add()
130     bpy.ops.object.mode_set(mode='EDIT')
131
132
133 def ctx_editmode_curves_empty():
134     bpy.ops.curve.primitive_nurbs_circle_add()
135     bpy.ops.object.mode_set(mode='EDIT')
136     bpy.ops.curve.delete(type='ALL')
137
138
139 def ctx_editmode_surface():
140     bpy.ops.surface.primitive_nurbs_surface_torus_add()
141     bpy.ops.object.mode_set(mode='EDIT')
142
143
144 def ctx_editmode_mball():
145     bpy.ops.object.metaball_add()
146     bpy.ops.object.mode_set(mode='EDIT')
147
148
149 def ctx_editmode_text():
150     bpy.ops.object.text_add()
151     bpy.ops.object.mode_set(mode='EDIT')
152
153
154 def ctx_editmode_armature():
155     bpy.ops.object.armature_add()
156     bpy.ops.object.mode_set(mode='EDIT')
157
158
159 def ctx_editmode_armature_empty():
160     bpy.ops.object.armature_add()
161     bpy.ops.object.mode_set(mode='EDIT')
162     bpy.ops.armature.select_all(action='SELECT')
163     bpy.ops.armature.delete()
164
165
166 def ctx_editmode_lattice():
167     bpy.ops.object.add(type='LATTICE')
168     bpy.ops.object.mode_set(mode='EDIT')
169     # bpy.ops.object.vertex_group_add()
170
171
172 def ctx_object_empty():
173     bpy.ops.object.add(type='EMPTY')
174
175
176 def ctx_object_pose():
177     bpy.ops.object.armature_add()
178     bpy.ops.object.mode_set(mode='POSE')
179     bpy.ops.pose.select_all(action='SELECT')
180
181
182 def ctx_object_paint_weight():
183     bpy.ops.object.mode_set(mode='WEIGHT_PAINT')
184
185
186 def ctx_object_paint_vertex():
187     bpy.ops.object.mode_set(mode='VERTEX_PAINT')
188
189
190 def ctx_object_paint_sculpt():
191     bpy.ops.object.mode_set(mode='SCULPT')
192
193
194 def ctx_object_paint_texture():
195     bpy.ops.object.mode_set(mode='TEXTURE_PAINT')
196
197
198 def bpy_check_type_duplicates():
199     # non essential sanity check
200     bl_types = dir(bpy.types)
201     bl_types_unique = set(bl_types)
202
203     if len(bl_types) != len(bl_types_unique):
204         print("Error, found duplicates in 'bpy.types'")
205         for t in sorted(bl_types_unique):
206             tot = bl_types.count(t)
207             if tot > 1:
208                 print("    '%s', %d" % (t, tot))
209         import sys
210         sys.exit(1)
211
212
213 def main():
214
215     bpy_check_type_duplicates()
216
217     # bpy.ops.wm.read_factory_settings()
218     import bpy
219     operators = []
220     for mod_name in dir(bpy.ops):
221         mod = getattr(bpy.ops, mod_name)
222         for submod_name in dir(mod):
223             op = getattr(mod, submod_name)
224             operators.append(("%s.%s" % (mod_name, submod_name), op))
225
226     operators.sort(key=lambda op: op[0])
227
228     filter_op_list(operators)
229
230     # for testing, mix the list up.
231     #operators.reverse()
232
233     #import random
234     #random.shuffle(operators)
235
236     # 2 passes, first just run setup_func to make sure they are ok
237     for operators_test in ((), operators):
238         # Run the operator tests in different contexts
239         run_ops(operators_test, setup_func=lambda: None)
240         run_ops(operators_test, setup_func=ctx_clear_scene)
241         # object modes
242         run_ops(operators_test, setup_func=ctx_object_empty)
243         run_ops(operators_test, setup_func=ctx_object_pose)
244         run_ops(operators_test, setup_func=ctx_object_paint_weight)
245         run_ops(operators_test, setup_func=ctx_object_paint_vertex)
246         run_ops(operators_test, setup_func=ctx_object_paint_sculpt)
247         run_ops(operators_test, setup_func=ctx_object_paint_texture)
248         # mesh
249         run_ops(operators_test, setup_func=ctx_editmode_mesh)
250         run_ops(operators_test, setup_func=ctx_editmode_mesh_extra)
251         run_ops(operators_test, setup_func=ctx_editmode_mesh_empty)
252         # armature
253         run_ops(operators_test, setup_func=ctx_editmode_armature)
254         run_ops(operators_test, setup_func=ctx_editmode_armature_empty)
255         # curves
256         run_ops(operators_test, setup_func=ctx_editmode_curves)
257         run_ops(operators_test, setup_func=ctx_editmode_curves_empty)
258         run_ops(operators_test, setup_func=ctx_editmode_surface)
259         # other
260         run_ops(operators_test, setup_func=ctx_editmode_mball)
261         run_ops(operators_test, setup_func=ctx_editmode_text)
262         run_ops(operators_test, setup_func=ctx_editmode_lattice)
263
264         if not operators_test:
265             print("All setup functions run fine!")
266
267     print("Finished %r" % __file__)
268
269 if __name__ == "__main__":
270     main()