svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r22075:22099
[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         *flag = 0;
85
86         if (PySequence_Check(seq)) {
87                 i= PySequence_Length(seq);
88
89                 while(i--) {
90                         item = PySequence_ITEM(seq, i);
91                         cstring= _PyUnicode_AsString(item);
92                         if(cstring) {
93                                 fd= flagdef;
94                                 while(fd->name) {
95                                         if (strcmp(cstring, fd->name) == 0)
96                                                 (*flag) |= fd->flag;
97                                         fd++;
98                                 }
99                                 if (fd==NULL) { /* could not find a match */
100                                         error_val= 1;
101                                 }
102                         } else {
103                                 error_val= 1;
104                         }
105                         Py_DECREF(item);
106                 }
107         }
108         else {
109                 error_val= 1;
110         }
111
112         if (*flag == 0)
113                 error_val = 1;
114
115         if (error_val) {
116                 char *buf = bpy_flag_error_str(flagdef);
117                 PyErr_SetString(PyExc_AttributeError, buf);
118                 MEM_freeN(buf);
119                 return -1; /* error value */
120         }
121
122         return 0; /* ok */
123 }
124
125
126 /* Copied from pythons 3's Object.c */
127 #ifndef Py_CmpToRich
128 PyObject *
129 Py_CmpToRich(int op, int cmp)
130 {
131         PyObject *res;
132         int ok;
133
134         if (PyErr_Occurred())
135                 return NULL;
136         switch (op) {
137         case Py_LT:
138                 ok = cmp <  0;
139                 break;
140         case Py_LE:
141                 ok = cmp <= 0;
142                 break;
143         case Py_EQ:
144                 ok = cmp == 0;
145                 break;
146         case Py_NE:
147                 ok = cmp != 0;
148                 break;
149         case Py_GT:
150                 ok = cmp >  0;
151                 break;
152         case Py_GE:
153                 ok = cmp >= 0;
154                 break;
155         default:
156                 PyErr_BadArgument();
157                 return NULL;
158         }
159         res = ok ? Py_True : Py_False;
160         Py_INCREF(res);
161         return res;
162 }
163 #endif
164
165 /* for debugging */
166 void PyObSpit(char *name, PyObject *var) {
167         fprintf(stderr, "<%s> : ", name);
168         if (var==NULL) {
169                 fprintf(stderr, "<NIL>");
170         }
171         else {
172                 PyObject_Print(var, stderr, 0);
173                 fprintf(stderr, " ref:%d ", var->ob_refcnt);
174                 fprintf(stderr, " ptr:%p", (void *)var);
175                 
176                 fprintf(stderr, " type:");
177                 if(Py_TYPE(var))
178                         fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
179                 else
180                         fprintf(stderr, "<NIL>");
181         }
182         fprintf(stderr, "\n");
183 }
184
185 void PyLineSpit(void) {
186         char *filename;
187         int lineno;
188
189         PyErr_Clear();
190         BPY_getFileAndNum(&filename, &lineno);
191         
192         fprintf(stderr, "%s:%d\n", filename, lineno);
193 }
194
195 void BPY_getFileAndNum(char **filename, int *lineno)
196 {
197         PyObject *getframe, *frame;
198         PyObject *f_lineno= NULL, *co_filename= NULL;
199         
200         if (filename)   *filename= NULL;
201         if (lineno)             *lineno = -1;
202         
203         getframe = PySys_GetObject("_getframe"); // borrowed
204         if (getframe==NULL) {
205                 return;
206         }
207         
208         frame = PyObject_CallObject(getframe, NULL);
209         if (frame==NULL)
210                 return;
211         
212         if (filename) {
213                 co_filename= PyObject_GetAttrStringArgs(frame, 1, "f_code", "co_filename");
214                 if (co_filename==NULL) {
215                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_code.co_filename");
216                         Py_DECREF(frame);
217                         return;
218                 }
219                 
220                 *filename = _PyUnicode_AsString(co_filename);
221                 Py_DECREF(co_filename);
222         }
223         
224         if (lineno) {
225                 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
226                 if (f_lineno==NULL) {
227                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_lineno");
228                         Py_DECREF(frame);
229                         return;
230                 }
231                 
232                 *lineno = (int)PyLong_AsSsize_t(f_lineno);
233                 Py_DECREF(f_lineno);
234         }
235
236         Py_DECREF(frame);
237 }
238
239 /* Would be nice if python had this built in */
240 PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
241 {
242         Py_ssize_t i;
243         PyObject *item= o;
244         char *attr;
245         
246         va_list vargs;
247
248         va_start(vargs, n);
249         for (i=0; i<n; i++) {
250                 attr = va_arg(vargs, char *);
251                 item = PyObject_GetAttrString(item, attr);
252                 
253                 if (item) 
254                         Py_DECREF(item);
255                 else /* python will set the error value here */
256                         break;
257                 
258         }
259         va_end(vargs);
260         
261         Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
262         return item;
263 }
264
265 int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs)
266 {
267         PyObject *item, *fitem;
268         PyObject *py_arg_count;
269         int i, arg_count;
270
271         if (base_class) {
272                 if (!PyObject_IsSubclass(class, base_class)) {
273                         PyObject *name= PyObject_GetAttrString(base_class, "__name__");
274                         PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
275                         Py_XDECREF(name);
276                         return -1;
277                 }
278         }
279         
280         for(i= 0;class_attrs->name; class_attrs++, i++) {
281                 item = PyObject_GetAttrString(class, class_attrs->name);
282
283                 if (py_class_attrs)
284                         py_class_attrs[i]= item;
285                 
286                 if (item==NULL) {
287                         if ((class_attrs->flag & BPY_CLASS_ATTR_OPTIONAL)==0) {
288                                 PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, class_attrs->name);
289                                 return -1;
290                         }
291
292                         PyErr_Clear();
293                 }
294                 else {
295                         Py_DECREF(item); /* no need to keep a ref, the class owns it */
296
297                         if((item==Py_None) && (class_attrs->flag & BPY_CLASS_ATTR_NONE_OK)) {
298                                 /* dont do anything, this is ok, dont bother checking other types */
299                         }
300                         else {
301                                 switch(class_attrs->type) {
302                                 case 's':
303                                         if (PyUnicode_Check(item)==0) {
304                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a string", class_type, class_attrs->name);
305                                                 return -1;
306                                         }
307                                         if(class_attrs->len != -1 && class_attrs->len < PyUnicode_GetSize(item)) {
308                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute string to be shorter then %d", class_type, class_attrs->name, class_attrs->len);
309                                                 return -1;
310                                         }
311
312                                         break;
313                                 case 'l':
314                                         if (PyList_Check(item)==0) {
315                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a list", class_type, class_attrs->name);
316                                                 return -1;
317                                         }
318                                         if(class_attrs->len != -1 && class_attrs->len < PyList_GET_SIZE(item)) {
319                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute list to be shorter then %d", class_type, class_attrs->name, class_attrs->len);
320                                                 return -1;
321                                         }
322                                         break;
323                                 case 'f':
324                                         if (PyMethod_Check(item))
325                                                 fitem= PyMethod_Function(item); /* py 2.x */
326                                         else
327                                                 fitem= item; /* py 3.x */
328
329                                         if (PyFunction_Check(fitem)==0) {
330                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, class_attrs->name);
331                                                 return -1;
332                                         }
333                                         if (class_attrs->arg_count >= 0) { /* -1 if we dont care*/
334                                                 py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(fitem), "co_argcount");
335                                                 arg_count = PyLong_AsSsize_t(py_arg_count);
336                                                 Py_DECREF(py_arg_count);
337
338                                                 if (arg_count != class_attrs->arg_count) {
339                                                         PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, class_attrs->name, class_attrs->arg_count);
340                                                         return -1;
341                                                 }
342                                         }
343                                         break;
344                                 }
345                         }
346                 }
347         }
348         return 0;
349 }
350
351
352
353 /* returns the exception string as a new PyUnicode object, depends on external StringIO module */
354 PyObject *BPY_exception_buffer(void)
355 {
356         PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
357         PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
358         PyObject *string_io = NULL;
359         PyObject *string_io_buf = NULL;
360         PyObject *string_io_mod= NULL;
361         PyObject *string_io_getvalue= NULL;
362         
363         PyObject *error_type, *error_value, *error_traceback;
364         
365         if (!PyErr_Occurred())
366                 return NULL;
367         
368         PyErr_Fetch(&error_type, &error_value, &error_traceback);
369         
370         PyErr_Clear();
371         
372         /* import StringIO / io
373          * string_io = StringIO.StringIO()
374          */
375         
376 #if PY_VERSION_HEX < 0x03000000
377         if(! (string_io_mod= PyImport_ImportModule("StringIO")) ) {
378 #else
379         if(! (string_io_mod= PyImport_ImportModule("io")) ) {
380 #endif
381                 goto error_cleanup;
382         } else if (! (string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) {
383                 goto error_cleanup;
384         } else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, "getvalue"))) {
385                 goto error_cleanup;
386         }
387         
388         Py_INCREF(stdout_backup); // since these were borrowed we dont want them freed when replaced.
389         Py_INCREF(stderr_backup);
390         
391         PySys_SetObject("stdout", string_io); // both of these are free'd when restoring
392         PySys_SetObject("stderr", string_io);
393         
394         PyErr_Restore(error_type, error_value, error_traceback);
395         PyErr_Print(); /* print the error */
396         PyErr_Clear();
397         
398         string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
399         
400         PySys_SetObject("stdout", stdout_backup);
401         PySys_SetObject("stderr", stderr_backup);
402         
403         Py_DECREF(stdout_backup); /* now sys owns the ref again */
404         Py_DECREF(stderr_backup);
405         
406         Py_DECREF(string_io_mod);
407         Py_DECREF(string_io_getvalue);
408         Py_DECREF(string_io); /* free the original reference */
409         
410         PyErr_Clear();
411         return string_io_buf;
412         
413         
414 error_cleanup:
415         /* could not import the module so print the error and close */
416         Py_XDECREF(string_io_mod);
417         Py_XDECREF(string_io);
418         
419         PyErr_Restore(error_type, error_value, error_traceback);
420         PyErr_Print(); /* print the error */
421         PyErr_Clear();
422         
423         return NULL;
424 }
425
426 char *BPy_enum_as_string(EnumPropertyItem *item)
427 {
428         DynStr *dynstr= BLI_dynstr_new();
429         EnumPropertyItem *e;
430         char *cstring;
431
432         for (e= item; item->identifier; item++) {
433                 if(item->identifier[0])
434                         BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
435         }
436
437         cstring = BLI_dynstr_get_cstring(dynstr);
438         BLI_dynstr_free(dynstr);
439         return cstring;
440 }
441
442 int BPy_reports_to_error(ReportList *reports)
443 {
444         char *report_str;
445
446         report_str= BKE_reports_string(reports, RPT_ERROR);
447
448         if(report_str) {
449                 PyErr_SetString(PyExc_SystemError, report_str);
450                 MEM_freeN(report_str);
451         }
452
453         return (report_str != NULL);
454 }
455
456
457 int BPy_errors_to_report(ReportList *reports)
458 {
459         PyObject *pystring;
460         char *cstring;
461         
462         if (!PyErr_Occurred())
463                 return 1;
464         
465         /* less hassle if we allow NULL */
466         if(reports==NULL) {
467                 PyErr_Print();
468                 PyErr_Clear();
469                 return 1;
470         }
471         
472         pystring= BPY_exception_buffer();
473         
474         if(pystring==NULL) {
475                 BKE_report(reports, RPT_ERROR, "unknown py-exception, could not convert");
476                 return 0;
477         }
478         
479         cstring= _PyUnicode_AsString(pystring);
480         
481         BKE_report(reports, RPT_ERROR, cstring);
482         fprintf(stderr, "%s\n", cstring); // not exactly needed. just for testing
483         Py_DECREF(pystring);
484         return 1;
485 }