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