documentation - brief descriptions for bpy api files.
[blender.git] / source / blender / python / intern / bpy_operator.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/intern/bpy_operator.c
24  *  \ingroup pythonintern
25  *
26  * This file defines '_bpy.ops', an internal python module which gives python
27  * the ability to inspect and call both C and Python defined operators.
28  *
29  * \note
30  * This module is exposed to the user via 'release/scripts/modules/bpy/ops.py'
31  * which fakes exposing operators as modules/functions using its own classes.
32  */
33
34
35 /* Note, this module is not to be used directly by the user.
36  * Internally its exposed as '_bpy.ops', which provides functions for 'bpy.ops', a python package.
37  * */
38
39 #include <Python.h>
40
41 #include "RNA_types.h"
42
43 #include "BPY_extern.h"
44 #include "bpy_operator.h"
45 #include "bpy_operator_wrap.h"
46 #include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
47 #include "bpy_util.h"
48 #include "../generic/bpy_internal_import.h"
49
50 #include "BLI_utildefines.h"
51 #include "BLI_string.h"
52
53 #include "RNA_access.h"
54 #include "RNA_enum_types.h"
55
56 #include "WM_api.h"
57 #include "WM_types.h"
58
59 #include "MEM_guardedalloc.h"
60
61 #include "BLI_ghash.h"
62
63 #include "BKE_report.h"
64 #include "BKE_context.h"
65
66 /* so operators called can spawn threads which aquire the GIL */
67 #define BPY_RELEASE_GIL
68
69
70 static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args)
71 {
72         wmOperatorType *ot;
73         char            *opname;
74         PyObject        *context_dict= NULL; /* optional args */
75         PyObject        *context_dict_back;
76         char            *context_str= NULL;
77         PyObject        *ret;
78
79         int context= WM_OP_EXEC_DEFAULT;
80
81         // 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...
82         bContext *C= (bContext *)BPy_GetContext();
83         
84         if (C==NULL) {
85                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
86                 return NULL;
87         }
88
89         if (!PyArg_ParseTuple(args, "s|Os:_bpy.ops.poll", &opname, &context_dict, &context_str))
90                 return NULL;
91         
92         ot= WM_operatortype_find(opname, TRUE);
93
94         if (ot == NULL) {
95                 PyErr_Format(PyExc_AttributeError,
96                              "Polling operator \"bpy.ops.%s\" error, "
97                              "could not be found", opname);
98                 return NULL;
99         }
100
101         if (context_str) {
102                 if (RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
103                         char *enum_str= BPy_enum_as_string(operator_context_items);
104                         PyErr_Format(PyExc_TypeError,
105                                      "Calling operator \"bpy.ops.%s.poll\" error, "
106                                      "expected a string enum in (%.200s)",
107                                      opname, enum_str);
108                         MEM_freeN(enum_str);
109                         return NULL;
110                 }
111         }
112         
113         if (context_dict==NULL || context_dict==Py_None) {
114                 context_dict= NULL;
115         }
116         else if (!PyDict_Check(context_dict)) {
117                 PyErr_Format(PyExc_TypeError,
118                              "Calling operator \"bpy.ops.%s.poll\" error, "
119                              "custom context expected a dict or None, got a %.200s",
120                              opname, Py_TYPE(context_dict)->tp_name);
121                 return NULL;
122         }
123
124         context_dict_back= CTX_py_dict_get(C);
125         CTX_py_dict_set(C, (void *)context_dict);
126         Py_XINCREF(context_dict); /* so we done loose it */
127         
128         /* main purpose of thsi function */
129         ret= WM_operator_poll_context((bContext*)C, ot, context) ? Py_True : Py_False;
130         
131         /* restore with original context dict, probably NULL but need this for nested operator calls */
132         Py_XDECREF(context_dict);
133         CTX_py_dict_set(C, (void *)context_dict_back);
134         
135         Py_INCREF(ret);
136         return ret;
137 }
138
139 static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args)
140 {
141         wmOperatorType *ot;
142         int error_val= 0;
143         PointerRNA ptr;
144         int operator_ret= OPERATOR_CANCELLED;
145
146         char            *opname;
147         char            *context_str= NULL;
148         PyObject        *kw= NULL; /* optional args */
149         PyObject        *context_dict= NULL; /* optional args */
150         PyObject        *context_dict_back;
151
152         /* note that context is an int, python does the conversion in this case */
153         int context= WM_OP_EXEC_DEFAULT;
154
155         // 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...
156         bContext *C= (bContext *)BPy_GetContext();
157         
158         if (C==NULL) {
159                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant poll any operators");
160                 return NULL;
161         }
162         
163         if (!PyArg_ParseTuple(args, "sO|O!s:_bpy.ops.call", &opname, &context_dict, &PyDict_Type, &kw, &context_str))
164                 return NULL;
165
166         ot= WM_operatortype_find(opname, TRUE);
167
168         if (ot == NULL) {
169                 PyErr_Format(PyExc_AttributeError,
170                              "Calling operator \"bpy.ops.%s\" error, "
171                              "could not be found", opname);
172                 return NULL;
173         }
174         
175         if (!pyrna_write_check()) {
176                 PyErr_Format(PyExc_RuntimeError,
177                              "Calling operator \"bpy.ops.%s\" error, "
178                              "can't modify blend data in this state (drawing/rendering)",
179                              opname);
180                 return NULL;
181         }
182
183         if (context_str) {
184                 if (RNA_enum_value_from_id(operator_context_items, context_str, &context)==0) {
185                         char *enum_str= BPy_enum_as_string(operator_context_items);
186                         PyErr_Format(PyExc_TypeError,
187                                      "Calling operator \"bpy.ops.%s\" error, "
188                                      "expected a string enum in (%.200s)",
189                                      opname, enum_str);
190                         MEM_freeN(enum_str);
191                         return NULL;
192                 }
193         }
194
195         if (context_dict==NULL || context_dict==Py_None) {
196                 context_dict= NULL;
197         }
198         else if (!PyDict_Check(context_dict)) {
199                 PyErr_Format(PyExc_TypeError,
200                              "Calling operator \"bpy.ops.%s\" error, "
201                              "custom context expected a dict or None, got a %.200s",
202                              opname, Py_TYPE(context_dict)->tp_name);
203                 return NULL;
204         }
205
206         context_dict_back= CTX_py_dict_get(C);
207
208         CTX_py_dict_set(C, (void *)context_dict);
209         Py_XINCREF(context_dict); /* so we done loose it */
210
211         if (WM_operator_poll_context((bContext*)C, ot, context) == FALSE) {
212                 const char *msg= CTX_wm_operator_poll_msg_get(C);
213                 PyErr_Format(PyExc_RuntimeError,
214                              "Operator bpy.ops.%.200s.poll() %.200s",
215                              opname, msg ? msg : "failed, context is incorrect");
216                 CTX_wm_operator_poll_msg_set(C, NULL); /* better set to NULL else it could be used again */
217                 error_val= -1;
218         }
219         else {
220                 WM_operator_properties_create_ptr(&ptr, ot);
221                 WM_operator_properties_sanitize(&ptr, 0);
222
223                 if (kw && PyDict_Size(kw))
224                         error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
225
226
227                 if (error_val==0) {
228                         ReportList *reports;
229
230                         reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
231                         BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these dont move into global reports */
232
233 #ifdef BPY_RELEASE_GIL
234                         /* release GIL, since a thread could be started from an operator
235                          * that updates a driver */
236                         /* note: I havve not seen any examples of code that does this
237                          * so it may not be officially supported but seems to work ok. */
238                         {
239                                 PyThreadState *ts= PyEval_SaveThread();
240 #endif
241
242                                 operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports);
243
244 #ifdef BPY_RELEASE_GIL
245                                 /* regain GIL */
246                                 PyEval_RestoreThread(ts);
247                         }
248 #endif
249
250                         error_val= BPy_reports_to_error(reports, PyExc_RuntimeError, FALSE);
251
252                         /* operator output is nice to have in the terminal/console too */
253                         if (reports->list.first) {
254                                 char *report_str= BKE_reports_string(reports, 0); /* all reports */
255         
256                                 if (report_str) {
257                                         PySys_WriteStdout("%s\n", report_str);
258                                         MEM_freeN(report_str);
259                                 }
260                         }
261         
262                         BKE_reports_clear(reports);
263                         if ((reports->flag & RPT_FREE) == 0)
264                         {
265                                 MEM_freeN(reports);
266                         }
267                 }
268
269                 WM_operator_properties_free(&ptr);
270
271 #if 0
272                 /* if there is some way to know an operator takes args we should use this */
273                 {
274                         /* no props */
275                         if (kw != NULL) {
276                                 PyErr_Format(PyExc_AttributeError,
277                                              "Operator \"%s\" does not take any args",
278                                              opname);
279                                 return NULL;
280                         }
281
282                         WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
283                 }
284 #endif
285         }
286
287         /* restore with original context dict, probably NULL but need this for nested operator calls */
288         Py_XDECREF(context_dict);
289         CTX_py_dict_set(C, (void *)context_dict_back);
290
291         if (error_val==-1) {
292                 return NULL;
293         }
294
295         /* when calling  bpy.ops.wm.read_factory_settings() bpy.data's main pointer is freed by clear_globals(),
296          * further access will crash blender. setting context is not needed in this case, only calling because this
297          * function corrects bpy.data (internal Main pointer) */
298         BPY_modules_update(C);
299
300         /* needed for when WM_OT_read_factory_settings us called from within a script */
301         bpy_import_main_set(CTX_data_main(C));
302
303         /* return operator_ret as a bpy enum */
304         return pyrna_enum_bitfield_to_py(operator_return_items, operator_ret);
305
306 }
307
308 static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
309 {
310         wmOperatorType *ot;
311         PointerRNA ptr;
312
313         char            *opname;
314         PyObject        *kw= NULL; /* optional args */
315         int all_args= 1;
316         int error_val= 0;
317
318         char *buf= NULL;
319         PyObject *pybuf;
320
321         bContext *C= (bContext *)BPy_GetContext();
322
323         if (C==NULL) {
324                 PyErr_SetString(PyExc_RuntimeError, "Context is None, cant get the string representation of this object.");
325                 return NULL;
326         }
327         
328         if (!PyArg_ParseTuple(args, "s|O!i:_bpy.ops.as_string", &opname, &PyDict_Type, &kw, &all_args))
329                 return NULL;
330
331         ot= WM_operatortype_find(opname, TRUE);
332
333         if (ot == NULL) {
334                 PyErr_Format(PyExc_AttributeError,
335                              "_bpy.ops.as_string: operator \"%.200s\" "
336                              "could not be found", opname);
337                 return NULL;
338         }
339
340         /* WM_operator_properties_create(&ptr, opname); */
341         /* Save another lookup */
342         RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
343
344         if (kw && PyDict_Size(kw))
345                 error_val= pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
346
347         if (error_val==0)
348                 buf= WM_operator_pystring(C, ot, &ptr, all_args);
349
350         WM_operator_properties_free(&ptr);
351
352         if (error_val==-1) {
353                 return NULL;
354         }
355
356         if (buf) {
357                 pybuf= PyUnicode_FromString(buf);
358                 MEM_freeN(buf);
359         }
360         else {
361                 pybuf= PyUnicode_FromString("");
362         }
363
364         return pybuf;
365 }
366
367 static PyObject *pyop_dir(PyObject *UNUSED(self))
368 {
369         GHashIterator *iter= WM_operatortype_iter();
370         PyObject *list= PyList_New(0), *name;
371
372         for ( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
373                 wmOperatorType *ot= BLI_ghashIterator_getValue(iter);
374
375                 name= PyUnicode_FromString(ot->idname);
376                 PyList_Append(list, name);
377                 Py_DECREF(name);
378         }
379         BLI_ghashIterator_free(iter);
380
381         return list;
382 }
383
384 static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value)
385 {
386         wmOperatorType *ot;
387         PointerRNA ptr;
388         const char *opname= _PyUnicode_AsString(value);
389         BPy_StructRNA *pyrna= NULL;
390         
391         if (opname==NULL) {
392                 PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_rna() expects a string argument");
393                 return NULL;
394         }
395         ot= WM_operatortype_find(opname, TRUE);
396         if (ot==NULL) {
397                 PyErr_Format(PyExc_KeyError, "_bpy.ops.get_rna(\"%s\") not found", opname);
398                 return NULL;
399         }
400         
401         /* type */
402         //RNA_pointer_create(NULL, &RNA_Struct, ot->srna, &ptr);
403
404         /* XXX - should call WM_operator_properties_free */
405         WM_operator_properties_create_ptr(&ptr, ot);
406         WM_operator_properties_sanitize(&ptr, 0);
407
408         
409         pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
410 #ifdef PYRNA_FREE_SUPPORT
411         pyrna->freeptr= TRUE;
412 #endif
413         return (PyObject *)pyrna;
414 }
415
416 static PyObject *pyop_getinstance(PyObject *UNUSED(self), PyObject *value)
417 {
418         wmOperatorType *ot;
419         wmOperator *op;
420         PointerRNA ptr;
421         const char *opname= _PyUnicode_AsString(value);
422         BPy_StructRNA *pyrna= NULL;
423
424         if (opname==NULL) {
425                 PyErr_SetString(PyExc_TypeError, "_bpy.ops.get_instance() expects a string argument");
426                 return NULL;
427         }
428         ot= WM_operatortype_find(opname, TRUE);
429         if (ot==NULL) {
430                 PyErr_Format(PyExc_KeyError, "_bpy.ops.get_instance(\"%s\") not found", opname);
431                 return NULL;
432         }
433
434 #ifdef PYRNA_FREE_SUPPORT
435         op= MEM_callocN(sizeof(wmOperator), __func__);
436 #else
437         op= PyMem_MALLOC(sizeof(wmOperator));
438         memset(op, 0, sizeof(wmOperator));
439 #endif
440         BLI_strncpy(op->idname, op->idname, sizeof(op->idname)); /* incase its needed */
441         op->type= ot;
442
443         RNA_pointer_create(NULL, &RNA_Operator, op, &ptr);
444
445         pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr);
446 #ifdef PYRNA_FREE_SUPPORT
447         pyrna->freeptr= TRUE;
448 #endif
449         op->ptr= &pyrna->ptr;
450
451         return (PyObject *)pyrna;
452 }
453
454 static struct PyMethodDef bpy_ops_methods[]= {
455         {"poll", (PyCFunction) pyop_poll, METH_VARARGS, NULL},
456         {"call", (PyCFunction) pyop_call, METH_VARARGS, NULL},
457         {"as_string", (PyCFunction) pyop_as_string, METH_VARARGS, NULL},
458         {"dir", (PyCFunction) pyop_dir, METH_NOARGS, NULL},
459         {"get_rna", (PyCFunction) pyop_getrna, METH_O, NULL},           /* only for introspection, leaks memory */
460         {"get_instance", (PyCFunction) pyop_getinstance, METH_O, NULL}, /* only for introspection, leaks memory */
461         {"macro_define", (PyCFunction) PYOP_wrap_macro_define, METH_VARARGS, NULL},
462         {NULL, NULL, 0, NULL}
463 };
464
465 static struct PyModuleDef bpy_ops_module= {
466         PyModuleDef_HEAD_INIT,
467         "_bpy.ops",
468         NULL,
469         -1,/* multiple "initialization" just copies the module dict. */
470         bpy_ops_methods,
471         NULL, NULL, NULL, NULL
472 };
473
474 PyObject *BPY_operator_module(void)
475 {
476         PyObject *submodule;
477
478         submodule= PyModule_Create(&bpy_ops_module);
479
480         return submodule;
481 }