Blender  V2.93
bpy_capi_utils.c
Go to the documentation of this file.
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 
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 
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 
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 
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 
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_AsUTF8(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_AsUTF8(pystring),
148  filename,
149  lineno);
150  }
151  else {
152  BKE_reportf(reports, RPT_ERROR, "%s: %s", error_prefix, PyUnicode_AsUTF8(pystring));
153  }
154 
155  Py_DECREF(pystring);
156  return 1;
157 }
158 
160 {
161  return BPy_errors_to_report_ex(reports, NULL, true, true);
162 }
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
char * BKE_reports_string(ReportList *reports, ReportType level)
Definition: report.c:254
void BKE_reports_clear(ReportList *reports)
Definition: report.c:84
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:358
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
char * BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:323
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define TIP_(msgid)
Read Guarded memory(de)allocation.
char * BPy_enum_as_string(const EnumPropertyItem *item)
bool BPy_errors_to_report_ex(ReportList *reports, const char *error_prefix, const bool use_full, const bool use_location)
void BPy_reports_write_stdout(const ReportList *reports, const char *header)
short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
bool BPy_errors_to_report(ReportList *reports)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static void clear(Message *msg)
Definition: msgfmt.c:294
PyObject * PyC_ExceptionBuffer(void)
PyObject * PyC_ExceptionBuffer_Simple(void)
void PyC_FileAndNum(const char **r_filename, int *r_lineno)
const char * identifier
Definition: RNA_types.h:446