Blender  V3.3
bpy_capi_utils.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
10 #include <Python.h>
11 
12 #include "BLI_dynstr.h"
13 #include "BLI_listbase.h"
14 #include "BLI_utildefines.h"
15 
16 #include "bpy_capi_utils.h"
17 
18 #include "MEM_guardedalloc.h"
19 
20 #include "BKE_context.h"
21 #include "BKE_report.h"
22 
23 #include "BLT_translation.h"
24 
25 #include "../generic/py_capi_utils.h"
26 
27 short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
28 {
29  char *report_str;
30 
31  report_str = BKE_reports_string(reports, RPT_ERROR);
32 
33  if (clear == true) {
34  BKE_reports_clear(reports);
35  }
36 
37  if (report_str) {
38  PyErr_SetString(exception, report_str);
39  MEM_freeN(report_str);
40  }
41 
42  return (report_str == NULL) ? 0 : -1;
43 }
44 
45 void BPy_reports_write_stdout(const ReportList *reports, const char *header)
46 {
47  if (header) {
48  PySys_WriteStdout("%s\n", header);
49  }
50 
51  LISTBASE_FOREACH (const Report *, report, &reports->list) {
52  PySys_WriteStdout("%s: %s\n", report->typestr, report->message);
53  }
54 }
55 
57  const char *err_prefix,
58  const bool use_full,
59  const bool use_location)
60 {
61 
62  if (!PyErr_Occurred()) {
63  return 1;
64  }
65 
66  PyObject *err_str_py = use_full ? PyC_ExceptionBuffer() : PyC_ExceptionBuffer_Simple();
67  if (err_str_py == NULL) {
68  BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert");
69  return 0;
70  }
71 
72  /* Strip trailing newlines so the report doesn't show a blank-line in the info space. */
73  Py_ssize_t err_str_len;
74  const char *err_str = PyUnicode_AsUTF8AndSize(err_str_py, &err_str_len);
75  while (err_str_len > 0 && err_str[err_str_len - 1] == '\n') {
76  err_str_len -= 1;
77  }
78 
79  if (err_prefix == NULL) {
80  /* Not very helpful, better than nothing. */
81  err_prefix = "Python";
82  }
83 
84  const char *location_filepath = NULL;
85  int location_line_number = -1;
86 
87  /* Give some additional context. */
88  if (use_location) {
89  PyC_FileAndNum(&location_filepath, &location_line_number);
90  }
91 
92  if (location_filepath) {
93  BKE_reportf(reports,
94  RPT_ERROR,
95  "%s: %.*s\n"
96  /* Location (when available). */
97  "Location: %s:%d",
98  err_prefix,
99  (int)err_str_len,
100  err_str,
101  location_filepath,
102  location_line_number);
103  }
104  else {
105  BKE_reportf(reports, RPT_ERROR, "%s: %.*s", err_prefix, (int)err_str_len, err_str);
106  }
107 
108  /* Ensure this is _always_ printed to the output so developers don't miss exceptions. */
109  Py_DECREF(err_str_py);
110  return 1;
111 }
112 
114 {
115  return BPy_errors_to_report_ex(reports, NULL, true, true);
116 }
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_reports_clear(ReportList *reports)
Definition: report.c:63
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
char * BKE_reports_string(ReportList *reports, eReportType level)
Definition: report.c:231
A dynamically sized string ADT.
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
Read Guarded memory(de)allocation.
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_ex(ReportList *reports, const char *err_prefix, const bool use_full, const bool use_location)
bool BPy_errors_to_report(ReportList *reports)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static void clear(Message *msg)
Definition: msgfmt.c:278
PyObject * PyC_ExceptionBuffer(void)
PyObject * PyC_ExceptionBuffer_Simple(void)
void PyC_FileAndNum(const char **r_filename, int *r_lineno)