merge from trunk 38379
[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 /** \file blender/python/intern/bpy_util.c
26  *  \ingroup pythonintern
27  */
28
29
30 #include <Python.h>
31
32 #include "bpy_util.h"
33 #include "BLI_dynstr.h"
34 #include "MEM_guardedalloc.h"
35 #include "BKE_report.h"
36 #include "BKE_context.h"
37
38 #include "../generic/py_capi_utils.h"
39
40 static bContext*        __py_context= NULL;
41 bContext*       BPy_GetContext(void) { return __py_context; }
42 void            BPy_SetContext(bContext *C) { __py_context= C; }
43
44 char *BPy_enum_as_string(EnumPropertyItem *item)
45 {
46         DynStr *dynstr= BLI_dynstr_new();
47         EnumPropertyItem *e;
48         char *cstring;
49
50         for (e= item; item->identifier; item++) {
51                 if(item->identifier[0])
52                         BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
53         }
54
55         cstring= BLI_dynstr_get_cstring(dynstr);
56         BLI_dynstr_free(dynstr);
57         return cstring;
58 }
59
60 short BPy_reports_to_error(ReportList *reports, PyObject *exception, const short clear)
61 {
62         char *report_str;
63
64         report_str= BKE_reports_string(reports, RPT_ERROR);
65
66         if(clear) {
67                 BKE_reports_clear(reports);
68         }
69
70         if(report_str) {
71                 PyErr_SetString(exception, report_str);
72                 MEM_freeN(report_str);
73         }
74
75         return (report_str == NULL) ? 0 : -1;
76 }
77
78
79 short BPy_errors_to_report(ReportList *reports)
80 {
81         PyObject *pystring;
82         PyObject *pystring_format= NULL; // workaround, see below
83         char *cstring;
84
85         const char *filename;
86         int lineno;
87
88         if (!PyErr_Occurred())
89                 return 1;
90         
91         /* less hassle if we allow NULL */
92         if(reports==NULL) {
93                 PyErr_Print();
94                 PyErr_Clear();
95                 return 1;
96         }
97         
98         pystring= PyC_ExceptionBuffer();
99         
100         if(pystring==NULL) {
101                 BKE_report(reports, RPT_ERROR, "unknown py-exception, couldn't convert");
102                 return 0;
103         }
104         
105         PyC_FileAndNum(&filename, &lineno);
106         if(filename==NULL)
107                 filename= "<unknown location>";
108         
109         cstring= _PyUnicode_AsString(pystring);
110
111 #if 0 // ARG!. workaround for a bug in blenders use of vsnprintf
112         BKE_reportf(reports, RPT_ERROR, "%s\nlocation:%s:%d\n", cstring, filename, lineno);
113 #else
114         pystring_format= PyUnicode_FromFormat("%s\nlocation:%s:%d\n", cstring, filename, lineno);
115         cstring= _PyUnicode_AsString(pystring_format);
116         BKE_report(reports, RPT_ERROR, cstring);
117 #endif
118         
119         fprintf(stderr, "%s\nlocation:%s:%d\n", cstring, filename, lineno); // not exactly needed. just for testing
120         
121         Py_DECREF(pystring);
122         Py_DECREF(pystring_format); // workaround
123         return 1;
124 }