diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-07-27 06:46:58 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-07-27 14:00:50 +0300 |
commit | 565d7f75ccfe955821991793fcd6335e58b6825b (patch) | |
tree | f5526fc547c112a6694d187504ae1ac739e1933c | |
parent | 7beef1fd33b37f62d14a7de7150cfc7b0d88f159 (diff) |
UI: improve errors when evaluating a number button fails
Showing the Python error without any explanation is often
not enough information and doesn't hint that the error was in the
user input.
The error report from a invalid expression such as '..1' used to be:
('invalid syntax', ('<string>', 1, 1, '..1'))
Now reads:
Error evaluating number, see Info editor for details: invalid syntax
Address issue raised by T78913.
-rw-r--r-- | source/blender/editors/include/ED_numinput.h | 8 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 10 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_context_menu.c | 2 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_region_tooltip.c | 10 | ||||
-rw-r--r-- | source/blender/editors/util/numinput.c | 17 | ||||
-rw-r--r-- | source/blender/python/BPY_extern.h | 8 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_capi_utils.c | 25 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_capi_utils.h | 2 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 37 |
9 files changed, 80 insertions, 39 deletions
diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h index 8c8f3e6f4a3..16d05a7793a 100644 --- a/source/blender/editors/include/ED_numinput.h +++ b/source/blender/editors/include/ED_numinput.h @@ -103,8 +103,12 @@ bool handleNumInput(struct bContext *C, NumInput *n, const struct wmEvent *event #define NUM_MODAL_INCREMENT_UP 18 #define NUM_MODAL_INCREMENT_DOWN 19 -bool user_string_to_number( - bContext *C, const char *str, const struct UnitSettings *unit, int type, double *r_value); +bool user_string_to_number(bContext *C, + const char *str, + const struct UnitSettings *unit, + int type, + const char *error_prefix, + double *r_value); /** \} */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 8c4f337f2d9..9441e48ef24 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2800,10 +2800,16 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size) return str; } +/** + * Report a generic error prefix when evaluating a string with #BPY_execute_string_as_number + * as the Python error on it's own doesn't provide enough context. + */ +#define UI_NUMBER_EVAL_ERROR_PREFIX IFACE_("Error evaluating number, see Info editor for details") + static bool ui_number_from_string_units( bContext *C, const char *str, const int unit_type, const UnitSettings *unit, double *r_value) { - return user_string_to_number(C, str, unit, unit_type, r_value); + return user_string_to_number(C, str, unit, unit_type, UI_NUMBER_EVAL_ERROR_PREFIX, r_value); } static bool ui_number_from_string_units_with_but(bContext *C, @@ -2820,7 +2826,7 @@ static bool ui_number_from_string(bContext *C, const char *str, double *r_value) { bool ok; #ifdef WITH_PYTHON - ok = BPY_execute_string_as_number(C, NULL, str, true, r_value); + ok = BPY_execute_string_as_number(C, NULL, str, UI_NUMBER_EVAL_ERROR_PREFIX, r_value); #else UNUSED_VARS(C); *r_value = atof(str); diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index a08c5c45b6f..aaa5e1c0cf1 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -407,7 +407,7 @@ static void ui_but_user_menu_add(bContext *C, uiBut *but, bUserMenu *um) "'%s').label", idname); char *expr_result = NULL; - if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) { + if (BPY_execute_string_as_string(C, expr_imports, expr, __func__, &expr_result)) { STRNCPY(drawstr, expr_result); MEM_freeN(expr_result); } diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 46814e11b9e..7c64e4c2709 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -433,7 +433,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is if (has_valid_context == false) { expr_result = BLI_strdup(has_valid_context_error); } - else if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) { + else if (BPY_execute_string_as_string(C, expr_imports, expr, __func__, &expr_result)) { if (STREQ(expr_result, "")) { MEM_freeN(expr_result); expr_result = NULL; @@ -490,7 +490,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is if (has_valid_context == false) { expr_result = BLI_strdup(has_valid_context_error); } - else if (BPY_execute_string_as_string(C, expr_imports, expr, true, &expr_result)) { + else if (BPY_execute_string_as_string(C, expr_imports, expr, __func__, &expr_result)) { if (STREQ(expr_result, ".")) { MEM_freeN(expr_result); expr_result = NULL; @@ -594,7 +594,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is if (has_valid_context == false) { shortcut = BLI_strdup(has_valid_context_error); } - else if (BPY_execute_string_as_intptr(C, expr_imports, expr, true, &expr_result)) { + else if (BPY_execute_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) { if (expr_result != 0) { wmKeyMap *keymap = (wmKeyMap *)expr_result; LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { @@ -659,7 +659,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is /* pass */ } else if (BPY_execute_string_as_string_and_size( - C, expr_imports, expr, true, &expr_result, &expr_result_len)) { + C, expr_imports, expr, __func__, &expr_result, &expr_result_len)) { /* pass. */ } } @@ -736,7 +736,7 @@ static uiTooltipData *ui_tooltip_data_from_tool(bContext *C, uiBut *but, bool is if (has_valid_context == false) { /* pass */ } - else if (BPY_execute_string_as_intptr(C, expr_imports, expr, true, &expr_result)) { + else if (BPY_execute_string_as_intptr(C, expr_imports, expr, __func__, &expr_result)) { if (expr_result != 0) { { uiTooltipField *field = text_field_add(data, diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 3c747a29361..384da6fb931 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -26,6 +26,8 @@ #include "BLI_string_utf8.h" #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "BKE_context.h" #include "BKE_scene.h" #include "BKE_unit.h" @@ -277,8 +279,12 @@ static bool editstr_insert_at_cursor(NumInput *n, const char *buf, const int buf return true; } -bool user_string_to_number( - bContext *C, const char *str, const UnitSettings *unit, int type, double *r_value) +bool user_string_to_number(bContext *C, + const char *str, + const UnitSettings *unit, + int type, + const char *error_prefix, + double *r_value) { #ifdef WITH_PYTHON double unit_scale = BKE_scene_unit_scale(unit, type, 1.0); @@ -288,10 +294,10 @@ bool user_string_to_number( bUnit_ReplaceString( str_unit_convert, sizeof(str_unit_convert), str, unit_scale, unit->system, type); - return BPY_execute_string_as_number(C, NULL, str_unit_convert, true, r_value); + return BPY_execute_string_as_number(C, NULL, str_unit_convert, error_prefix, r_value); } - int success = BPY_execute_string_as_number(C, NULL, str, true, r_value); + int success = BPY_execute_string_as_number(C, NULL, str, error_prefix, r_value); *r_value *= bUnit_PreferredInputUnitScalar(unit, type); *r_value /= unit_scale; return success; @@ -573,7 +579,8 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) Scene *sce = CTX_data_scene(C); double val; - int success = user_string_to_number(C, n->str, &sce->unit, n->unit_type[idx], &val); + int success = user_string_to_number( + C, n->str, &sce->unit, n->unit_type[idx], IFACE_("Numeric input evaluation"), &val); if (success) { n->val[idx] = (float)val; diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 5c6e0b0a308..049b919b4a4 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -82,23 +82,23 @@ bool BPY_execute_text(struct bContext *C, bool BPY_execute_string_as_number(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, double *r_value); bool BPY_execute_string_as_intptr(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, intptr_t *r_value); bool BPY_execute_string_as_string_and_size(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, char **r_value, size_t *r_value_size); bool BPY_execute_string_as_string(struct bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, char **r_value); bool BPY_execute_string_ex(struct bContext *C, diff --git a/source/blender/python/intern/bpy_capi_utils.c b/source/blender/python/intern/bpy_capi_utils.c index 0befd6aad2f..27eea80f1f6 100644 --- a/source/blender/python/intern/bpy_capi_utils.c +++ b/source/blender/python/intern/bpy_capi_utils.c @@ -97,7 +97,10 @@ void BPy_reports_write_stdout(const ReportList *reports, const char *header) } } -bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const bool use_location) +bool BPy_errors_to_report_ex(ReportList *reports, + const char *error_prefix, + const bool use_full, + const bool use_location) { PyObject *pystring; @@ -124,6 +127,11 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo return 0; } + if (error_prefix == NULL) { + /* Not very helpful, better than nothing. */ + error_prefix = "Python"; + } + if (use_location) { const char *filename; int lineno; @@ -135,17 +143,22 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo BKE_reportf(reports, RPT_ERROR, - TIP_("%s\nlocation: %s:%d\n"), + TIP_("%s: %s\nlocation: %s:%d\n"), + error_prefix, _PyUnicode_AsString(pystring), filename, lineno); /* Not exactly needed. Useful for developers tracking down issues. */ - fprintf( - stderr, TIP_("%s\nlocation: %s:%d\n"), _PyUnicode_AsString(pystring), filename, lineno); + fprintf(stderr, + TIP_("%s: %s\nlocation: %s:%d\n"), + error_prefix, + _PyUnicode_AsString(pystring), + filename, + lineno); } else { - BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(pystring)); + BKE_reportf(reports, RPT_ERROR, "%s: %s", error_prefix, _PyUnicode_AsString(pystring)); } Py_DECREF(pystring); @@ -154,5 +167,5 @@ bool BPy_errors_to_report_ex(ReportList *reports, const bool use_full, const boo bool BPy_errors_to_report(ReportList *reports) { - return BPy_errors_to_report_ex(reports, true, true); + return BPy_errors_to_report_ex(reports, NULL, true, true); } diff --git a/source/blender/python/intern/bpy_capi_utils.h b/source/blender/python/intern/bpy_capi_utils.h index 97344ce1326..2d654336f8f 100644 --- a/source/blender/python/intern/bpy_capi_utils.h +++ b/source/blender/python/intern/bpy_capi_utils.h @@ -39,8 +39,10 @@ char *BPy_enum_as_string(const struct EnumPropertyItem *item); short BPy_reports_to_error(struct ReportList *reports, PyObject *exception, const bool clear); void BPy_reports_write_stdout(const struct ReportList *reports, const char *header); bool BPy_errors_to_report_ex(struct ReportList *reports, + const char *error_prefix, const bool use_full, const bool use_location); +bool BPy_errors_to_report_brief_with_prefix(struct ReportList *reports, const char *error_prefix); bool BPy_errors_to_report(struct ReportList *reports); /* TODO - find a better solution! */ diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index c40b2ded8ff..f91afa414ce 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -617,8 +617,11 @@ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr) /** * \return success */ -bool BPY_execute_string_as_number( - bContext *C, const char *imports[], const char *expr, const bool verbose, double *r_value) +bool BPY_execute_string_as_number(bContext *C, + const char *imports[], + const char *expr, + const char *report_prefix, + double *r_value) { PyGILState_STATE gilstate; bool ok = true; @@ -637,8 +640,8 @@ bool BPY_execute_string_as_number( ok = PyC_RunString_AsNumber(imports, expr, "<expr as number>", r_value); if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + if (report_prefix != NULL) { + BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false); } else { PyErr_Clear(); @@ -656,7 +659,7 @@ bool BPY_execute_string_as_number( bool BPY_execute_string_as_string_and_size(bContext *C, const char *imports[], const char *expr, - const bool verbose, + const char *report_prefix, char **r_value, size_t *r_value_size) { @@ -674,8 +677,8 @@ bool BPY_execute_string_as_string_and_size(bContext *C, ok = PyC_RunString_AsStringAndSize(imports, expr, "<expr as str>", r_value, r_value_size); if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + if (report_prefix != NULL) { + BPy_errors_to_report_ex(CTX_wm_reports(C), false, false, report_prefix); } else { PyErr_Clear(); @@ -687,12 +690,15 @@ bool BPY_execute_string_as_string_and_size(bContext *C, return ok; } -bool BPY_execute_string_as_string( - bContext *C, const char *imports[], const char *expr, const bool verbose, char **r_value) +bool BPY_execute_string_as_string(bContext *C, + const char *imports[], + const char *expr, + const char *report_prefix, + char **r_value) { size_t value_dummy_size; return BPY_execute_string_as_string_and_size( - C, imports, expr, verbose, r_value, &value_dummy_size); + C, imports, expr, report_prefix, r_value, &value_dummy_size); } /** @@ -700,8 +706,11 @@ bool BPY_execute_string_as_string( * * \return success */ -bool BPY_execute_string_as_intptr( - bContext *C, const char *imports[], const char *expr, const bool verbose, intptr_t *r_value) +bool BPY_execute_string_as_intptr(bContext *C, + const char *imports[], + const char *expr, + const char *report_prefix, + intptr_t *r_value) { BLI_assert(r_value && expr); PyGILState_STATE gilstate; @@ -717,8 +726,8 @@ bool BPY_execute_string_as_intptr( ok = PyC_RunString_AsIntPtr(imports, expr, "<expr as intptr>", r_value); if (ok == false) { - if (verbose) { - BPy_errors_to_report_ex(CTX_wm_reports(C), false, false); + if (report_prefix != NULL) { + BPy_errors_to_report_ex(CTX_wm_reports(C), report_prefix, false, false); } else { PyErr_Clear(); |