From 5d23eaa8f462cdace80b8afc2b766068b4630243 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 2 Jan 2009 07:54:38 +0000 Subject: python support for reporting with operators. * errors in python called operators are raised as errors * Python defined operators errors are reported as errors (not full traceback yet) * added BKE_reports_string, same as BKE_reports_print but it returns a string rather then printing it. * WM_operator_name_call optionally takes an initialized report struct --- source/blender/python/epy_doc_gen.py | 4 ++-- source/blender/python/intern/bpy_operator.c | 25 +++++++++++++++++++++---- source/blender/python/intern/bpy_opwrapper.c | 22 ++++++++++++++++++---- 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'source/blender/python') diff --git a/source/blender/python/epy_doc_gen.py b/source/blender/python/epy_doc_gen.py index 77b0c245dbd..9e0c6127a4c 100644 --- a/source/blender/python/epy_doc_gen.py +++ b/source/blender/python/epy_doc_gen.py @@ -86,8 +86,8 @@ def rna2epy(target_path): array_str = get_array_str(length) - if rna_prop.readonly: readonly_str = ' (readonly)' - else: readonly_str = '' + if rna_prop.editable: readonly_str = '' + else: readonly_str = ' (readonly)' if rna_prop_ptr: # Use the pointer type out.write('\t@ivar %s: %s\n' % (rna_prop_identifier, rna_desc)) diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index cc87fd0704e..061c43c4773 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -35,7 +35,8 @@ #include "WM_types.h" #include "MEM_guardedalloc.h" -#include "BKE_idprop.h" +//#include "BKE_idprop.h" +#include "BKE_report.h" extern ListBase global_ops; /* evil, temp use */ @@ -168,7 +169,7 @@ PyObject *pyop_func_get_rna(BPy_OperatorFunc *self) } static PyGetSetDef pyop_func_getseters[] = { - {"rna", (getter)pyop_func_get_rna, (setter)NULL, "vertex's coordinate", NULL}, + {"rna", (getter)pyop_func_get_rna, (setter)NULL, "Operator RNA properties", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -178,7 +179,8 @@ static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObje int error_val = 0; PointerRNA ptr; - + char *report_str= NULL; + if (PyTuple_Size(args)) { PyErr_SetString( PyExc_AttributeError, "All operator args must be keywords"); return NULL; @@ -195,7 +197,22 @@ static PyObject * pyop_func_call(BPy_OperatorFunc * self, PyObject *args, PyObje error_val= PYOP_props_from_dict(&ptr, kw); if (error_val==0) { - WM_operator_name_call(self->C, self->name, WM_OP_EXEC_DEFAULT, &ptr); + ReportList reports; + + BKE_reports_init(&reports, RPT_STORE); + + WM_operator_name_call(self->C, self->name, WM_OP_EXEC_DEFAULT, &ptr, &reports); + + report_str= BKE_reports_string(&reports, RPT_ERROR); + + if (report_str) { + PyErr_SetString(PyExc_SystemError, report_str); + MEM_freeN(report_str); + error_val = -1; + } + + if (reports.list.first) + BKE_reports_clear(&reports); } WM_operator_properties_free(&ptr); diff --git a/source/blender/python/intern/bpy_opwrapper.c b/source/blender/python/intern/bpy_opwrapper.c index 000bec3b675..8a644f51b24 100644 --- a/source/blender/python/intern/bpy_opwrapper.c +++ b/source/blender/python/intern/bpy_opwrapper.c @@ -27,6 +27,7 @@ #include "bpy_opwrapper.h" #include "BLI_listbase.h" #include "BKE_context.h" +#include "BKE_report.h" #include "DNA_windowmanager_types.h" #include "MEM_guardedalloc.h" #include "WM_api.h" @@ -168,6 +169,19 @@ static PyObject *pyop_dict_from_event(wmEvent *event) return dict; } +/* TODO - a whole traceback would be ideal */ +static void pyop_error_report(ReportList *reports) +{ + PyObject *exception, *v, *tb; + PyErr_Fetch(&exception, &v, &tb); + if (exception == NULL) + return; + /* Now we know v != NULL too */ + BKE_report(reports, RPT_ERROR, _PyUnicode_AsString(v)); + + PyErr_Print(); +} + static struct BPY_flag_def pyop_ret_flags[] = { {"RUNNING_MODAL", OPERATOR_RUNNING_MODAL}, {"CANCELLED", OPERATOR_CANCELLED}, @@ -188,12 +202,12 @@ static int PYTHON_OT_exec(bContext *C, wmOperator *op) ret = PyObject_Call(pyot->py_exec, args, kw); if (ret == NULL) { - PyErr_Print(); + pyop_error_report(op->reports); } else { if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) { /* the returned value could not be converted into a flag */ - PyErr_Print(); + pyop_error_report(op->reports); } } @@ -232,12 +246,12 @@ static int PYTHON_OT_invoke(bContext *C, wmOperator *op, wmEvent *event) ret = PyObject_Call(pyot->py_invoke, args, NULL); if (ret == NULL) { - PyErr_Print(); + pyop_error_report(op->reports); } else { if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == -1) { /* the returned value could not be converted into a flag */ - PyErr_Print(); + pyop_error_report(op->reports); } /* there is no need to copy the py keyword dict modified by * pyot->py_invoke(), back to the operator props since they are just -- cgit v1.2.3