py api was raising SystemError exception incorrectly, this is intended for internal...
[blender.git] / source / blender / python / intern / bpy_operator.c
1
2 /**
3  * $Id$
4  *
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * Contributor(s): Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /* Note, this module is not to be used directly by the user.
27  * Internally its exposed as '_bpy.ops', which provides functions for 'bpy.ops', a python package.
28  * */
29
30 #include <Python.h>
31
32 #include "bpy_operator.h"
33 #include "bpy_operator_wrap.h"
34 #include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
35 #include "bpy_util.h"
36
37 #include "BLI_utildefines.h"
38
39 #include "RNA_enum_types.h"
40
41 #include "WM_api.h"
42 #include "WM_types.h"
43
44 #include "MEM_guardedalloc.h"
45 #include "BKE_report.h"
46 #include "BKE_context.h"
47
48 static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
49 {
50         wmOperatorType *ot;
51         char            *opname;
52         PyObject        *context_dict= NULL; /* optional args */
53         PyObject        *context_dict_back;
54         char            *context_str= NULL;
55         PyObject        *ret;
56
57         int context= WM_OP_EXEC_DEFAULT;
58
59         // XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
60         bContext *C= (bContext *)BPy_GetContext();
61         
62         if(C==NULL) {
63                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
64                 return NULL;
65         }
66
67         if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str))
68                 return NULL;
69         
70         ot= WM_operatortype_find(opname, TRUE);
71
72         if (ot == NULL) {
73                 PyErr_Format(PyExc_AttributeError, "Polling operator \"bpy.ops.%s\" error, could not be found", opname);
74                 return NULL;
75         }
76
77         if(context_str) {
78                 if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
79                         char *enum_str= BPy_enum_as_string(operator_context_items);
80                         PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, expected a string enum in (%.200s)", opname, enum_str);
81                         MEM_freeN(enum_str);
82                         return NULL;
83                 }
84         }
85         
86         if(context_dict==NULL || context_dict==Py_None) {
87                 context_dict= NULL;
88         }
89         else if (!PyDict_Check(context_dict)) {
90                 PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s.poll\" error, custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name);
91                 return NULL;
92         }
93
94         context_dict_back= CTX_py_dict_get(C);
95
96         CTX_py_dict_set(C, (void *)context_dict);
97         Py_XINCREF(context_dict); /* so we done loose it */
98         
99         /* main purpose of thsi function */
100         ret= WM_operator_poll_context((bContext*)C, ot, context) ? Py_True : Py_False;
101         
102         /* restore with original context dict, probably NULL but need this for nested operator calls */
103         Py_XDECREF(context_dict);
104         CTX_py_dict_set(C, (void *)context_dict_back);
105         
106         Py_INCREF(ret);
107         return ret;
108 }
109
110 static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
111 {
112         wmOperatorType *ot;
113         int error_val = 0;
114         PointerRNA ptr;
115         int operator_ret= OPERATOR_CANCELLED;
116
117         char            *opname;
118         char            *context_str= NULL;
119         PyObject        *kw= NULL; /* optional args */
120         PyObject        *context_dict= NULL; /* optional args */
121         PyObject        *context_dict_back;
122
123         /* note that context is an int, python does the conversion in this case */
124         int context= WM_OP_EXEC_DEFAULT;
125
126         // XXX Todo, work out a better solution for passing on context, could make a tuple from self and pack the name and Context into it...
127         bContext *C = (bContext *)BPy_GetContext();
128         
129         if(C==NULL) {
130                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
131                 return NULL;
132         }
133         
134         if (!PyArg_ParseTuple(args, "sO|O!s:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str))
135                 return NULL;
136
137         ot= WM_operatortype_find(opname, TRUE);
138
139         if (ot == NULL) {
140                 PyErr_Format(PyExc_LookupError, "Calling operator \"bpy.ops.%s\" error, could not be found", opname);
141                 return NULL;
142         }
143         
144         if(!pyrna_write_check()) {
145                 PyErr_Format(PyExc_RuntimeError, "Calling operator \"bpy.ops.%s\" error, can't modify blend data in this state (drawing/rendering)", opname);
146                 return NULL;
147         }
148
149         if(context_str) {
150                 if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
151                         char *enum_str= BPy_enum_as_string(operator_context_items);
152                         PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, expected a string enum in (%.200s)", opname, enum_str);
153                         MEM_freeN(enum_str);
154                         return NULL;
155                 }
156         }
157
158         if(context_dict==NULL || context_dict==Py_None) {
159                 context_dict= NULL;
160         }
161         else if (!PyDict_Check(context_dict)) {
162                 PyErr_Format(PyExc_TypeError, "Calling operator \"bpy.ops.%s\" error, custom context expected a dict or None, got a %.200s", opname, Py_TYPE(context_dict)->tp_name);
163                 return NULL;
164         }
165
166         context_dict_back= CTX_py_dict_get(C);
167
168         CTX_py_dict_set(C, (void *)context_dict);
169         Py_XINCREF(context_dict); /* so we done loose it */
170
171         if(WM_operator_poll_context((bContext*)C, ot, context) == FALSE) {
172                 const char *msg= CTX_wm_operator_poll_msg_get(C);
173                 PyErr_Format(PyExc_RuntimeError, "Operator bpy.ops.%.200s.poll() %.200s", opname, msg ? msg : "failed, context is incorrect");
174                 CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
175                 error_val= -1;
176         }
177         else {
178                 WM_operator_properties_create_ptr(&ptr, ot);
179                 WM_operator_properties_sanitize(&ptr, 0);
180
181                 if(kw && PyDict_Size(kw))
182                         error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
183
184
185                 if (error_val==0) {
186                         ReportList *reports;
187
188                         reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
189                         BKE_reports_init(reports, RPT_STORE);
190
191                         operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports);
192
193                         if(BPy_reports_to_error(reports, FALSE))
194                                 error_val = -1;
195
196                         /* operator output is nice to have in the terminal/console too */
197                         if(reports->list.first) {
198                                 char *report_str= BKE_reports_string(reports, 0); /* all reports */
199         
200                                 if(report_str) {
201                                         PySys_WriteStdout("%s\n", report_str);
202                                         MEM_freeN(report_str);
203                                 }
204                         }
205         
206                         BKE_reports_clear(reports);
207                         if ((reports->flag & RPT_FREE) == 0)
208                         {
209                                 MEM_freeN(reports);
210                         }
211                 }
212
213                 WM_operator_properties_free(&ptr);
214
215 #if 0
216                 /* if there is some way to know an operator takes args we should use this */
217                 {
218                         /* no props */
219                         if (kw != NULL) {
220                                 PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
221                                 return NULL;
222                         }
223
224                         WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
225                 }
226 #endif
227         }
228
229         /* restore with original context dict, probably NULL but need this for nested operator calls */
230         Py_XDECREF(context_dict);
231         CTX_py_dict_set(C, (void *)context_dict_back);
232
233         if (error_val==-1) {
234                 return NULL;
235         }
236
237         /* when calling  bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
238          * further access will crash blender. setting context is not needed in this case, only calling because this
239          * function corrects bpy.data (internal Main pointer) */
240         BPY_modules_update(C);
241
242
243         /* return operator_ret as a bpy enum */
244         return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret);
245
246 }
247
248 static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
249 {
250         wmOperatorType *ot;
251         PointerRNA ptr;
252
253         char            *opname;
254         PyObject        *kw= NULL; /* optional args */
255         int all_args = 1;
256         int error_val= 0;
257
258         char *buf = NULL;
259         PyObject *pybuf;
260
261         bContext *C= (bContext *)BPy_GetContext();
262
263         if(C==NULL) {
264                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object.");
265                 return NULL;
266         }
267         
268         if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
269                 return NULL;
270
271         ot= WM_operatortype_find(opname, TRUE);
272
273         if (ot == NULL) {
274                 PyErr_Format(PyExc_AttributeError, "_bpy.ops.as_string: operator \"%.200s\"could not be found", opname);
275                 return NULL;
276         }
277
278         /* WM_operator_properties_create(&ptr, opname); */
279         /* Save another lookup */
280         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
281
282         if(kw && PyDict_Size(kw))
283                 error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
284
285         if (error_val==0)
286                 buf= WM_operator_pystring(C, ot, &ptr, all_args);
287
288         WM_operator_properties_free(&ptr);
289
290         if (error_val==-1) {
291                 return NULL;
292         }
293
294         if(buf) {
295                 pybuf= PyUnicode_FromString(buf);
296                 MEM_freeN(buf);
297         }
298         else {
299                 pybuf= PyUnicode_FromString("");
300         }
301
302         return pybuf;
303 }
304
305 static PyObject *pyop_dir(PyObject *UNUSED(self))
306 {
307         PyObject *list = PyList_New(0), *name;
308         wmOperatorType *ot;
309         
310         for(ot= WM_operatortype_first(); ot; ot= ot->next) {
311                 name = PyUnicode_FromString(ot->idname);
312                 PyList_Append(list, name);
313                 Py_DECREF(name);
314         }
315         
316         return list;
317 }
318
319 static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value)
320 {
321         wmOperatorType *ot;
322         PointerRNA ptr;
323         char *opname= _PyUnicode_AsString(value);
324         BPy_StructRNA *pyrna= NULL;
325         
326         if(opname==NULL) {
327                 PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_rna() expects a string argument");
328                 return NULL;
329         }
330         ot= WM_operatortype_find(opname, TRUE);
331         if(ot==NULL) {
332                 PyErr_Format(PyExc_KeyError, "_bpy.ops.get_rna(\"%s\") not found", opname);
333                 return NULL;
334         }
335         
336         /* type */
337         //RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr);
338
339         /* XXX - should call WM_operator_properties_free */
340         WM_operator_properties_create_ptr(&ptr, ot);
341         WM_operator_properties_sanitize(&ptr, 0);
342
343         
344         pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
345         pyrna->freeptr= TRUE;
346         return (PyObject *)pyrna;
347 }
348
349 static struct PyMethodDef bpy_ops_methods[] = {
350         {"poll", (PyCFunction) pyop_poll, METH_VARARGS, NULL},
351         {"call", (PyCFunction) pyop_call, METH_VARARGS, NULL},
352         {"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL},
353         {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL},
354         {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL},
355         {"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL},
356         {NULL, NULL, 0, NULL}
357 };
358
359 static struct PyModuleDef bpy_ops_module = {
360         PyModuleDef_HEAD_INIT,
361         "_bpy.ops",
362         NULL,
363         -1,/* multiple "initialization" just copies the module dict. */
364         bpy_ops_methods,
365         NULL, NULL, NULL, NULL
366 };
367
368 PyObject *BPY_operator_module(void)
369 {
370         PyObject *submodule;
371
372         submodule= PyModule_Create(&bpy_ops_module);
373
374         return submodule;
375 }