Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_report.h5
-rw-r--r--source/blender/blenkernel/intern/report.c14
-rw-r--r--source/blender/editors/space_text/text_ops.c4
-rw-r--r--source/blender/python/intern/bpy_capi_utils.c72
-rw-r--r--source/blender/python/intern/bpy_capi_utils.h13
-rw-r--r--source/blender/python/intern/bpy_interface_run.c26
-rw-r--r--source/blender/python/intern/bpy_traceback.c5
7 files changed, 86 insertions, 53 deletions
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index b67c4856e89..38b5c68c8ca 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -45,6 +45,11 @@ eReportType BKE_report_store_level(ReportList *reports);
void BKE_report_store_level_set(ReportList *reports, eReportType level);
char *BKE_reports_string(ReportList *reports, eReportType level);
+
+/**
+ * \return true when reports of this type will print to the `stdout`.
+ */
+bool BKE_reports_print_test(const ReportList *reports, eReportType type);
void BKE_reports_print(ReportList *reports, eReportType level);
Report *BKE_reports_last_displayable(ReportList *reports);
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 98b680c8054..6d654730bca 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -86,9 +86,7 @@ void BKE_report(ReportList *reports, eReportType type, const char *_message)
int len;
const char *message = TIP_(_message);
- /* in background mode always print otherwise there are cases the errors won't be displayed,
- * but still add to the report list since this is used for python exception handling */
- if (G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
+ if (BKE_reports_print_test(reports, type)) {
printf("%s: %s\n", BKE_report_type_str(type), message);
fflush(stdout); /* this ensures the message is printed before a crash */
}
@@ -115,7 +113,7 @@ void BKE_reportf(ReportList *reports, eReportType type, const char *_format, ...
va_list args;
const char *format = TIP_(_format);
- if (G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
+ if (BKE_reports_print_test(reports, type)) {
printf("%s: ", BKE_report_type_str(type));
va_start(args, _format);
vprintf(format, args);
@@ -258,6 +256,14 @@ char *BKE_reports_string(ReportList *reports, eReportType level)
return cstring;
}
+bool BKE_reports_print_test(const ReportList *reports, eReportType type)
+{
+ /* In background mode always print otherwise there are cases the errors won't be displayed,
+ * but still add to the report list since this is used for python exception handling. */
+ return (G.background || (reports == NULL) ||
+ ((reports->flag & RPT_PRINT) && (type >= reports->printlevel)));
+}
+
void BKE_reports_print(ReportList *reports, eReportType level)
{
char *cstring = BKE_reports_string(reports, level);
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 49c0236866d..d4aac8dd57f 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -788,9 +788,7 @@ static int text_run_script(bContext *C, ReportList *reports)
}
}
- BKE_report(
- reports, RPT_ERROR, "Python script failed, check the message in the system console");
-
+ /* No need to report the error, this has already been handled by #BPY_run_text. */
return OPERATOR_FINISHED;
}
#else
diff --git a/source/blender/python/intern/bpy_capi_utils.c b/source/blender/python/intern/bpy_capi_utils.c
index 742c04de3d7..f7f8253edac 100644
--- a/source/blender/python/intern/bpy_capi_utils.c
+++ b/source/blender/python/intern/bpy_capi_utils.c
@@ -54,70 +54,60 @@ void BPy_reports_write_stdout(const ReportList *reports, const char *header)
}
bool BPy_errors_to_report_ex(ReportList *reports,
- const char *error_prefix,
+ const char *err_prefix,
const bool use_full,
const bool use_location)
{
- PyObject *pystring;
if (!PyErr_Occurred()) {
return 1;
}
- /* less hassle if we allow NULL */
- if (reports == NULL) {
- PyErr_Print();
- PyErr_Clear();
- return 1;
- }
-
- if (use_full) {
- pystring = PyC_ExceptionBuffer();
- }
- else {
- pystring = PyC_ExceptionBuffer_Simple();
- }
-
- if (pystring == NULL) {
+ PyObject *err_str_py = use_full ? PyC_ExceptionBuffer() : PyC_ExceptionBuffer_Simple();
+ if (err_str_py == NULL) {
BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert");
return 0;
}
- if (error_prefix == NULL) {
+ /* Trim trailing newlines so the report doesn't contain a trailing new-line.
+ * This would add a blank-line in the info space. */
+ Py_ssize_t err_str_len;
+ const char *err_str = PyUnicode_AsUTF8AndSize(err_str_py, &err_str_len);
+ while (err_str_len > 0 && err_str[err_str_len - 1] == '\n') {
+ err_str_len -= 1;
+ }
+
+ if (err_prefix == NULL) {
/* Not very helpful, better than nothing. */
- error_prefix = "Python";
+ err_prefix = "Python";
}
- if (use_location) {
- const char *filename;
- int lineno;
+ const char *location_filepath = NULL;
+ int location_line_number = -1;
- PyC_FileAndNum(&filename, &lineno);
- if (filename == NULL) {
- filename = "<unknown location>";
- }
+ /* Give some additional context. */
+ if (use_location) {
+ PyC_FileAndNum(&location_filepath, &location_line_number);
+ }
+ if (location_filepath) {
BKE_reportf(reports,
RPT_ERROR,
- TIP_("%s: %s\nlocation: %s:%d\n"),
- error_prefix,
- PyUnicode_AsUTF8(pystring),
- filename,
- lineno);
-
- /* Not exactly needed. Useful for developers tracking down issues. */
- fprintf(stderr,
- TIP_("%s: %s\nlocation: %s:%d\n"),
- error_prefix,
- PyUnicode_AsUTF8(pystring),
- filename,
- lineno);
+ "%s: %.*s\n"
+ /* Location (when available). */
+ "Location: %s:%d",
+ err_prefix,
+ (int)err_str_len,
+ err_str,
+ location_filepath,
+ location_line_number);
}
else {
- BKE_reportf(reports, RPT_ERROR, "%s: %s", error_prefix, PyUnicode_AsUTF8(pystring));
+ BKE_reportf(reports, RPT_ERROR, "%s: %.*s", err_prefix, (int)err_str_len, err_str);
}
- Py_DECREF(pystring);
+ /* Ensure this is _always_ printed to the output so developers don't miss exceptions. */
+ Py_DECREF(err_str_py);
return 1;
}
diff --git a/source/blender/python/intern/bpy_capi_utils.h b/source/blender/python/intern/bpy_capi_utils.h
index 223c6ad5f7e..ab5ce7818f3 100644
--- a/source/blender/python/intern/bpy_capi_utils.h
+++ b/source/blender/python/intern/bpy_capi_utils.h
@@ -27,7 +27,18 @@ bool BPy_errors_to_report_ex(struct ReportList *reports,
const char *error_prefix,
bool use_full,
bool use_location);
-bool BPy_errors_to_report_brief_with_prefix(struct ReportList *reports, const char *error_prefix);
+/**
+ * \param reports: When set, an error will be added to this report, when NULL, print the error.
+ *
+ * \note Unless the caller handles printing the reports (or reports is NULL) it's best to ensure
+ * the output is printed to the `stdout/stderr`:
+ * \code{.cc}
+ * BPy_errors_to_report(reports);
+ * if (!BKE_reports_print_test(reports)) {
+ * BKE_reports_print(reports);
+ * }
+ * \endcode
+ */
bool BPy_errors_to_report(struct ReportList *reports);
struct bContext *BPY_context_get(void);
diff --git a/source/blender/python/intern/bpy_interface_run.c b/source/blender/python/intern/bpy_interface_run.c
index 147c6cf8187..50a2722c276 100644
--- a/source/blender/python/intern/bpy_interface_run.c
+++ b/source/blender/python/intern/bpy_interface_run.c
@@ -271,7 +271,23 @@ static bool bpy_run_string_impl(bContext *C,
if (retval == NULL) {
ok = false;
- BPy_errors_to_report(CTX_wm_reports(C));
+
+ ReportList reports;
+ BKE_reports_init(&reports, RPT_STORE);
+ BPy_errors_to_report(&reports);
+
+ /* Ensure the reports are printed. */
+ if (!BKE_reports_print_test(&reports, RPT_ERROR)) {
+ BKE_reports_print(&reports, RPT_ERROR);
+ }
+
+ ReportList *wm_reports = CTX_wm_reports(C);
+ if (wm_reports) {
+ BLI_movelisttolist(&wm_reports->list, &reports.list);
+ }
+ else {
+ BKE_reports_clear(&reports);
+ }
}
else {
Py_DECREF(retval);
@@ -330,6 +346,14 @@ static void run_string_handle_error(struct BPy_RunErrInfo *err_info)
}
}
+ /* Print the reports if they were not printed already. */
+ if ((err_info->reports == NULL) || !BKE_reports_print_test(err_info->reports, RPT_ERROR)) {
+ if (err_info->report_prefix) {
+ fprintf(stderr, "%s: ", err_info->report_prefix);
+ }
+ fprintf(stderr, "%s\n", err_str);
+ }
+
if (err_info->r_string != NULL) {
*err_info->r_string = BLI_strdup(err_str);
}
diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c
index 40478f3613c..1c545774203 100644
--- a/source/blender/python/intern/bpy_traceback.c
+++ b/source/blender/python/intern/bpy_traceback.c
@@ -205,12 +205,9 @@ bool python_script_error_jump(
}
}
}
- PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */
}
else {
PyErr_NormalizeException(&exception, &value, (PyObject **)&tb);
- PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */
- PyErr_Print();
for (tb = (PyTracebackObject *)PySys_GetObject("last_traceback");
tb && (PyObject *)tb != Py_None;
@@ -230,5 +227,7 @@ bool python_script_error_jump(
}
}
+ PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */
+
return success;
}