whitespace edits for bpy api, split some really long lines.
[blender-staging.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 }
125
126 /* array utility function */
127 int PyC_AsArray(void *array, PyObject *value, int length, PyTypeObject *type, const char *error_prefix)
128 {
129         PyObject *value_fast;
130         int value_len;
131         int i;
132
133         if(!(value_fast=PySequence_Fast(value, error_prefix))) {
134                 return -1;
135         }
136
137         value_len= PySequence_Fast_GET_SIZE(value_fast);
138
139         if(value_len != length) {
140                 Py_DECREF(value);
141                 PyErr_Format(PyExc_TypeError,
142                              "%.200s: invalid sequence length. expected %d, got %d",
143                              error_prefix, length, value_len);
144                 return -1;
145         }
146
147         /* for each type */
148         if(type == &PyFloat_Type) {
149                 float *array_float= array;
150                 for(i=0; i<length; i++) {
151                         array_float[i]= PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value_fast, i));
152                 }
153         }
154         else if(type == &PyLong_Type) {
155                 int *array_int= array;
156                 for(i=0; i<length; i++) {
157                         array_int[i]= PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i));
158                 }
159         }
160         else if(type == &PyBool_Type) {
161                 int *array_bool= array;
162                 for(i=0; i<length; i++) {
163                         array_bool[i]= (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value_fast, i)) != 0);
164                 }
165         }
166         else {
167                 Py_DECREF(value_fast);
168                 PyErr_Format(PyExc_TypeError,
169                              "%s: internal error %s is invalid",
170                              error_prefix, type->tp_name);
171                 return -1;
172         }
173
174         Py_DECREF(value_fast);
175
176         if(PyErr_Occurred()) {
177                 PyErr_Format(PyExc_TypeError,
178                              "%s: one or more items could not be used as a %s",
179                              error_prefix, type->tp_name);
180                 return -1;
181         }
182
183         return 0;
184 }