4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * Contributor(s): Campbell Barton
22 * ***** END GPL LICENSE BLOCK *****
25 #include "DNA_listBase.h"
26 #include "RNA_access.h"
28 #include "BLI_dynstr.h"
29 #include "MEM_guardedalloc.h"
30 #include "BKE_report.h"
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; };
39 PyObject *BPY_flag_to_list(struct BPY_flag_def *flagdef, int flag)
41 PyObject *list = PyList_New(0);
48 if (fd->flag & flag) {
49 item = PyUnicode_FromString(fd->name);
50 PyList_Append(list, item);
60 static char *bpy_flag_error_str(BPY_flag_def *flagdef)
62 BPY_flag_def *fd= flagdef;
63 DynStr *dynstr= BLI_dynstr_new();
66 BLI_dynstr_append(dynstr, "Error converting a sequence of strings into a flag.\n\tExpected only these strings...\n\t");
69 BLI_dynstr_appendf(dynstr, fd!=flagdef?", '%s'":"'%s'", fd->name);
73 cstring = BLI_dynstr_get_cstring(dynstr);
74 BLI_dynstr_free(dynstr);
78 int BPY_flag_from_seq(BPY_flag_def *flagdef, PyObject *seq, int *flag)
86 if (PySequence_Check(seq)) {
87 i= PySequence_Length(seq);
90 item = PySequence_ITEM(seq, i);
91 cstring= _PyUnicode_AsString(item);
95 if (strcmp(cstring, fd->name) == 0)
99 if (fd==NULL) { /* could not find a match */
116 char *buf = bpy_flag_error_str(flagdef);
117 PyErr_SetString(PyExc_AttributeError, buf);
119 return -1; /* error value */
126 void PyObSpit(char *name, PyObject *var) {
127 fprintf(stderr, "<%s> : ", name);
129 fprintf(stderr, "<NIL>");
132 PyObject_Print(var, stderr, 0);
133 fprintf(stderr, " ref:%d ", (int)var->ob_refcnt);
134 fprintf(stderr, " ptr:%p", (void *)var);
136 fprintf(stderr, " type:");
138 fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
140 fprintf(stderr, "<NIL>");
142 fprintf(stderr, "\n");
145 void PyLineSpit(void) {
150 BPY_getFileAndNum(&filename, &lineno);
152 fprintf(stderr, "%s:%d\n", filename, lineno);
155 void BPY_getFileAndNum(char **filename, int *lineno)
157 PyObject *getframe, *frame;
158 PyObject *f_lineno= NULL, *co_filename= NULL;
160 if (filename) *filename= NULL;
161 if (lineno) *lineno = -1;
163 getframe = PySys_GetObject("_getframe"); // borrowed
164 if (getframe==NULL) {
169 frame = PyObject_CallObject(getframe, NULL);
176 co_filename= PyObject_GetAttrStringArgs(frame, 1, "f_code", "co_filename");
177 if (co_filename==NULL) {
178 PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_code.co_filename");
183 *filename = _PyUnicode_AsString(co_filename);
184 Py_DECREF(co_filename);
188 f_lineno= PyObject_GetAttrString(frame, "f_lineno");
189 if (f_lineno==NULL) {
190 PyErr_SetString(PyExc_SystemError, "Could not access sys._getframe().f_lineno");
195 *lineno = (int)PyLong_AsSsize_t(f_lineno);
202 /* Would be nice if python had this built in */
203 PyObject *PyObject_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...)
212 for (i=0; i<n; i++) {
213 attr = va_arg(vargs, char *);
214 item = PyObject_GetAttrString(item, attr);
218 else /* python will set the error value here */
224 Py_XINCREF(item); /* final value has is increfed, to match PyObject_GetAttrString */
228 int BPY_class_validate(const char *class_type, PyObject *class, PyObject *base_class, BPY_class_attr_check* class_attrs, PyObject **py_class_attrs)
230 PyObject *item, *fitem;
231 PyObject *py_arg_count;
235 if (!PyObject_IsSubclass(class, base_class)) {
236 PyObject *name= PyObject_GetAttrString(base_class, "__name__");
237 PyErr_Format( PyExc_AttributeError, "expected %s subclass of class \"%s\"", class_type, name ? _PyUnicode_AsString(name):"<UNKNOWN>");
243 for(i= 0;class_attrs->name; class_attrs++, i++) {
244 item = PyObject_GetAttrString(class, class_attrs->name);
247 py_class_attrs[i]= item;
250 if ((class_attrs->flag & BPY_CLASS_ATTR_OPTIONAL)==0) {
251 PyErr_Format( PyExc_AttributeError, "expected %s class to have an \"%s\" attribute", class_type, class_attrs->name);
258 Py_DECREF(item); /* no need to keep a ref, the class owns it */
260 if((item==Py_None) && (class_attrs->flag & BPY_CLASS_ATTR_NONE_OK)) {
261 /* dont do anything, this is ok, dont bother checking other types */
264 switch(class_attrs->type) {
266 if (PyUnicode_Check(item)==0) {
267 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a string", class_type, class_attrs->name);
270 if(class_attrs->len != -1 && class_attrs->len < PyUnicode_GetSize(item)) {
271 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute string to be shorter then %d", class_type, class_attrs->name, class_attrs->len);
277 if (PyList_Check(item)==0) {
278 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a list", class_type, class_attrs->name);
281 if(class_attrs->len != -1 && class_attrs->len < PyList_GET_SIZE(item)) {
282 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute list to be shorter then %d", class_type, class_attrs->name, class_attrs->len);
287 if (PyMethod_Check(item))
288 fitem= PyMethod_Function(item); /* py 2.x */
290 fitem= item; /* py 3.x */
292 if (PyFunction_Check(fitem)==0) {
293 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" attribute to be a function", class_type, class_attrs->name);
296 if (class_attrs->arg_count >= 0) { /* -1 if we dont care*/
297 py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(fitem), "co_argcount");
298 arg_count = PyLong_AsSsize_t(py_arg_count);
299 Py_DECREF(py_arg_count);
301 if (arg_count != class_attrs->arg_count) {
302 PyErr_Format( PyExc_AttributeError, "expected %s class \"%s\" function to have %d args", class_type, class_attrs->name, class_attrs->arg_count);
316 /* returns the exception string as a new PyUnicode object, depends on external StringIO module */
317 PyObject *BPY_exception_buffer(void)
319 PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
320 PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
321 PyObject *string_io = NULL;
322 PyObject *string_io_buf = NULL;
323 PyObject *string_io_mod= NULL;
324 PyObject *string_io_getvalue= NULL;
326 PyObject *error_type, *error_value, *error_traceback;
328 if (!PyErr_Occurred())
331 PyErr_Fetch(&error_type, &error_value, &error_traceback);
335 /* import StringIO / io
336 * string_io = StringIO.StringIO()
339 if(! (string_io_mod= PyImport_ImportModule("io")) ) {
341 } else if (! (string_io = PyObject_CallMethod(string_io_mod, "StringIO", NULL))) {
343 } else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, "getvalue"))) {
347 Py_INCREF(stdout_backup); // since these were borrowed we dont want them freed when replaced.
348 Py_INCREF(stderr_backup);
350 PySys_SetObject("stdout", string_io); // both of these are free'd when restoring
351 PySys_SetObject("stderr", string_io);
353 PyErr_Restore(error_type, error_value, error_traceback);
354 PyErr_Print(); /* print the error */
357 string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
359 PySys_SetObject("stdout", stdout_backup);
360 PySys_SetObject("stderr", stderr_backup);
362 Py_DECREF(stdout_backup); /* now sys owns the ref again */
363 Py_DECREF(stderr_backup);
365 Py_DECREF(string_io_mod);
366 Py_DECREF(string_io_getvalue);
367 Py_DECREF(string_io); /* free the original reference */
370 return string_io_buf;
374 /* could not import the module so print the error and close */
375 Py_XDECREF(string_io_mod);
376 Py_XDECREF(string_io);
378 PyErr_Restore(error_type, error_value, error_traceback);
379 PyErr_Print(); /* print the error */
385 char *BPy_enum_as_string(EnumPropertyItem *item)
387 DynStr *dynstr= BLI_dynstr_new();
391 for (e= item; item->identifier; item++) {
392 if(item->identifier[0])
393 BLI_dynstr_appendf(dynstr, (e==item)?"'%s'":", '%s'", item->identifier);
396 cstring = BLI_dynstr_get_cstring(dynstr);
397 BLI_dynstr_free(dynstr);
401 int BPy_reports_to_error(ReportList *reports)
405 report_str= BKE_reports_string(reports, RPT_ERROR);
408 PyErr_SetString(PyExc_SystemError, report_str);
409 MEM_freeN(report_str);
412 return (report_str != NULL);
416 int BPy_errors_to_report(ReportList *reports)
419 PyObject *pystring_format= NULL; // workaround, see below
425 if (!PyErr_Occurred())
428 /* less hassle if we allow NULL */
435 pystring= BPY_exception_buffer();
438 BKE_report(reports, RPT_ERROR, "unknown py-exception, could not convert");
442 BPY_getFileAndNum(&filename, &lineno);
444 filename= "<unknown location>";
446 cstring= _PyUnicode_AsString(pystring);
448 #if 0 // ARG!. workaround for a bug in blenders use of vsnprintf
449 BKE_reportf(reports, RPT_ERROR, "%s\nlocation:%s:%d\n", cstring, filename, lineno);
451 pystring_format= PyUnicode_FromFormat("%s\nlocation:%s:%d\n", cstring, filename, lineno);
452 cstring= _PyUnicode_AsString(pystring_format);
453 BKE_report(reports, RPT_ERROR, cstring);
456 fprintf(stderr, "%s\nlocation:%s:%d\n", cstring, filename, lineno); // not exactly needed. just for testing
459 Py_DECREF(pystring_format); // workaround