doxygen: prevent GPL license block from being parsed as doxygen comment.
[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 <Python.h>
26
27 #include "bpy_util.h"
28 #include "BLI_dynstr.h"
29 #include "MEM_guardedalloc.h"
30 #include "BKE_report.h"
31 #include "BKE_context.h"
32
33 #include "../generic/py_capi_utils.h"
34
35 static bContext*        __py_context = NULL;
36 bContext*       BPy_GetContext(void) { return __py_context; }
37 void            BPy_SetContext(bContext *C) { __py_context= C; }
38
39 char *BPy_enum_as_string(EnumPropertyItem *item)
40 {
41         DynStr *dynstr= BLI_dynstr_new();
42         EnumPropertyItem *e;
43         char *cstring;
44
45         for (e= item; item->identifier; item++) {
46                 if(item->identifier[0])
47                         BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
48         }
49
50         cstring = BLI_dynstr_get_cstring(dynstr);
51         BLI_dynstr_free(dynstr);
52         return cstring;
53 }
54
55 short BPy_reports_to_error(ReportList *reports, const short clear)
56 {
57         char *report_str;
58
59         report_str= BKE_reports_string(reports, RPT_ERROR);
60
61         if(clear) {
62                 BKE_reports_clear(reports);
63         }
64
65         if(report_str) {
66                 PyErr_SetString(PyExc_RuntimeError, report_str);
67                 MEM_freeN(report_str);
68         }
69
70         return (report_str != NULL);
71 }
72
73
74 short BPy_errors_to_report(ReportList *reports)
75 {
76         PyObject *pystring;
77         PyObject *pystring_format= NULL; // workaround, see below
78         char *cstring;
79
80         const char *filename;
81         int lineno;
82
83         if (!PyErr_Occurred())
84                 return 1;
85         
86         /* less hassle if we allow NULL */
87         if(reports==NULL) {
88                 PyErr_Print();
89                 PyErr_Clear();
90                 return 1;
91         }
92         
93         pystring= PyC_ExceptionBuffer();
94         
95         if(pystring==NULL) {
96                 BKE_report(reports, RPT_ERROR, "unknown py-exception, could not convert");
97                 return 0;
98         }
99         
100         PyC_FileAndNum(&filename, &lineno);
101         if(filename==NULL)
102                 filename= "<unknown location>";
103         
104         cstring= _PyUnicode_AsString(pystring);
105
106 #if 0 // ARG!. workaround for a bug in blenders use of vsnprintf
107         BKE_reportf(reports, RPT_ERROR, "%s\nlocation:%s:%d\n", cstring, filename, lineno);
108 #else
109         pystring_format= PyUnicode_FromFormat("%s\nlocation:%s:%d\n", cstring, filename, lineno);
110         cstring= _PyUnicode_AsString(pystring_format);
111         BKE_report(reports, RPT_ERROR, cstring);
112 #endif
113         
114         fprintf(stderr, "%s\nlocation:%s:%d\n", cstring, filename, lineno); // not exactly needed. just for testing
115         
116         Py_DECREF(pystring);
117         Py_DECREF(pystring_format); // workaround
118         return 1;
119 }
120
121 /* array utility function */
122 int PyC_AsArray(void *array, PyObject *value, int length, PyTypeObject *type, const char *error_prefix)
123 {
124         PyObject *value_fast;
125         int value_len;
126         int i;
127
128         if(!(value_fast=PySequence_Fast(value, error_prefix))) {
129                 return -1;
130         }
131
132         value_len= PySequence_Fast_GET_SIZE(value_fast);
133
134         if(value_len != length) {
135                 Py_DECREF(value);
136                 PyErr_Format(PyExc_TypeError, "%.200s: invalid sequence length. expected %d, got %d", error_prefix, length, value_len);
137                 return -1;
138         }
139
140         /* for each type */
141         if(type == &PyFloat_Type) {
142                 float *array_float= array;
143                 for(i=0; i<length; i++) {
144                         array_float[i] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
145                 }
146         }
147         else if(type == &PyLong_Type) {
148                 int *array_int= array;
149                 for(i=0; i<length; i++) {
150                         array_int[i] = PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
151                 }
152         }
153         else if(type == &PyBool_Type) {
154                 int *array_bool= array;
155                 for(i=0; i<length; i++) {
156                         array_bool[i] = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
157                 }
158         }
159         else {
160                 Py_DECREF(value_fast);
161                 PyErr_Format(PyExc_TypeError, "%s: internal error %s is invalid", error_prefix, type->tp_name);
162                 return -1;
163         }
164
165         Py_DECREF(value_fast);
166
167         if(PyErr_Occurred()) {
168                 PyErr_Format(PyExc_TypeError, "%s: one or more items could not be used as a %s", error_prefix, type->tp_name);
169                 return -1;
170         }
171
172         return 0;
173 }