svn merge -r36583:36603 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[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 /** \file blender/python/intern/bpy_operator.c
27  *  \ingroup pythonintern
28  */
29
30
31 /* Note, this module is not to be used directly by the user.
32  * Internally its exposed as '_bpy.ops', which provides functions for 'bpy.ops', a python package.
33  * */
34
35 #include <Python.h>
36
37 #include "RNA_types.h"
38
39 #include "BPY_extern.h"
40 #include "bpy_operator.h"
41 #include "bpy_operator_wrap.h"
42 #include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
43 #include "bpy_util.h"
44 #include "../generic/bpy_internal_import.h"
45
46 #include "BLI_utildefines.h"
47
48 #include "RNA_access.h"
49 #include "RNA_enum_types.h"
50
51 #include "WM_api.h"
52 #include "WM_types.h"
53
54 #include "MEM_guardedalloc.h"
55 #include "BKE_report.h"
56 #include "BKE_context.h"
57
58 static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
59 {
60         wmOperatorType *ot;
61         char            *opname;
62         PyObject        *context_dict= NULL; /* optional args */
63         PyObject        *context_dict_back;
64         char            *context_str= NULL;
65         PyObject        *ret;
66
67         int context= WM_OP_EXEC_DEFAULT;
68
69         // 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...
70         bContext *C= (bContext *)BPy_GetContext();
71         
72         if(C==NULL) {
73                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
74                 return NULL;
75         }
76
77         if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str))
78                 return NULL;
79         
80         ot= WM_operatortype_find(opname, TRUE);
81
82         if (ot == NULL) {
83                 PyErr_Format(PyExc_AttributeError,
84                              "Polling operator \"bpy.ops.%s\" error, "
85                              "could not be found", opname);
86                 return NULL;
87         }
88
89         if(context_str) {
90                 if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
91                         char *enum_str= BPy_enum_as_string(operator_context_items);
92                         PyErr_Format(PyExc_TypeError,
93                                      "Calling operator \"bpy.ops.%s.poll\" error, "
94                                      "expected a string enum in (%.200s)",
95                                      opname, enum_str);
96                         MEM_freeN(enum_str);
97                         return NULL;
98                 }
99         }
100         
101         if(context_dict==NULL || context_dict==Py_None) {
102                 context_dict= NULL;
103         }
104         else if (!PyDict_Check(context_dict)) {
105                 PyErr_Format(PyExc_TypeError,
106                              "Calling operator \"bpy.ops.%s.poll\" error, "
107                              "custom context expected a dict or None, got a %.200s",
108                              opname, Py_TYPE(context_dict)->tp_name);
109                 return NULL;
110         }
111
112         context_dict_back= CTX_py_dict_get(C);
113
114         CTX_py_dict_set(C, (void *)context_dict);
115         Py_XINCREF(context_dict); /* so we done loose it */
116         
117         /* main purpose of thsi function */
118         ret= WM_operator_poll_context((bContext*)C, ot, context) ? Py_True : Py_False;
119         
120         /* restore with original context dict, probably NULL but need this for nested operator calls */
121         Py_XDECREF(context_dict);
122         CTX_py_dict_set(C, (void *)context_dict_back);
123         
124         Py_INCREF(ret);
125         return ret;
126 }
127
128 static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
129 {
130         wmOperatorType *ot;
131         int error_val= 0;
132         PointerRNA ptr;
133         int operator_ret= OPERATOR_CANCELLED;
134
135         char            *opname;
136         char            *context_str= NULL;
137         PyObject        *kw= NULL; /* optional args */
138         PyObject        *context_dict= NULL; /* optional args */
139         PyObject        *context_dict_back;
140
141         /* note that context is an int, python does the conversion in this case */
142         int context= WM_OP_EXEC_DEFAULT;
143
144         // 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...
145         bContext *C= (bContext *)BPy_GetContext();
146         
147         if(C==NULL) {
148                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
149                 return NULL;
150         }
151         
152         if (!PyArg_ParseTuple(args, "sO|O!s:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str))
153                 return NULL;
154
155         ot= WM_operatortype_find(opname, TRUE);
156
157         if (ot == NULL) {
158                 PyErr_Format(PyExc_AttributeError,
159                              "Calling operator \"bpy.ops.%s\" error, "
160                              "could not be found", opname);
161                 return NULL;
162         }
163         
164         if(!pyrna_write_check()) {
165                 PyErr_Format(PyExc_RuntimeError,
166                              "Calling operator \"bpy.ops.%s\" error, "
167                              "can't modify blend data in this state (drawing/rendering)",
168                              opname);
169                 return NULL;
170         }
171
172         if(context_str) {
173                 if(RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
174                         char *enum_str= BPy_enum_as_string(operator_context_items);
175                         PyErr_Format(PyExc_TypeError,
176                                      "Calling operator \"bpy.ops.%s\" error, "
177                                      "expected a string enum in (%.200s)",
178                                      opname, enum_str);
179                         MEM_freeN(enum_str);
180                         return NULL;
181                 }
182         }
183
184         if(context_dict==NULL || context_dict==Py_None) {
185                 context_dict= NULL;
186         }
187         else if (!PyDict_Check(context_dict)) {
188                 PyErr_Format(PyExc_TypeError,
189                              "Calling operator \"bpy.ops.%s\" error, "
190                              "custom context expected a dict or None, got a %.200s",
191                              opname, Py_TYPE(context_dict)->tp_name);
192                 return NULL;
193         }
194
195         context_dict_back= CTX_py_dict_get(C);
196
197         CTX_py_dict_set(C, (void *)context_dict);
198         Py_XINCREF(context_dict); /* so we done loose it */
199
200         if(WM_operator_poll_context((bContext*)C, ot, context) == FALSE) {
201                 const char *msg= CTX_wm_operator_poll_msg_get(C);
202                 PyErr_Format(PyExc_RuntimeError,
203                              "Operator bpy.ops.%.200s.poll() %.200s",
204                              opname, msg ? msg : "failed, context is incorrect");
205                 CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
206                 error_val= -1;
207         }
208         else {
209                 WM_operator_properties_create_ptr(&ptr, ot);
210                 WM_operator_properties_sanitize(&ptr, 0);
211
212                 if(kw && PyDict_Size(kw))
213                         error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
214
215
216                 if (error_val==0) {
217                         ReportList *reports;
218
219                         reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
220                         BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these dont move into global reports */
221
222                         operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports);
223
224                         error_val= BPy_reports_to_error(reports, PyExc_RuntimeError, FALSE);
225
226                         /* operator output is nice to have in the terminal/console too */
227                         if(reports->list.first) {
228                                 char *report_str= BKE_reports_string(reports, 0); /* all reports */
229         
230                                 if(report_str) {
231                                         PySys_WriteStdout("%s\n", report_str);
232                                         MEM_freeN(report_str);
233                                 }
234                         }
235         
236                         BKE_reports_clear(reports);
237                         if ((reports->flag & RPT_FREE) == 0)
238                         {
239                                 MEM_freeN(reports);
240                         }
241                 }
242
243                 WM_operator_properties_free(&ptr);
244
245 #if 0
246                 /* if there is some way to know an operator takes args we should use this */
247                 {
248                         /* no props */
249                         if (kw != NULL) {
250                                 PyErr_Format(PyExc_AttributeError,
251                                              "Operator \"%s\" does not take any args",
252                                              opname);
253                                 return NULL;
254                         }
255
256                         WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
257                 }
258 #endif
259         }
260
261         /* restore with original context dict, probably NULL but need this for nested operator calls */
262         Py_XDECREF(context_dict);
263         CTX_py_dict_set(C, (void *)context_dict_back);
264
265         if (error_val==-1) {
266                 return NULL;
267         }
268
269         /* when calling  bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
270          * further access will crash blender. setting context is not needed in this case, only calling because this
271          * function corrects bpy.data (internal Main pointer) */
272         BPY_modules_update(C);
273
274         /* needed for when WM_OT_read_factory_settings us called fro within a script */
275         bpy_import_main_set(CTX_data_main(C));
276
277         /* return operator_ret as a bpy enum */
278         return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret);
279
280 }
281
282 static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
283 {
284         wmOperatorType *ot;
285         PointerRNA ptr;
286
287         char            *opname;
288         PyObject        *kw= NULL; /* optional args */
289         int all_args= 1;
290         int error_val= 0;
291
292         char *buf= NULL;
293         PyObject *pybuf;
294
295         bContext *C= (bContext *)BPy_GetContext();
296
297         if(C==NULL) {
298                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object.");
299                 return NULL;
300         }
301         
302         if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
303                 return NULL;
304
305         ot= WM_operatortype_find(opname, TRUE);
306
307         if (ot == NULL) {
308                 PyErr_Format(PyExc_AttributeError,
309                              "_bpy.ops.as_string: operator \"%.200s\" "
310                              "could not be found", opname);
311                 return NULL;
312         }
313
314         /* WM_operator_properties_create(&ptr, opname); */
315         /* Save another lookup */
316         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
317
318         if(kw && PyDict_Size(kw))
319                 error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
320
321         if (error_val==0)
322                 buf= WM_operator_pystring(C, ot, &ptr, all_args);
323
324         WM_operator_properties_free(&ptr);
325
326         if (error_val==-1) {
327                 return NULL;
328         }
329
330         if(buf) {
331                 pybuf= PyUnicode_FromString(buf);
332                 MEM_freeN(buf);
333         }
334         else {
335                 pybuf= PyUnicode_FromString("");
336         }
337
338         return pybuf;
339 }
340
341 static PyObject *pyop_dir(PyObject *UNUSED(self))
342 {
343         PyObject *list= PyList_New(0), *name;
344         wmOperatorType *ot;
345         
346         for(ot= WM_operatortype_first(); ot; ot= ot->next) {
347                 name= PyUnicode_FromString(ot->idname);
348                 PyList_Append(list, name);
349                 Py_DECREF(name);
350         }
351         
352         return list;
353 }
354
355 static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value)
356 {
357         wmOperatorType *ot;
358         PointerRNA ptr;
359         char *opname= _PyUnicode_AsString(value);
360         BPy_StructRNA *pyrna= NULL;
361         
362         if(opname==NULL) {
363                 PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_rna() expects a string argument");
364                 return NULL;
365         }
366         ot= WM_operatortype_find(opname, TRUE);
367         if(ot==NULL) {
368                 PyErr_Format(PyExc_KeyError, "_bpy.ops.get_rna(\"%s\") not found", opname);
369                 return NULL;
370         }
371         
372         /* type */
373         //RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr);
374
375         /* XXX - should call WM_operator_properties_free */
376         WM_operator_properties_create_ptr(&ptr, ot);
377         WM_operator_properties_sanitize(&ptr, 0);
378
379         
380         pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
381         pyrna->freeptr= TRUE;
382         return (PyObject *)pyrna;
383 }
384
385 static struct PyMethodDef bpy_ops_methods[]= {
386         {"poll", (PyCFunction) pyop_poll, METH_VARARGS, NULL},
387         {"call", (PyCFunction) pyop_call, METH_VARARGS, NULL},
388         {"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL},
389         {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL},
390         {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL},
391         {"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL},
392         {NULL, NULL, 0, NULL}
393 };
394
395 static struct PyModuleDef bpy_ops_module= {
396         PyModuleDef_HEAD_INIT,
397         "_bpy.ops",
398         NULL,
399         -1,/* multiple "initialization" just copies the module dict. */
400         bpy_ops_methods,
401         NULL, NULL, NULL, NULL
402 };
403
404 PyObject *BPY_operator_module(void)
405 {
406         PyObject *submodule;
407
408         submodule= PyModule_Create(&bpy_ops_module);
409
410         return submodule;
411 }