1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 */
16
17 /** \file
18 * \ingroup pythonintern
19 *
20 * This file contains Blender/Python utility functions to help implementing API's.
21 * This is not related to a particular module.
22 */
23
24 #include <Python.h>
25
26 #include "BLI_dynstr.h"
27 #include "BLI_listbase.h"
28 #include "BLI_utildefines.h"
29
30 #include "bpy_capi_utils.h"
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BKE_context.h"
35 #include "BKE_report.h"
36
37 #include "BLT_translation.h"
38
39 #include "../generic/py_capi_utils.h"
40
BPy_enum_as_string(const EnumPropertyItem * item)41 char *BPy_enum_as_string(const EnumPropertyItem *item)
42 {
43 DynStr *dynstr = BLI_dynstr_new();
44
45 /* We can't compare with the first element in the array
46 * since it may be a category (without an identifier). */
47 for (bool is_first = true; item->identifier; item++) {
48 if (item->identifier[0]) {
49 BLI_dynstr_appendf(dynstr, is_first ? "'%s'" : ", '%s'", item->identifier);
50 is_first = false;
51 }
52 }
53
54 char *cstring = BLI_dynstr_get_cstring(dynstr);
55 BLI_dynstr_free(dynstr);
56 return cstring;
57 }
58
BPy_reports_to_error(ReportList * reports,PyObject * exception,const bool clear)59 short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
60 {
61 char *report_str;
62
63 report_str = BKE_reports_string(reports, RPT_ERROR);
64
65 if (clear == true) {
66 BKE_reports_clear(reports);
67 }
68
69 if (report_str) {
70 PyErr_SetString(exception, report_str);
71 MEM_freeN(report_str);
72 }
73
74 return (report_str == NULL) ? 0 : -1;
75 }
76
77 /**
78 * A version of #BKE_report_write_file_fp that uses Python's stdout.
79 */
BPy_reports_write_stdout(const ReportList * reports,const char * header)80 void BPy_reports_write_stdout(const ReportList *reports, const char *header)
81 {
82 if (header) {
83 PySys_WriteStdout("%s\n", header);
84 }
85
86 LISTBASE_FOREACH (const Report *, report, &reports->list) {
87 PySys_WriteStdout("%s: %s\n", report->typestr, report->message);
88 }
89 }
90
BPy_errors_to_report_ex(ReportList * reports,const char * error_prefix,const bool use_full,const bool use_location)91 bool BPy_errors_to_report_ex(ReportList *reports,
92 const char *error_prefix,
93 const bool use_full,
94 const bool use_location)
95 {
96 PyObject *pystring;
97
98 if (!PyErr_Occurred()) {
99 return 1;
100 }
101
102 /* less hassle if we allow NULL */
103 if (reports == NULL) {
104 PyErr_Print();
105 PyErr_Clear();
106 return 1;
107 }
108
109 if (use_full) {
110 pystring = PyC_ExceptionBuffer();
111 }
112 else {
113 pystring = PyC_ExceptionBuffer_Simple();
114 }
115
116 if (pystring == NULL) {
117 BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert");
118 return 0;
119 }
120
121 if (error_prefix == NULL) {
122 /* Not very helpful, better than nothing. */
123 error_prefix = "Python";
124 }
125
126 if (use_location) {
127 const char *filename;
128 int lineno;
129
130 PyC_FileAndNum(&filename, &lineno);
131 if (filename == NULL) {
132 filename = "<unknown location>";
133 }
134
135 BKE_reportf(reports,
136 RPT_ERROR,
137 TIP_("%s: %s\nlocation: %s:%d\n"),
138 error_prefix,
139 _PyUnicode_AsString(pystring),
140 filename,
141 lineno);
142
143 /* Not exactly needed. Useful for developers tracking down issues. */
144 fprintf(stderr,
145 TIP_("%s: %s\nlocation: %s:%d\n"),
146 error_prefix,
147 _PyUnicode_AsString(pystring),
148 filename,
149 lineno);
150 }
151 else {
152 BKE_reportf(reports, RPT_ERROR, "%s: %s", error_prefix, _PyUnicode_AsString(pystring));
153 }
154
155 Py_DECREF(pystring);
156 return 1;
157 }
158
BPy_errors_to_report(ReportList * reports)159 bool BPy_errors_to_report(ReportList *reports)
160 {
161 return BPy_errors_to_report_ex(reports, NULL, true, true);
162 }
163