calling operators from python was raising an error without returning an error value.
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * Contributor(s): Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include "bpy_operator.h"
27 #include "bpy_operator_wrap.h"
28 #include "bpy_rna.h" /* for setting arg props only - pyrna_py_to_prop() */
29 #include "bpy_compat.h"
30 #include "bpy_util.h"
31
32 //#include "blendef.h"
33 #include "BLI_dynstr.h"
34
35 #include "WM_api.h"
36 #include "WM_types.h"
37
38 #include "MEM_guardedalloc.h"
39 //#include "BKE_idprop.h"
40 #include "BKE_report.h"
41
42 extern ListBase global_ops; /* evil, temp use */
43
44 static PyObject *pyop_base_dir(PyObject *self);
45 static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname);
46 static struct PyMethodDef pyop_base_methods[] = {
47         {"__dir__", (PyCFunction)pyop_base_dir, METH_NOARGS, ""},
48         {"__rna__", (PyCFunction)pyop_base_rna, METH_O, ""},
49         {"add", (PyCFunction)PYOP_wrap_add, METH_O, ""},
50         {"remove", (PyCFunction)PYOP_wrap_remove, METH_O, ""},
51         {NULL, NULL, 0, NULL}
52 };
53
54 /* 'self' stores the operator string */
55 static PyObject *pyop_base_call( PyObject * self, PyObject * args,  PyObject * kw)
56 {
57         wmOperatorType *ot;
58         int error_val = 0;
59         PointerRNA ptr;
60         
61         // 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...
62         bContext *C = BPy_GetContext();
63         
64         char *opname = _PyUnicode_AsString(self);
65
66         if (PyTuple_Size(args)) {
67                 PyErr_SetString( PyExc_AttributeError, "All operator args must be keywords");
68                 return NULL;
69         }
70
71         ot= WM_operatortype_find(opname, 1);
72         if (ot == NULL) {
73                 PyErr_Format( PyExc_SystemError, "Operator \"%s\"could not be found", opname);
74                 return NULL;
75         }
76         
77         if(ot->poll && (ot->poll(C) == 0)) {
78                 PyErr_SetString( PyExc_SystemError, "Operator poll() function failed, context is incorrect");
79                 return NULL;
80         }
81         
82         WM_operator_properties_create(&ptr, opname);
83         
84         error_val= pyrna_pydict_to_props(&ptr, kw, "Converting py args to operator properties: ");
85         
86         if (error_val==0) {
87                 ReportList reports;
88
89                 BKE_reports_init(&reports, RPT_STORE);
90
91                 WM_operator_call_py(C, ot, &ptr, &reports);
92
93                 if(BPy_reports_to_error(&reports))
94                         error_val = -1;
95
96                 BKE_reports_clear(&reports);
97         }
98
99         WM_operator_properties_free(&ptr);
100
101 #if 0
102         /* if there is some way to know an operator takes args we should use this */
103         {
104                 /* no props */
105                 if (kw != NULL) {
106                         PyErr_Format(PyExc_AttributeError, "Operator \"%s\" does not take any args", opname);
107                         return NULL;
108                 }
109
110                 WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
111         }
112 #endif
113
114         if (error_val==-1) {
115                 return NULL;
116         }
117
118         Py_RETURN_NONE;
119 }
120
121 static PyMethodDef pyop_base_call_meth[] = {
122         {"__op_call__", (PyCFunction)pyop_base_call, METH_VARARGS|METH_KEYWORDS, "generic operator calling function"}
123 };
124
125
126 //---------------getattr--------------------------------------------
127 static PyObject *pyop_base_getattro( BPy_OperatorBase * self, PyObject *pyname )
128 {
129         char *name = _PyUnicode_AsString(pyname);
130         PyObject *ret;
131         wmOperatorType *ot;
132         
133         /* First look for the operator, then our own methods if that fails.
134          * when methods are searched first, PyObject_GenericGetAttr will raise an error
135          * each time we want to call an operator, we could clear the error but I prefer
136          * not to since calling operators is a lot more common then adding and removing. - Campbell */
137         
138         if ((ot= WM_operatortype_find(name, 1))) {
139                 ret = PyCFunction_New( pyop_base_call_meth, pyname); /* set the name string as self, PyCFunction_New incref's self */
140         }
141         else if ((ret = PyObject_GenericGetAttr((PyObject *)self, pyname))) {
142                 /* do nothing, this accounts for methoddef's add and remove
143                  * An exception is raised when PyObject_GenericGetAttr fails
144                  * but its ok because its overwritten below */
145         }
146         else {
147                 PyErr_Format( PyExc_AttributeError, "Operator \"%s\" not found", name);
148                 ret= NULL;
149         }
150
151         return ret;
152 }
153
154 static PyObject *pyop_base_dir(PyObject *self)
155 {
156         PyObject *list = PyList_New(0), *name;
157         wmOperatorType *ot;
158         PyMethodDef *meth;
159         
160         for(ot= WM_operatortype_first(); ot; ot= ot->next) {
161                 name = PyUnicode_FromString(ot->idname);
162                 PyList_Append(list, name);
163                 Py_DECREF(name);
164         }
165
166         for(meth=pyop_base_methods; meth->ml_name; meth++) {
167                 name = PyUnicode_FromString(meth->ml_name);
168                 PyList_Append(list, name);
169                 Py_DECREF(name);
170         }
171         
172         return list;
173 }
174
175 static PyObject *pyop_base_rna(PyObject *self, PyObject *pyname)
176 {
177         char *name = _PyUnicode_AsString(pyname);
178         wmOperatorType *ot;
179         
180         if ((ot= WM_operatortype_find(name, 1))) {
181                 BPy_StructRNA *pyrna;
182                 PointerRNA ptr;
183                 
184                 /* XXX POINTER - if this 'ot' is python generated, it could be free'd */
185                 RNA_pointer_create(NULL, ot->srna, NULL, &ptr);
186                 
187                 pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); /* were not really using &ptr, overwite next */
188                 //pyrna->freeptr= 1;
189                 return (PyObject *)pyrna;
190         }
191         else {
192                 PyErr_Format(PyExc_AttributeError, "Operator \"%s\" not found", name);
193                 return NULL;
194         }
195 }
196
197 PyTypeObject pyop_base_Type = {NULL};
198
199 PyObject *BPY_operator_module( void )
200 {
201         pyop_base_Type.tp_name = "OperatorBase";
202         pyop_base_Type.tp_basicsize = sizeof( BPy_OperatorBase );
203         pyop_base_Type.tp_getattro = ( getattrofunc )pyop_base_getattro;
204         pyop_base_Type.tp_flags = Py_TPFLAGS_DEFAULT;
205         pyop_base_Type.tp_methods = pyop_base_methods;
206         
207         if( PyType_Ready( &pyop_base_Type ) < 0 )
208                 return NULL;
209
210         //submodule = Py_InitModule3( "operator", M_rna_methods, "rna module" );
211         return (PyObject *)PyObject_NEW( BPy_OperatorBase, &pyop_base_Type );
212 }
213