Integrated unit testing framework with scons on Linux.
[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
131 /* Copied from pythons 3's Object.c */
132 #ifndef Py_CmpToRich
133 PyObject *
134 Py_CmpToRich(int op, int cmp)
135 {
136         PyObject *res;
137         int ok;
138
139         if (PyErr_Occurred())
140                 return NULL;
141         switch (op) {
142         case Py_LT:
143                 ok = cmp <  0;
144                 break;
145         case Py_LE:
146                 ok = cmp <= 0;
147                 break;
148         case Py_EQ:
149                 ok = cmp == 0;
150                 break;
151         case Py_NE:
152                 ok = cmp != 0;
153                 break;
154         case Py_GT:
155                 ok = cmp >  0;
156                 break;
157         case Py_GE:
158                 ok = cmp >= 0;
159                 break;
160         default:
161                 PyErr_BadArgument();
162                 return NULL;
163         }
164         res = ok ? Py_True : Py_False;
165         Py_INCREF(res);
166         return res;
167 }
168 #endif
169
170 /* for debugging */
171 void PyObSpit(char *name, PyObject *var) {
172         fprintf(stderr, "<%s> : ", name);
173         if (var==NULL) {
174                 fprintf(stderr, "<NIL>");
175         }
176         else {
177                 PyObject_Print(var, stderr, 0);
178                 fprintf(stderr, " ref:%d ", var->ob_refcnt);
179                 fprintf(stderr, " ptr:%p", (void *)var);
180                 
181                 fprintf(stderr, " type:");
182                 if(Py_TYPE(var))
183                         fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
184                 else
185                         fprintf(stderr, "<NIL>");
186         }
187         fprintf(stderr, "\n");
188 }
189
190 void PyLineSpit(void) {
191         char *filename;
192         int lineno;
193
194         PyErr_Clear();
195         BPY_getFileAndNum(&filename, &lineno);
196         
197         fprintf(stderr, "%s:%d\n", filename, lineno);
198 }
199
200 void BPY_getFileAndNum(char **filename, int *lineno)
201 {
202         PyObject *getframe, *frame;
203         PyObject *f_lineno= NULL, *co_filename= NULL;
204         
205         if (filename)   *filename= NULL;
206         if (lineno)             *lineno = -1;
207         
208         getframe = PySys_GetObject("_getframe"); // borrowed
209         if (getframe==NULL) {
210                 return;
211         }
212         
213         frame = PyObject_CallObject(getframe, NULL);
214         if (frame==NULL)
215                 return;
216         
217         if (filename) {
218                 co_filename= PyObject_GetAttrStringArgs(frame, 1, "f_code", "co_filename");
219                 if (co_filename==NULL) {
220                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_code.co_filename");
221                         Py_DECREF(frame);
222                         return;
223                 }
224                 
225                 *filename = _PyUnicode_AsString(co_filename);
226                 Py_DECREF(co_filename);
227         }
228         
229         if (lineno) {
230                 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
231                 if (f_lineno==NULL) {
232                         PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_lineno");
233                         Py_DECREF(frame);
234                         return;
235                 }
236                 
237                 *lineno = (int)PyLong_AsSsize_t(f_lineno);
238                 Py_DECREF(f_lineno);
239         }
240
241         Py_DECREF(frame);
242 }
243
244 /* Would be nice if python had this built in */
245 PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
246 {
247         Py_ssize_t i;
248         PyObject *item= o;
249         char *attr;
250         
251         va_list vargs;
252
253         va_start(vargs, n);
254         for (i=0; i<n; i++) {
255                 attr = va_arg(vargs, char *);
256                 item = PyObject_GetAttrString(item, attr);
257                 
258                 if (item) 
259                         Py_DECREF(item);
260                 else /* python will set the error value here */
261                         break;
262                 
263         }
264         va_end(vargs);
265         
266         Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
267         return item;
268 }
269
270 int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs)
271 {
272         PyObject *item, *fitem;
273         PyObject *py_arg_count;
274         int i, arg_count;
275
276         if (base_class) {
277                 if (!PyObject_IsSubclass(class, base_class)) {
278                         PyObject *name= PyObject_GetAttrString(base_class, "__name__");
279                         PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
280                         Py_XDECREF(name);
281                         return -1;
282                 }
283         }
284         
285         for(i= 0;class_attrs->name; class_attrs++, i++) {
286                 item = PyObject_GetAttrString(class, class_attrs->name);
287
288                 if (py_class_attrs)
289                         py_class_attrs[i]= item;
290                 
291                 if (item==NULL) {
292                         if ((class_attrs->flag & BPY_CLASS_ATTR_OPTIONAL)==0) {
293                                 PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, class_attrs->name);
294                                 return -1;
295                         }
296
297                         PyErr_Clear();
298                 }
299                 else {
300                         Py_DECREF(item); /* no need to keep a ref, the class owns it */
301
302                         if((item==Py_None) && (class_attrs->flag & BPY_CLASS_ATTR_NONE_OK)) {
303                                 /* dont do anything, this is ok, dont bother checking other types */
304                         }
305                         else {
306                                 switch(class_attrs->type) {
307                                 case 's':
308                                         if (PyUnicode_Check(item)==0) {
309                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a string", class_type, class_attrs->name);
310                                                 return -1;
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                                         break;
319                                 case 'f':
320                                         if (PyMethod_Check(item))
321                                                 fitem= PyMethod_Function(item); /* py 2.x */
322                                         else
323                                                 fitem= item; /* py 3.x */
324
325                                         if (PyFunction_Check(fitem)==0) {
326                                                 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, class_attrs->name);
327                                                 return -1;
328                                         }
329                                         if (class_attrs->arg_count >= 0) { /* -1 if we dont care*/
330                                                 py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(fitem), "co_argcount");
331                                                 arg_count = PyLong_AsSsize_t(py_arg_count);
332                                                 Py_DECREF(py_arg_count);
333
334                                                 if (arg_count != class_attrs->arg_count) {
335                                                         PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, class_attrs->name, class_attrs->arg_count);
336                                                         return -1;
337                                                 }
338                                         }
339                                         break;
340                                 }
341                         }
342                 }
343         }
344         return 0;
345 }
346
347
348
349 /* returns the exception string as a new PyUnicode object, depends on external StringIO module */
350 PyObject *BPY_exception_buffer(void)
351 {
352         PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
353         PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
354         PyObject *string_io = NULL;
355         PyObject *string_io_buf = NULL;
356         PyObject *string_io_mod;
357         PyObject *string_io_getvalue;
358         
359         PyObject *error_type, *error_value, *error_traceback;
360         
361         if (!PyErr_Occurred())
362                 return NULL;
363         
364         PyErr_Fetch(&error_type, &error_value, &error_traceback);
365         
366         PyErr_Clear();
367         
368         /* import StringIO / io
369          * string_io = StringIO.StringIO()
370          */
371         
372 #if PY_VERSION_HEX < 0x03000000
373         if(! (string_io_mod= PyImport_ImportModule("StringIO")) ) {
374 #else
375         if(! (string_io_mod= PyImport_ImportModule("io")) ) {
376 #endif
377                 return NULL;
378         } else if (! (string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) {
379                 Py_DECREF(string_io_mod);
380                 return NULL;
381         } else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, "getvalue"))) {
382                 Py_DECREF(string_io_mod);
383                 Py_DECREF(string_io);
384                 return NULL;
385         }
386         
387         Py_INCREF(stdout_backup); // since these were borrowed we dont want them freed when replaced.
388         Py_INCREF(stderr_backup);
389         
390         PySys_SetObject("stdout", string_io); // both of these are free'd when restoring
391         PySys_SetObject("stderr", string_io);
392         
393         PyErr_Restore(error_type, error_value, error_traceback);
394         PyErr_Print(); /* print the error */
395         PyErr_Clear();
396         
397         string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
398         
399         PySys_SetObject("stdout", stdout_backup);
400         PySys_SetObject("stderr", stderr_backup);
401         
402         Py_DECREF(stdout_backup); /* now sys owns the ref again */
403         Py_DECREF(stderr_backup);
404         
405         Py_DECREF(string_io_mod);
406         Py_DECREF(string_io_getvalue);
407         Py_DECREF(string_io); /* free the original reference */
408         
409         PyErr_Clear();
410         return string_io_buf;
411 }
412
413 char *BPy_enum_as_string(EnumPropertyItem *item)
414 {
415         DynStr *dynstr= BLI_dynstr_new();
416         EnumPropertyItem *e;
417         char *cstring;
418
419         for (e= item; item->identifier; item++) {
420                 BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
421         }
422
423         cstring = BLI_dynstr_get_cstring(dynstr);
424         BLI_dynstr_free(dynstr);
425         return cstring;
426 }
427
428 int BPy_reports_to_error(ReportList *reports)
429 {
430         char *report_str;
431
432         report_str= BKE_reports_string(reports, RPT_ERROR);
433
434         if(report_str) {
435                 PyErr_SetString(PyExc_SystemError, report_str);
436                 MEM_freeN(report_str);
437         }
438
439         return (report_str != NULL);
440 }
441
442
443 int BPy_errors_to_report(ReportList *reports)
444 {
445         PyObject *pystring;
446         char *cstring;
447         
448         if (!PyErr_Occurred())
449                 return 1;
450         
451         /* less hassle if we allow NULL */
452         if(reports==NULL) {
453                 PyErr_Print();
454                 PyErr_Clear();
455                 return 1;
456         }
457         
458         pystring= BPY_exception_buffer();
459         
460         if(pystring==NULL) {
461                 BKE_report(reports, RPT_ERROR, "unknown py-exception, could not convert");
462                 return 0;
463         }
464         
465         cstring= _PyUnicode_AsString(pystring);
466         
467         BKE_report(reports, RPT_ERROR, cstring);
468         fprintf(stderr, "%s\n", cstring); // not exactly needed. just for testing
469         Py_DECREF(pystring);
470         return 1;
471 }
472
473
474 /* bpy.util module */
475 static PyObject *bpy_util_copy_images(PyObject *self, PyObject *args);
476
477 struct PyMethodDef bpy_util_methods[] = {
478         {"copy_images", bpy_util_copy_images, METH_VARARGS, NULL},
479         {NULL, NULL, 0, NULL}
480 };
481
482 #if PY_VERSION_HEX >= 0x03000000
483 static struct PyModuleDef bpy_util_module = {
484         PyModuleDef_HEAD_INIT,
485         "bpyutil",
486         NULL,
487         -1,
488         bpy_util_methods,
489         NULL, NULL, NULL, NULL
490 };
491 #endif
492
493 PyObject *BPY_util_module( void )
494 {
495         PyObject *submodule, *dict;
496
497 #if PY_VERSION_HEX >= 0x03000000
498         submodule= PyModule_Create(&bpy_util_module);
499 #else /* Py2.x */
500         submodule= Py_InitModule3("bpyutil", bpy_util_methods, NULL);
501 #endif
502
503         dict = PyModule_GetDict(submodule);
504         
505         return submodule;
506 }
507
508 /*
509   copy_images(images, dest_dir)
510   return filenames
511 */
512 static PyObject *bpy_util_copy_images(PyObject *self, PyObject *args)
513 {
514         const char *dest_dir;
515         ListBase *images;
516         ListBase *paths;
517         LinkData *link;
518         PyObject *seq;
519         PyObject *ret;
520         PyObject *item;
521         int i;
522         int len;
523
524         /* check args/types */
525         if (!PyArg_ParseTuple(args, "Os", &seq, &dest_dir)) {
526                 PyErr_SetString(PyExc_TypeError, "Invalid arguments.");
527                 return NULL;
528         }
529
530         /* expecting a sequence of Image objects */
531         if (!PySequence_Check(seq)) {
532                 PyErr_SetString(PyExc_TypeError, "Expected a sequence of images.");
533                 return NULL;
534         }
535
536         /* create image list */
537         len= PySequence_Size(seq);
538
539         if (!len) {
540                 PyErr_SetString(PyExc_TypeError, "At least one image should be specified.");
541                 return NULL;
542         }
543
544         /* make sure all sequence items are Image */
545         for(i= 0; i < len; i++) {
546                 item= PySequence_GetItem(seq, i);
547
548                 if (!BPy_StructRNA_Check(item) || ((BPy_StructRNA*)item)->ptr.type != &RNA_Image) {
549                         PyErr_SetString(PyExc_TypeError, "Expected a sequence of Image objects.");
550                         return NULL;
551                 }
552         }
553
554         images= MEM_callocN(sizeof(*images), "ListBase of images");
555
556         for(i= 0; i < len; i++) {
557                 BPy_StructRNA* srna;
558
559                 item= PySequence_GetItem(seq, i);
560                 srna= (BPy_StructRNA*)item;
561
562                 link= MEM_callocN(sizeof(LinkData), "LinkData image");
563                 link->data= srna->ptr.data;
564                 BLI_addtail(images, link);
565
566                 Py_DECREF(item);
567         }
568
569         paths= MEM_callocN(sizeof(*paths), "ListBase of image paths");
570
571         /* call BKE_copy_images */
572         BKE_copy_images(images, dest_dir, paths);
573
574         /* convert filenames */
575         ret= PyList_New(0);
576         len= BLI_countlist(paths);
577
578         for(link= paths->first, i= 0; link; link++, i++) {
579                 if (link->data) {
580                         item= PyUnicode_FromString(link->data);
581                         PyList_Append(ret, item);
582                         Py_DECREF(item);
583                 }
584                 else {
585                         PyList_Append(ret, Py_None);
586                 }
587         }
588
589         /* free memory */
590         BLI_freelistN(images);
591         BLI_freelistN(paths);
592
593         /* return filenames */
594         return ret;
595 }