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