rna_define.c, RNA_def_struct - set the py_type to NULL when making an rna struct...
[blender.git] / source / blender / python / intern / bpy_util.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * Contributor(s): Campbell Barton
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include "DNA_listBase.h"
26 #include "RNA_access.h"
27 #include "bpy_util.h"
28 #include "BLI_dynstr.h"
29 #include "MEM_guardedalloc.h"
30 #include "BKE_report.h"
31
32
33 #include "BKE_context.h"
34 bContext*       __py_context = NULL;
35 bContext*       BPy_GetContext(void) { return __py_context; };
36 void            BPy_SetContext(bContext *C) { __py_context= C; };
37
38
39 PyObject *BPY_flag_to_list(struct BPY_flag_def *flagdef, int flag)
40 {
41         PyObject *list = PyList_New(0);
42         
43         PyObject *item;
44         BPY_flag_def *fd;
45
46         fd= flagdef;
47         while(fd->name) {
48                 if (fd->flag & flag) {
49                         item = PyUnicode_FromString(fd->name);
50                         PyList_Append(list, item);
51                         Py_DECREF(item);
52                 }
53                 fd++;
54         }
55         
56         return list;
57
58 }
59
60 static char *bpy_flag_error_str(BPY_flag_def *flagdef)
61 {
62         BPY_flag_def *fd= flagdef;
63         DynStr *dynstr= BLI_dynstr_new();
64         char *cstring;
65
66         BLI_dynstr_append(dynstr, "Error converting a sequence of strings into a flag.\n\tExpected only these strings...\n\t");
67
68         while(fd->name) {
69                 BLI_dynstr_appendf(dynstr, fd!=flagdef?", '%s'":"'%s'", fd->name);
70                 fd++;
71         }
72         
73         cstring = BLI_dynstr_get_cstring(dynstr);
74         BLI_dynstr_free(dynstr);
75         return cstring;
76 }
77
78 int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag)
79 {
80         int i, error_val= 0;
81         char *cstring;
82         PyObject *item;
83         BPY_flag_def *fd;
84
85         if (PySequence_Check(seq)) {
86                 i= PySequence_Length(seq);
87
88                 while(i--) {
89                         item = PySequence_ITEM(seq, i);
90                         cstring= _PyUnicode_AsString(item);
91                         if(cstring) {
92                                 fd= flagdef;
93                                 while(fd->name) {
94                                         if (strcmp(cstring, fd->name) == 0)
95                                                 (*flag) |= fd->flag;
96                                         fd++;
97                                 }
98                                 if (fd==NULL) { /* could not find a match */
99                                         error_val= 1;
100                                 }
101                         } else {
102                                 error_val= 1;
103                         }
104                         Py_DECREF(item);
105                 }
106         }
107         else {
108                 error_val= 1;
109         }
110
111         if (error_val) {
112                 char *buf = bpy_flag_error_str(flagdef);
113                 PyErr_SetString(PyExc_AttributeError, buf);
114                 MEM_freeN(buf);
115                 return -1; /* error value */
116         }
117
118         return 0; /* ok */
119 }
120
121
122 /* Copied from pythons 3's Object.c */
123 #ifndef Py_CmpToRich
124 PyObject *
125 Py_CmpToRich(int op, int cmp)
126 {
127         PyObject *res;
128         int ok;
129
130         if (PyErr_Occurred())
131                 return NULL;
132         switch (op) {
133         case Py_LT:
134                 ok = cmp <  0;
135                 break;
136         case Py_LE:
137                 ok = cmp <= 0;
138                 break;
139         case Py_EQ:
140                 ok = cmp == 0;
141                 break;
142         case Py_NE:
143                 ok = cmp != 0;
144                 break;
145         case Py_GT:
146                 ok = cmp >  0;
147                 break;
148         case Py_GE:
149                 ok = cmp >= 0;
150                 break;
151         default:
152                 PyErr_BadArgument();
153                 return NULL;
154         }
155         res = ok ? Py_True : Py_False;
156         Py_INCREF(res);
157         return res;
158 }
159 #endif
160
161 /* for debugging */
162 void PyObSpit(char *name, PyObject *var) {
163         fprintf(stderr, "<%s> : ", name);
164         if (var==NULL) {
165                 fprintf(stderr, "<NIL>");
166         }
167         else {
168                 PyObject_Print(var, stderr, 0);
169                 fprintf(stderr, " ref:%d ", var->ob_refcnt);
170                 fprintf(stderr, " ptr:%ld", (long)var);
171         }
172         fprintf(stderr, "\n");
173 }
174
175 void PyLineSpit(void) {
176         char *filename;
177         int lineno;
178
179         PyErr_Clear();
180         BPY_getFileAndNum(&filename, &lineno);
181         
182         fprintf(stderr, "%s:%d\n", filename, lineno);
183 }
184
185 void BPY_getFileAndNum(char **filename, int *lineno)
186 {
187         PyObject *getframe, *frame;
188         PyObject *f_lineno= NULL, *co_filename= NULL;
189         
190         if (filename)   *filename= NULL;
191         if (lineno)             *lineno = -1;
192         
193         getframe = PySys_GetObject("_getframe"); // borrowed
194         if (getframe==NULL) {
195                 return;
196         }
197         
198         frame = PyObject_CallObject(getframe, NULL);
199         if (frame==NULL)
200                 return;
201         
202         if (filename) {
203                 co_filename= PyObject_GetAttrStringArgs(frame, 1, "f_code", "co_filename");
204                 if (co_filename==NULL) {
205                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_code.co_filename");
206                         Py_DECREF(frame);
207                         return;
208                 }
209                 
210                 *filename = _PyUnicode_AsString(co_filename);
211                 Py_DECREF(co_filename);
212         }
213         
214         if (lineno) {
215                 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
216                 if (f_lineno==NULL) {
217                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_lineno");
218                         Py_DECREF(frame);
219                         return;
220                 }
221                 
222                 *lineno = (int)PyLong_AsSsize_t(f_lineno);
223                 Py_DECREF(f_lineno);
224         }
225
226         Py_DECREF(frame);
227 }
228
229 /* Would be nice if python had this built in */
230 PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
231 {
232         Py_ssize_t i;
233         PyObject *item= o;
234         char *attr;
235         
236         va_list vargs;
237
238         va_start(vargs, n);
239         for (i=0; i<n; i++) {
240                 attr = va_arg(vargs, char *);
241                 item = PyObject_GetAttrString(item, attr);
242                 
243                 if (item) 
244                         Py_DECREF(item);
245                 else /* python will set the error value here */
246                         break;
247                 
248         }
249         va_end(vargs);
250         
251         Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
252         return item;
253 }
254
255 int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs)
256 {
257         PyObject *item, *fitem;
258         PyObject *py_arg_count;
259         int i, arg_count;
260
261         if (base_class) {
262                 if (!PyObject_IsSubclass(class, base_class)) {
263                         PyObject *name= PyObject_GetAttrString(base_class, "__name__");
264                         PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
265                         Py_XDECREF(name);
266                         return -1;
267                 }
268         }
269         
270         for(i= 0;class_attrs->name; class_attrs++, i++) {
271                 item = PyObject_GetAttrString(class, class_attrs->name);
272
273                 if (py_class_attrs)
274                         py_class_attrs[i]= item;
275                 
276                 if (item==NULL) {
277                         if ((class_attrs->flag & BPY_CLASS_ATTR_OPTIONAL)==0) {
278                                 PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, class_attrs->name);
279                                 return -1;
280                         }
281
282                         PyErr_Clear();
283                 }
284                 else {
285                         Py_DECREF(item); /* no need to keep a ref, the class owns it */
286
287                         if((item==Py_None) && (class_attrs->flag & BPY_CLASS_ATTR_NONE_OK)) {
288                                 /* dont do anything, this is ok, dont bother checking other types */
289                         }
290                         else {
291                                 switch(class_attrs->type) {
292                                 case 's':
293                                         if (PyUnicode_Check(item)==0) {
294                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a string", class_type, class_attrs->name);
295                                                 return -1;
296                                         }
297                                         break;
298                                 case 'l':
299                                         if (PyList_Check(item)==0) {
300                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a list", class_type, class_attrs->name);
301                                                 return -1;
302                                         }
303                                         break;
304                                 case 'f':
305                                         if (PyMethod_Check(item))
306                                                 fitem= PyMethod_Function(item); /* py 2.x */
307                                         else
308                                                 fitem= item; /* py 3.x */
309
310                                         if (PyFunction_Check(fitem)==0) {
311                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, class_attrs->name);
312                                                 return -1;
313                                         }
314                                         if (class_attrs->arg_count >= 0) { /* -1 if we dont care*/
315                                                 py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(fitem), "co_argcount");
316                                                 arg_count = PyLong_AsSsize_t(py_arg_count);
317                                                 Py_DECREF(py_arg_count);
318
319                                                 if (arg_count != class_attrs->arg_count) {
320                                                         PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, class_attrs->name, class_attrs->arg_count);
321                                                         return -1;
322                                                 }
323                                         }
324                                         break;
325                                 }
326                         }
327                 }
328         }
329         return 0;
330 }
331
332 char *BPy_enum_as_string(EnumPropertyItem *item)
333 {
334         DynStr *dynstr= BLI_dynstr_new();
335         EnumPropertyItem *e;
336         char *cstring;
337
338         for (e= item; item->identifier; item++) {
339                 BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
340         }
341
342         cstring = BLI_dynstr_get_cstring(dynstr);
343         BLI_dynstr_free(dynstr);
344         return cstring;
345 }
346
347 int BPy_reports_to_error(ReportList *reports)
348 {
349         char *report_str;
350
351         report_str= BKE_reports_string(reports, RPT_ERROR);
352
353         if(report_str) {
354                 PyErr_SetString(PyExc_SystemError, report_str);
355                 MEM_freeN(report_str);
356         }
357
358         return (report_str != NULL);
359 }
360