make python3.3 compatible, __class__ is no longer in the class methods namespace.
[blender.git] / release / scripts / modules / bpy / ops.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-80 compliant>
20
21 # for slightly faster access
22 from _bpy import ops as ops_module
23
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
31
32 class BPyOps(object):
33     '''
34     Fake module like class.
35
36      bpy.ops
37     '''
38
39     def __getattr__(self, module):
40         '''
41         gets a bpy.ops submodule
42         '''
43         if module.startswith('__'):
44             raise AttributeError(module)
45         return BPyOpsSubMod(module)
46
47     def __dir__(self):
48
49         submodules = set()
50
51         # add this classes functions
52         for id_name in dir(self.__class__):
53             if not id_name.startswith('__'):
54                 submodules.add(id_name)
55
56         for id_name in op_dir():
57             id_split = id_name.split('_OT_', 1)
58
59             if len(id_split) == 2:
60                 submodules.add(id_split[0].lower())
61             else:
62                 submodules.add(id_split[0])
63
64         return list(submodules)
65
66     def __repr__(self):
67         return "<module like class 'bpy.ops'>"
68
69
70 class BPyOpsSubMod(object):
71     '''
72     Utility class to fake submodules.
73
74     eg. bpy.ops.object
75     '''
76     __keys__ = ('module',)
77
78     def __init__(self, module):
79         self.module = module
80
81     def __getattr__(self, func):
82         '''
83         gets a bpy.ops.submodule function
84         '''
85         if func.startswith('__'):
86             raise AttributeError(func)
87         return BPyOpsSubModOp(self.module, func)
88
89     def __dir__(self):
90
91         functions = set()
92
93         module_upper = self.module.upper()
94
95         for id_name in op_dir():
96             id_split = id_name.split('_OT_', 1)
97             if len(id_split) == 2 and module_upper == id_split[0]:
98                 functions.add(id_split[1])
99
100         return list(functions)
101
102     def __repr__(self):
103         return "<module like class 'bpy.ops.%s'>" % self.module
104
105
106 class BPyOpsSubModOp(object):
107     '''
108     Utility class to fake submodule operators.
109
110     eg. bpy.ops.object.somefunc
111     '''
112
113     __keys__ = ('module', 'func')
114
115     def _get_doc(self):
116         return op_as_string(self.idname())
117
118     @staticmethod
119     def _parse_args(args):
120         C_dict = None
121         C_exec = 'EXEC_DEFAULT'
122
123         if len(args) == 0:
124             pass
125         elif len(args) == 1:
126             if type(args[0]) != str:
127                 C_dict = args[0]
128             else:
129                 C_exec = args[0]
130         elif len(args) == 2:
131             C_exec, C_dict = args
132         else:
133             raise ValueError("1 or 2 args execution context is supported")
134
135         return C_dict, C_exec
136
137     @staticmethod
138     def _scene_update(context):
139         scene = context.scene
140         if scene:  # None in backgroud mode
141             scene.update()
142         else:
143             import bpy
144             for scene in bpy.data.scenes:
145                 scene.update()
146
147     __doc__ = property(_get_doc)
148
149     def __init__(self, module, func):
150         self.module = module
151         self.func = func
152
153     def poll(self, *args):
154         C_dict, C_exec = BPyOpsSubModOp._parse_args(args)
155         return op_poll(self.idname_py(), C_dict, C_exec)
156
157     def idname(self):
158         # submod.foo -> SUBMOD_OT_foo
159         return self.module.upper() + "_OT_" + self.func
160
161     def idname_py(self):
162         # submod.foo -> SUBMOD_OT_foo
163         return self.module + "." + self.func
164
165     def __call__(self, *args, **kw):
166         import bpy
167         context = bpy.context
168
169         # Get the operator from blender
170         wm = context.window_manager
171
172         # run to account for any rna values the user changes.
173         BPyOpsSubModOp._scene_update(context)
174
175         if args:
176             C_dict, C_exec = BPyOpsSubModOp._parse_args(args)
177             ret = op_call(self.idname_py(), C_dict, kw, C_exec)
178         else:
179             ret = op_call(self.idname_py(), None, kw)
180
181         if 'FINISHED' in ret and context.window_manager == wm:
182             BPyOpsSubModOp._scene_update(context)
183
184         return ret
185
186     def get_rna(self):
187         '''
188         currently only used for 'bl_rna'
189         '''
190         return op_get_rna(self.idname())
191
192     def __repr__(self):  # useful display, repr(op)
193         import bpy
194         idname = self.idname()
195         as_string = op_as_string(idname)
196         op_class = getattr(bpy.types, idname)
197         descr = op_class.bl_rna.description
198         # XXX, workaround for not registering
199         # every __doc__ to save time on load.
200         if not descr:
201             descr = op_class.__doc__
202             if not descr:
203                 descr = ""
204
205         return "# %s\n%s" % (descr, as_string)
206
207     def __str__(self):  # used for print(...)
208         return "<function bpy.ops.%s.%s at 0x%x'>" % \
209                 (self.module, self.func, id(self))
210
211 ops_fake_module = BPyOps()