remove unused includes
[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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Campbell Barton
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include "bpy_util.h"
26 #include "BLI_dynstr.h"
27 #include "MEM_guardedalloc.h"
28 #include "BKE_report.h"
29
30
31 #include "BKE_context.h"
32 bContext*       __py_context = NULL;
33 bContext*       BPy_GetContext(void) { return __py_context; };
34 void            BPy_SetContext(bContext *C) { __py_context= C; };
35
36 /* for debugging */
37 void PyObSpit(char *name, PyObject *var) {
38         fprintf(stderr, "<%s> : ", name);
39         if (var==NULL) {
40                 fprintf(stderr, "<NIL>");
41         }
42         else {
43                 PyObject_Print(var, stderr, 0);
44                 fprintf(stderr, " ref:%d ", (int)var->ob_refcnt);
45                 fprintf(stderr, " ptr:%p", (void *)var);
46                 
47                 fprintf(stderr, " type:");
48                 if(Py_TYPE(var))
49                         fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
50                 else
51                         fprintf(stderr, "<NIL>");
52         }
53         fprintf(stderr, "\n");
54 }
55
56 void PyLineSpit(void) {
57         char *filename;
58         int lineno;
59
60         PyErr_Clear();
61         BPY_getFileAndNum(&filename, &lineno);
62         
63         fprintf(stderr, "%s:%d\n", filename, lineno);
64 }
65
66 void BPY_getFileAndNum(char **filename, int *lineno)
67 {
68         PyObject *getframe, *frame;
69         PyObject *f_lineno= NULL, *co_filename= NULL;
70         
71         if (filename)   *filename= NULL;
72         if (lineno)             *lineno = -1;
73         
74         getframe = PySys_GetObject("_getframe"); // borrowed
75         if (getframe==NULL) {
76                 PyErr_Clear();
77                 return;
78         }
79         
80         frame = PyObject_CallObject(getframe, NULL);
81         if (frame==NULL) {
82                 PyErr_Clear();
83                 return;
84         }
85         
86         if (filename) {
87                 co_filename= PyObject_GetAttrStringArgs(frame, 1, "f_code", "co_filename");
88                 if (co_filename==NULL) {
89                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_code.co_filename");
90                         Py_DECREF(frame);
91                         return;
92                 }
93                 
94                 *filename = _PyUnicode_AsString(co_filename);
95                 Py_DECREF(co_filename);
96         }
97         
98         if (lineno) {
99                 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
100                 if (f_lineno==NULL) {
101                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_lineno");
102                         Py_DECREF(frame);
103                         return;
104                 }
105                 
106                 *lineno = (int)PyLong_AsSsize_t(f_lineno);
107                 Py_DECREF(f_lineno);
108         }
109
110         Py_DECREF(frame);
111 }
112
113 /* Would be nice if python had this built in */
114 PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
115 {
116         Py_ssize_t i;
117         PyObject *item= o;
118         char *attr;
119         
120         va_list vargs;
121
122         va_start(vargs, n);
123         for (i=0; i<n; i++) {
124                 attr = va_arg(vargs, char *);
125                 item = PyObject_GetAttrString(item, attr);
126                 
127                 if (item) 
128                         Py_DECREF(item);
129                 else /* python will set the error value here */
130                         break;
131                 
132         }
133         va_end(vargs);
134         
135         Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
136         return item;
137 }
138
139 int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs)
140 {
141         PyObject *item, *fitem;
142         PyObject *py_arg_count;
143         int i, arg_count;
144
145         if (base_class) {
146                 if (!PyObject_IsSubclass(class, base_class)) {
147                         PyObject *name= PyObject_GetAttrString(base_class, "__name__");
148                         PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
149                         Py_XDECREF(name);
150                         return -1;
151                 }
152         }
153         
154         for(i= 0;class_attrs->name; class_attrs++, i++) {
155                 item = PyObject_GetAttrString(class, class_attrs->name);
156
157                 if (py_class_attrs)
158                         py_class_attrs[i]= item;
159                 
160                 if (item==NULL) {
161                         if ((class_attrs->flag & BPY_CLASS_ATTR_OPTIONAL)==0) {
162                                 PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, class_attrs->name);
163                                 return -1;
164                         }
165
166                         PyErr_Clear();
167                 }
168                 else {
169                         Py_DECREF(item); /* no need to keep a ref, the class owns it */
170
171                         if((item==Py_None) && (class_attrs->flag & BPY_CLASS_ATTR_NONE_OK)) {
172                                 /* dont do anything, this is ok, dont bother checking other types */
173                         }
174                         else {
175                                 switch(class_attrs->type) {
176                                 case 's':
177                                         if (PyUnicode_Check(item)==0) {
178                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a string", class_type, class_attrs->name);
179                                                 return -1;
180                                         }
181                                         if(class_attrs->len != -1 && class_attrs->len < PyUnicode_GetSize(item)) {
182                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute string to be shorter then %d", class_type, class_attrs->name, class_attrs->len);
183                                                 return -1;
184                                         }
185
186                                         break;
187                                 case 'l':
188                                         if (PyList_Check(item)==0) {
189                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a list", class_type, class_attrs->name);
190                                                 return -1;
191                                         }
192                                         if(class_attrs->len != -1 && class_attrs->len < PyList_GET_SIZE(item)) {
193                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute list to be shorter then %d", class_type, class_attrs->name, class_attrs->len);
194                                                 return -1;
195                                         }
196                                         break;
197                                 case 'f':
198                                         if (PyMethod_Check(item))
199                                                 fitem= PyMethod_Function(item); /* py 2.x */
200                                         else
201                                                 fitem= item; /* py 3.x */
202
203                                         if (PyFunction_Check(fitem)==0) {
204                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, class_attrs->name);
205                                                 return -1;
206                                         }
207                                         if (class_attrs->arg_count >= 0) { /* -1 if we dont care*/
208                                                 py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(fitem), "co_argcount");
209                                                 arg_count = PyLong_AsSsize_t(py_arg_count);
210                                                 Py_DECREF(py_arg_count);
211
212                                                 if (arg_count != class_attrs->arg_count) {
213                                                         PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, class_attrs->name, class_attrs->arg_count);
214                                                         return -1;
215                                                 }
216                                         }
217                                         break;
218                                 }
219                         }
220                 }
221         }
222         return 0;
223 }
224
225
226
227 /* returns the exception string as a new PyUnicode object, depends on external StringIO module */
228 PyObject *BPY_exception_buffer(void)
229 {
230         PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
231         PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
232         PyObject *string_io = NULL;
233         PyObject *string_io_buf = NULL;
234         PyObject *string_io_mod= NULL;
235         PyObject *string_io_getvalue= NULL;
236         
237         PyObject *error_type, *error_value, *error_traceback;
238         
239         if (!PyErr_Occurred())
240                 return NULL;
241         
242         PyErr_Fetch(&error_type, &error_value, &error_traceback);
243         
244         PyErr_Clear();
245         
246         /* import StringIO / io
247          * string_io = StringIO.StringIO()
248          */
249         
250         if(! (string_io_mod= PyImport_ImportModule("io")) ) {
251                 goto error_cleanup;
252         } else if (! (string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) {
253                 goto error_cleanup;
254         } else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, "getvalue"))) {
255                 goto error_cleanup;
256         }
257         
258         Py_INCREF(stdout_backup); // since these were borrowed we dont want them freed when replaced.
259         Py_INCREF(stderr_backup);
260         
261         PySys_SetObject("stdout", string_io); // both of these are free'd when restoring
262         PySys_SetObject("stderr", string_io);
263         
264         PyErr_Restore(error_type, error_value, error_traceback);
265         PyErr_Print(); /* print the error */
266         PyErr_Clear();
267         
268         string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
269         
270         PySys_SetObject("stdout", stdout_backup);
271         PySys_SetObject("stderr", stderr_backup);
272         
273         Py_DECREF(stdout_backup); /* now sys owns the ref again */
274         Py_DECREF(stderr_backup);
275         
276         Py_DECREF(string_io_mod);
277         Py_DECREF(string_io_getvalue);
278         Py_DECREF(string_io); /* free the original reference */
279         
280         PyErr_Clear();
281         return string_io_buf;
282         
283         
284 error_cleanup:
285         /* could not import the module so print the error and close */
286         Py_XDECREF(string_io_mod);
287         Py_XDECREF(string_io);
288         
289         PyErr_Restore(error_type, error_value, error_traceback);
290         PyErr_Print(); /* print the error */
291         PyErr_Clear();
292         
293         return NULL;
294 }
295
296 char *BPy_enum_as_string(EnumPropertyItem *item)
297 {
298         DynStr *dynstr= BLI_dynstr_new();
299         EnumPropertyItem *e;
300         char *cstring;
301
302         for (e= item; item->identifier; item++) {
303                 if(item->identifier[0])
304                         BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
305         }
306
307         cstring = BLI_dynstr_get_cstring(dynstr);
308         BLI_dynstr_free(dynstr);
309         return cstring;
310 }
311
312 int BPy_reports_to_error(ReportList *reports)
313 {
314         char *report_str;
315
316         report_str= BKE_reports_string(reports, RPT_ERROR);
317
318         if(report_str) {
319                 PyErr_SetString(PyExc_SystemError, report_str);
320                 MEM_freeN(report_str);
321         }
322
323         return (report_str != NULL);
324 }
325
326
327 int BPy_errors_to_report(ReportList *reports)
328 {
329         PyObject *pystring;
330         PyObject *pystring_format= NULL; // workaround, see below
331         char *cstring;
332
333         char *filename;
334         int lineno;
335
336         if (!PyErr_Occurred())
337                 return 1;
338         
339         /* less hassle if we allow NULL */
340         if(reports==NULL) {
341                 PyErr_Print();
342                 PyErr_Clear();
343                 return 1;
344         }
345         
346         pystring= BPY_exception_buffer();
347         
348         if(pystring==NULL) {
349                 BKE_report(reports, RPT_ERROR, "unknown py-exception, could not convert");
350                 return 0;
351         }
352         
353         BPY_getFileAndNum(&filename, &lineno);
354         if(filename==NULL)
355                 filename= "<unknown location>";
356         
357         cstring= _PyUnicode_AsString(pystring);
358
359 #if 0 // ARG!. workaround for a bug in blenders use of vsnprintf
360         BKE_reportf(reports, RPT_ERROR, "%s\nlocation:%s:%d\n", cstring, filename, lineno);
361 #else
362         pystring_format= PyUnicode_FromFormat("%s\nlocation:%s:%d\n", cstring, filename, lineno);
363         cstring= _PyUnicode_AsString(pystring_format);
364         BKE_report(reports, RPT_ERROR, cstring);
365 #endif
366         
367         fprintf(stderr, "%s\nlocation:%s:%d\n", cstring, filename, lineno); // not exactly needed. just for testing
368         
369         Py_DECREF(pystring);
370         Py_DECREF(pystring_format); // workaround
371         return 1;
372 }
373
374 /* array utility function */
375 int BPyAsPrimitiveArray(void *array, PyObject *value, int length, PyTypeObject *type, char *error_prefix)
376 {
377         PyObject *value_fast;
378         int value_len;
379         int i;
380
381         if(!(value_fast=PySequence_Fast(value, error_prefix))) {
382                 return -1;
383         }
384
385         value_len= PySequence_Fast_GET_SIZE(value_fast);
386
387         if(value_len != length) {
388                 Py_DECREF(value);
389                 PyErr_Format(PyExc_TypeError, "%s: invalid sequence length. expected %d, got %d.", error_prefix, length, value_len);
390                 return -1;
391         }
392
393         /* for each type */
394         if(type == &PyFloat_Type) {
395                 float *array_float= array;
396                 for(i=0; i<length; i++) {
397                         array_float[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
398                 }
399         }
400         else if(type == &PyLong_Type) {
401                 int *array_int= array;
402                 for(i=0; i<length; i++) {
403                         array_int[i] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
404                 }
405         }
406         else if(type == &PyBool_Type) {
407                 int *array_bool= array;
408                 for(i=0; i<length; i++) {
409                         array_bool[i] = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
410                 }
411         }
412         else {
413                 Py_DECREF(value_fast);
414                 PyErr_Format(PyExc_TypeError, "%s: internal error %s is invalid.", error_prefix, type->tp_name);
415                 return -1;
416         }
417
418         Py_DECREF(value_fast);
419
420         if(PyErr_Occurred()) {
421                 PyErr_Format(PyExc_TypeError, "%s: one or more items could not be used as a %s.", error_prefix, type->tp_name);
422                 return -1;
423         }
424
425         return 0;
426 }