Support for the C Macro system in Python.
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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_remove = ops_module.remove
26 op_add_macro = ops_module.add_macro
27 op_dir = ops_module.dir
28 op_call = ops_module.call
29 op_as_string = ops_module.as_string
30 op_get_rna = ops_module.get_rna
31
32 # Keep in sync with WM_types.h
33 context_dict = {
34     'INVOKE_DEFAULT': 0,
35     'INVOKE_REGION_WIN': 1,
36     'INVOKE_AREA': 2,
37     'INVOKE_SCREEN': 3,
38     'EXEC_DEFAULT': 4,
39     'EXEC_REGION_WIN': 5,
40     'EXEC_AREA': 6,
41     'EXEC_SCREEN': 7,
42 }
43
44
45 class bpy_ops(object):
46     '''
47     Fake module like class.
48
49      bpy.ops
50     '''
51
52     def __getattr__(self, module):
53         '''
54         gets a bpy.ops submodule
55         '''
56         if module.startswith('__'):
57             raise AttributeError(module)
58         return bpy_ops_submodule(module)
59
60     def add(self, pyop):
61         op_add(pyop)
62     
63     def add_macro(self, pyop):
64         op_add_macro(pyop)
65
66     def remove(self, pyop):
67         op_remove(pyop)
68
69     def __dir__(self):
70
71         submodules = set()
72
73         # add this classes functions
74         for id_name in dir(self.__class__):
75             if not id_name.startswith('__'):
76                 submodules.add(id_name)
77
78         for id_name in op_dir():
79             id_split = id_name.split('_OT_', 1)
80
81             if len(id_split) == 2:
82                 submodules.add(id_split[0].lower())
83             else:
84                 submodules.add(id_split[0])
85
86         return list(submodules)
87
88     def __repr__(self):
89         return "<module like class 'bpy.ops'>"
90
91
92 class bpy_ops_submodule(object):
93     '''
94     Utility class to fake submodules.
95
96     eg. bpy.ops.object
97     '''
98     __keys__ = ('module',)
99
100     def __init__(self, module):
101         self.module = module
102
103     def __getattr__(self, func):
104         '''
105         gets a bpy.ops.submodule function
106         '''
107         if func.startswith('__'):
108             raise AttributeError(func)
109         return bpy_ops_submodule_op(self.module, func)
110
111     def __dir__(self):
112
113         functions = set()
114
115         module_upper = self.module.upper()
116
117         for id_name in op_dir():
118             id_split = id_name.split('_OT_', 1)
119             if len(id_split) == 2 and module_upper == id_split[0]:
120                 functions.add(id_split[1])
121
122         return list(functions)
123
124     def __repr__(self):
125         return "<module like class 'bpy.ops.%s'>" % self.module
126
127
128 class bpy_ops_submodule_op(object):
129     '''
130     Utility class to fake submodule operators.
131
132     eg. bpy.ops.object.somefunc
133     '''
134
135     __keys__ = ('module', 'func')
136
137
138     def _get_doc(self):
139         return op_as_string(self.idname())
140
141     __doc__ = property(_get_doc)
142
143     def __init__(self, module, func):
144         self.module = module
145         self.func = func
146
147     def idname(self):
148         # submod.foo -> SUBMOD_OT_foo
149         return self.module.upper() + '_OT_' + self.func
150
151     def __call__(self, *args, **kw):
152
153         # Get the operator from blender
154         if len(args) > 2:
155             raise ValueError("1 or 2 args execution context is supported")
156
157         C_dict = None
158
159         if args:
160
161             C_exec = 'EXEC_DEFAULT'
162
163             if len(args) == 2:
164                 C_exec = args[0]
165                 C_dict = args[1]
166             else:
167                 if type(args[0]) != str:
168                     C_dict = args[0]
169                 else:
170                     C_exec = args[0]
171
172             try:
173                 context = context_dict[C_exec]
174             except:
175                 raise ValueError("Expected a single context argument in: " + \
176                  str(list(context_dict.keys())))
177
178             if len(args) == 2:
179                 C_dict = args[1]
180
181             return op_call(self.idname(), C_dict, kw, context)
182
183         else:
184             return op_call(self.idname(), C_dict, kw)
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         return op_as_string(self.idname())
194
195     def __str__(self): # used for print(...)
196         return "<function bpy.ops.%s.%s at 0x%x'>" % \
197                 (self.module, self.func, id(self))
198
199 ops_fake_module = bpy_ops()