From 29aae4db38772cb5544a5e9998922facf951b89e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 18 May 2015 09:12:26 +1000 Subject: UI: errors in buttons now show in info report Mistakes in button expressions were previously only printed to the console. --- source/blender/editors/interface/interface.c | 1 + source/blender/python/generic/py_capi_utils.c | 28 ++++++++++++++ source/blender/python/generic/py_capi_utils.h | 1 + source/blender/python/intern/bpy_interface.c | 2 +- source/blender/python/intern/bpy_util.c | 43 +++++++++++++++------- source/blender/python/intern/bpy_util.h | 3 +- source/blender/windowmanager/WM_api.h | 1 + .../blender/windowmanager/intern/wm_event_system.c | 33 +++++++++++------ 8 files changed, 85 insertions(+), 27 deletions(-) (limited to 'source/blender') diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 6d1d51eae0e..1eadd259295 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2315,6 +2315,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str) double value; if (ui_but_string_set_eval_num(C, but, str, &value) == false) { + WM_report_banner_show(C); return false; } diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 92ac82508e5..6443c65a50a 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -478,6 +478,34 @@ error_cleanup: } #endif +PyObject *PyC_ExceptionBuffer_Simple(void) +{ + PyObject *string_io_buf; + + PyObject *error_type, *error_value, *error_traceback; + + if (!PyErr_Occurred()) + return NULL; + + PyErr_Fetch(&error_type, &error_value, &error_traceback); + + if (error_value == NULL) { + return NULL; + } + + string_io_buf = PyObject_Str(error_value); + /* Python does this too */ + if (UNLIKELY(string_io_buf == NULL)) { + string_io_buf = PyUnicode_FromFormat( + "", Py_TYPE(error_value)->tp_name); + } + + PyErr_Restore(error_type, error_value, error_traceback); + + PyErr_Print(); + PyErr_Clear(); + return string_io_buf; +} /* string conversion, escape non-unicode chars, coerce must be set to NULL */ const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce) diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 398d7da9179..ab630d1d203 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -32,6 +32,7 @@ void PyC_ObSpit(const char *name, PyObject *var); void PyC_LineSpit(void); void PyC_StackSpit(void); PyObject * PyC_ExceptionBuffer(void); +PyObject * PyC_ExceptionBuffer_Simple(void); PyObject * PyC_Object_GetAttrStringArgs(PyObject *o, Py_ssize_t n, ...); PyObject * PyC_FrozenSetFromStrings(const char **strings); PyObject * PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index ca61ba99f9f..4be63042c1e 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -595,7 +595,7 @@ int BPY_button_exec(bContext *C, const char *expr, double *value, const bool ver if (error_ret) { if (verbose) { - BPy_errors_to_report(CTX_wm_reports(C)); + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); } else { PyErr_Clear(); diff --git a/source/blender/python/intern/bpy_util.c b/source/blender/python/intern/bpy_util.c index 93183a4f320..6e26104ea2a 100644 --- a/source/blender/python/intern/bpy_util.c +++ b/source/blender/python/intern/bpy_util.c @@ -82,10 +82,9 @@ short BPy_reports_to_error(ReportList *reports, PyObject *exception, const bool } -short BPy_errors_to_report(ReportList *reports) +bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location) { PyObject *pystring; - PyObject *pystring_format = NULL; /* workaround, see below */ const char *cstring; const char *filename; @@ -101,31 +100,49 @@ short BPy_errors_to_report(ReportList *reports) return 1; } - pystring = PyC_ExceptionBuffer(); + if (use_full) { + pystring = PyC_ExceptionBuffer(); + } + else { + pystring = PyC_ExceptionBuffer_Simple(); + } if (pystring == NULL) { BKE_report(reports, RPT_ERROR, "Unknown py-exception, could not convert"); return 0; } - - PyC_FileAndNum(&filename, &lineno); - if (filename == NULL) - filename = ""; - + cstring = _PyUnicode_AsString(pystring); + if (use_location) { + PyObject *pystring_format; /* workaround, see below */ + + PyC_FileAndNum(&filename, &lineno); + if (filename == NULL) { + filename = ""; + } + #if 0 /* ARG!. workaround for a bug in blenders use of vsnprintf */ - BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", cstring, filename, lineno); + BKE_reportf(reports, RPT_ERROR, "%s\nlocation: %s:%d\n", cstring, filename, lineno); #else - pystring_format = PyUnicode_FromFormat(TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); - cstring = _PyUnicode_AsString(pystring_format); - BKE_report(reports, RPT_ERROR, cstring); + pystring_format = PyUnicode_FromFormat(TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); + cstring = _PyUnicode_AsString(pystring_format); + BKE_report(reports, RPT_ERROR, cstring); + Py_DECREF(pystring_format); /* workaround */ #endif + } + else { + BKE_report(reports, RPT_ERROR, cstring); + } /* not exactly needed. just for testing */ fprintf(stderr, TIP_("%s\nlocation: %s:%d\n"), cstring, filename, lineno); Py_DECREF(pystring); - Py_DECREF(pystring_format); /* workaround */ return 1; } + +bool BPy_errors_to_report(ReportList *reports) +{ + return BPy_errors_to_report_ex(reports, true, true); +} \ No newline at end of file diff --git a/source/blender/python/intern/bpy_util.h b/source/blender/python/intern/bpy_util.h index d19696aa230..1ae00a7fb02 100644 --- a/source/blender/python/intern/bpy_util.h +++ b/source/blender/python/intern/bpy_util.h @@ -40,7 +40,8 @@ char *BPy_enum_as_string(struct EnumPropertyItem *item); /* error reporting */ short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear); -short BPy_errors_to_report(struct ReportList *reports); +bool BPy_errors_to_report_ex(struct ReportList *reports, const bool use_full, const bool use_location); +bool BPy_errors_to_report(struct ReportList *reports); /* TODO - find a better solution! */ struct bContext *BPy_GetContext(void); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index d4148a56dd2..2131d5aae4a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -178,6 +178,7 @@ void WM_main_remove_notifier_reference(const void *reference); void WM_main_remove_editor_id_reference(const struct ID *id); /* reports */ +void WM_report_banner_show(const struct bContext *C); void WM_report(const struct bContext *C, ReportType type, const char *message); void WM_reportf(const struct bContext *C, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 658fb317688..85b94363616 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -587,26 +587,35 @@ void WM_event_print(const wmEvent *event) #endif /* NDEBUG */ +/** + * Show the report in the info header. + */ +void WM_report_banner_show(const bContext *C) +{ + wmWindowManager *wm = CTX_wm_manager(C); + ReportList *wm_reports = CTX_wm_reports(C); + ReportTimerInfo *rti; + + /* After adding reports to the global list, reset the report timer. */ + WM_event_remove_timer(wm, NULL, wm_reports->reporttimer); + + /* Records time since last report was added */ + wm_reports->reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMERREPORT, 0.05); + + rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); + wm_reports->reporttimer->customdata = rti; +} + static void wm_add_reports(const bContext *C, ReportList *reports) { /* if the caller owns them, handle this */ if (reports->list.first && (reports->flag & RPT_OP_HOLD) == 0) { - - wmWindowManager *wm = CTX_wm_manager(C); ReportList *wm_reports = CTX_wm_reports(C); - ReportTimerInfo *rti; /* add reports to the global list, otherwise they are not seen */ BLI_movelisttolist(&wm_reports->list, &reports->list); - - /* After adding reports to the global list, reset the report timer. */ - WM_event_remove_timer(wm, NULL, wm_reports->reporttimer); - - /* Records time since last report was added */ - wm_reports->reporttimer = WM_event_add_timer(wm, CTX_wm_window(C), TIMERREPORT, 0.05); - - rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); - wm_reports->reporttimer->customdata = rti; + + WM_report_banner_show(C); } } -- cgit v1.2.3