Blender V5.0
bpy_capi_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include <Python.h>
13
14#include "bpy_capi_utils.hh"
15
16#include "MEM_guardedalloc.h"
17
18#include "BKE_report.hh"
19
21
22short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool clear)
23{
24 char *report_str;
25
26 report_str = BKE_reports_string(reports, RPT_ERROR);
27
28 if (clear == true) {
29 BKE_reports_free(reports);
30 }
31
32 if (report_str) {
33 PyErr_SetString(exception, report_str);
34 MEM_freeN(report_str);
35 }
36
37 return (report_str == nullptr) ? 0 : -1;
38}
39
40void BPy_reports_write_stdout(const ReportList *reports, const char *header)
41{
42 const Report *report;
43 for (report = static_cast<const Report *>(reports->list.first); report; report = report->next) {
44 if (report->type < reports->printlevel) {
45 continue;
46 }
47 break;
48 }
49 if (report == nullptr) {
50 return;
51 }
52
53 if (header) {
54 PySys_WriteStdout("%s\n", header);
55 }
56
57 for (; report; report = report->next) {
58 if (report->type < reports->printlevel) {
59 continue;
60 }
61 PySys_WriteStdout("%s: %s\n", report->typestr, report->message);
62 }
63}
64
66 const char *error_prefix,
67 const bool use_full,
68 const bool use_location)
69{
70
71 if (!PyErr_Occurred()) {
72 return true;
73 }
74
75 PyObject *err_str_py = use_full ? PyC_ExceptionBuffer() : PyC_ExceptionBuffer_Simple();
76
77 /* Strip trailing newlines so the report doesn't show a blank-line in the info space. */
78 Py_ssize_t err_str_len;
79 const char *err_str = PyUnicode_AsUTF8AndSize(err_str_py, &err_str_len);
80 while (err_str_len > 0 && err_str[err_str_len - 1] == '\n') {
81 err_str_len -= 1;
82 }
83
84 if (error_prefix == nullptr) {
85 /* Not very helpful, better than nothing. */
86 error_prefix = "Python";
87 }
88
89 const char *location_filepath = nullptr;
90 int location_line_number = -1;
91
92 /* Give some additional context. */
93 if (use_location) {
94 PyC_FileAndNum(&location_filepath, &location_line_number);
95 }
96
97 /* Create a temporary report list so none of the reports are printed (only stored).
98 * In practically all cases printing should be handled by #PyErr_Print since this invokes
99 * `sys.excepthook` as expected. */
100 ReportList _reports_buf = {{nullptr}};
101 ReportList *reports_orig = reports;
102 if ((reports->flag & RPT_PRINT_HANDLED_BY_OWNER) == 0) {
103 reports = &_reports_buf;
104 BKE_reports_init(reports, reports_orig->flag | RPT_PRINT_HANDLED_BY_OWNER);
105 reports->storelevel = reports_orig->storelevel;
106 }
107
108 if (location_filepath) {
109 BKE_reportf(reports,
110 RPT_ERROR,
111 "%s: %.*s\n"
112 /* Location (when available). */
113 "Location: %s:%d",
114 error_prefix,
115 int(err_str_len),
116 err_str,
117 location_filepath,
118 location_line_number);
119 }
120 else {
121 BKE_reportf(reports, RPT_ERROR, "%s: %.*s", error_prefix, int(err_str_len), err_str);
122 }
123
124 if (reports != reports_orig) {
125 BKE_reports_move_to_reports(reports_orig, reports);
126 BKE_reports_free(reports);
127 }
128
129 /* Ensure this is _always_ printed to the output so developers don't miss exceptions. */
130 Py_DECREF(err_str_py);
131 return true;
132}
133
135{
136 return BPy_errors_to_report_ex(reports, nullptr, true, true);
137}
@ RPT_PRINT_HANDLED_BY_OWNER
Definition BKE_report.hh:60
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
@ RPT_ERROR
Definition BKE_report.hh:39
char * BKE_reports_string(ReportList *reports, eReportType level)
Definition report.cc:296
void BKE_reports_free(ReportList *reports)
Definition report.cc:97
void BKE_reports_init(ReportList *reports, int flag)
Definition report.cc:82
void BKE_reports_move_to_reports(ReportList *reports_dst, ReportList *reports_src)
Definition report.cc:141
Read Guarded memory(de)allocation.
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.cc:113
static void clear(Message &msg)
Definition msgfmt.cc:213
PyObject * PyC_ExceptionBuffer()
PyObject * PyC_ExceptionBuffer_Simple()
void PyC_FileAndNum(const char **r_filename, int *r_lineno)
Py_DECREF(oname)
void * first
ListBase list
Definition BKE_report.hh:75
short type
Definition BKE_report.hh:66
const char * typestr
Definition BKE_report.hh:70
const char * message
Definition BKE_report.hh:71
Report * next
Definition BKE_report.hh:64