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