1 # ##### BEGIN GPL LICENSE BLOCK #####
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.
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.
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.
17 # ##### END GPL LICENSE BLOCK #####
21 # for slightly faster access
22 from _bpy import ops as ops_module
24 # op_add = ops_module.add
25 op_dir = ops_module.dir
26 op_poll = ops_module.poll
27 op_call = ops_module.call
28 op_as_string = ops_module.as_string
29 op_get_rna = ops_module.get_rna
30 op_get_rna_type = ops_module.get_rna_type
31 op_get_instance = ops_module.get_instance
36 Fake module like class.
42 def __getattr__(self, module):
44 gets a bpy.ops submodule
46 if module.startswith('__'):
47 raise AttributeError(module)
48 return BPyOpsSubMod(module)
54 # add this classes functions
55 for id_name in dir(self.__class__):
56 if not id_name.startswith('__'):
57 submodules.add(id_name)
59 for id_name in op_dir():
60 id_split = id_name.split('_OT_', 1)
62 if len(id_split) == 2:
63 submodules.add(id_split[0].lower())
65 submodules.add(id_split[0])
67 return list(submodules)
70 return "<module like class 'bpy.ops'>"
75 Utility class to fake submodules.
79 __slots__ = ("_module",)
81 def __init__(self, module):
84 def __getattr__(self, func):
86 gets a bpy.ops.submodule function
88 if func.startswith('__'):
89 raise AttributeError(func)
90 return BPyOpsSubModOp(self._module, func)
96 module_upper = self._module.upper()
98 for id_name in op_dir():
99 id_split = id_name.split('_OT_', 1)
100 if len(id_split) == 2 and module_upper == id_split[0]:
101 functions.add(id_split[1])
103 return list(functions)
106 return "<module like class 'bpy.ops.%s'>" % self._module
109 class BPyOpsSubModOp:
111 Utility class to fake submodule operators.
113 eg. bpy.ops.object.somefunc
116 __slots__ = ("_module", "_func")
119 idname = self.idname()
120 sig = op_as_string(self.idname())
121 # XXX You never quite know what you get from bpy.types,
122 # with operators... Operator and OperatorProperties
123 # are shadowing each other, and not in the same way for
124 # native ops and py ones! See T39158.
125 # op_class = getattr(bpy.types, idname)
126 op_class = op_get_rna_type(idname)
127 descr = op_class.description
128 return f"{sig}\n{descr}"
131 def _parse_args(args):
133 C_exec = 'EXEC_DEFAULT'
136 is_dict = is_exec = is_undo = False
138 for i, arg in enumerate(args):
139 if is_dict is False and isinstance(arg, dict):
140 if is_exec is True or is_undo is True:
141 raise ValueError("dict arg must come first")
144 elif is_exec is False and isinstance(arg, str):
146 raise ValueError("string arg must come before the boolean")
149 elif is_undo is False and isinstance(arg, int):
153 raise ValueError("1-3 args execution context is supported")
155 return C_dict, C_exec, C_undo
158 def _scene_update(context):
159 scene = context.scene
160 if scene: # None in background mode
164 for scene in bpy.data.scenes:
167 __doc__ = property(_get_doc)
169 def __init__(self, module, func):
170 self._module = module
173 def poll(self, *args):
174 C_dict, C_exec, C_undo = BPyOpsSubModOp._parse_args(args)
175 return op_poll(self.idname_py(), C_dict, C_exec)
178 # submod.foo -> SUBMOD_OT_foo
179 return self._module.upper() + "_OT_" + self._func
182 # submod.foo -> SUBMOD_OT_foo
183 return self._module + "." + self._func
185 def __call__(self, *args, **kw):
187 context = bpy.context
189 # Get the operator from blender
190 wm = context.window_manager
192 # run to account for any rna values the user changes.
193 BPyOpsSubModOp._scene_update(context)
196 C_dict, C_exec, C_undo = BPyOpsSubModOp._parse_args(args)
197 ret = op_call(self.idname_py(), C_dict, kw, C_exec, C_undo)
199 ret = op_call(self.idname_py(), None, kw)
201 if 'FINISHED' in ret and context.window_manager == wm:
202 BPyOpsSubModOp._scene_update(context)
206 def get_rna_type(self):
207 """Internal function for introspection"""
208 return op_get_rna_type(self.idname())
211 """Internal function for introspection"""
212 return op_get_rna(self.idname())
214 def get_instance(self):
215 """Internal function for introspection"""
216 return op_get_instance(self.idname())
218 def __repr__(self): # useful display, repr(op)
220 return op_as_string(self.idname())
222 def __str__(self): # used for print(...)
223 return ("<function bpy.ops.%s.%s at 0x%x'>" %
224 (self._module, self._func, id(self)))
227 ops_fake_module = BPyOps()