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:
authorCampbell Barton <ideasman42@gmail.com>2009-01-02 10:54:38 +0300
committerCampbell Barton <ideasman42@gmail.com>2009-01-02 10:54:38 +0300
commit5d23eaa8f462cdace80b8afc2b766068b4630243 (patch)
treea24348957a690523f007be7c36035de628f2b743
parentcf43c6b0a1a125cf49207d382b6ae6157e0905b4 (diff)
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
-rw-r--r--source/blender/blenkernel/BKE_report.h1
-rw-r--r--source/blender/blenkernel/intern/report.c28
-rw-r--r--source/blender/editors/interface/interface_handlers.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c2
-rw-r--r--source/blender/editors/space_action/action_header.c4
-rw-r--r--source/blender/editors/space_node/node_header.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c10
-rw-r--r--source/blender/python/epy_doc_gen.py4
-rw-r--r--source/blender/python/intern/bpy_operator.c25
-rw-r--r--source/blender/python/intern/bpy_opwrapper.c22
-rw-r--r--source/blender/windowmanager/WM_api.h2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c27
12 files changed, 96 insertions, 37 deletions
diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h
index 8a5c623a225..21221026b8b 100644
--- a/source/blender/blenkernel/BKE_report.h
+++ b/source/blender/blenkernel/BKE_report.h
@@ -80,6 +80,7 @@ void BKE_report_print_level_set(ReportList *reports, ReportType level);
ReportType BKE_report_store_level(ReportList *reports);
void BKE_report_store_level_set(ReportList *reports, ReportType level);
+char *BKE_reports_string(ReportList *reports, ReportType level);
void BKE_reports_print(ReportList *reports, ReportType level);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/intern/report.c b/source/blender/blenkernel/intern/report.c
index 97bbaf66b3a..5ba21529c5c 100644
--- a/source/blender/blenkernel/intern/report.c
+++ b/source/blender/blenkernel/intern/report.c
@@ -215,17 +215,37 @@ void BKE_report_store_level_set(ReportList *reports, ReportType level)
reports->storelevel= level;
}
-void BKE_reports_print(ReportList *reports, ReportType level)
+char *BKE_reports_string(ReportList *reports, ReportType level)
{
Report *report;
+ DynStr *ds;
+ char *cstring;
if(!reports)
- return;
-
+ return NULL;
+
+ ds= BLI_dynstr_new();
for(report=reports->list.first; report; report=report->next)
if(report->type >= level)
- printf("%s: %s\n", report->typestr, report->message);
+ BLI_dynstr_appendf(ds, "%s: %s\n", report->typestr, report->message);
+
+ if (BLI_dynstr_get_len(ds))
+ cstring= BLI_dynstr_get_cstring(ds);
+ else
+ cstring= NULL;
+ BLI_dynstr_free(ds);
+ return cstring;
+}
+
+void BKE_reports_print(ReportList *reports, ReportType level)
+{
+ char *cstring = BKE_reports_string(reports, level);
+
+ if (cstring == NULL)
+ return;
+
+ printf(cstring);
fflush(stdout);
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 55e7e297b3f..432d722dd62 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -222,7 +222,7 @@ static void ui_apply_but_funcs_after(bContext *C)
after->butm_func(C, after->butm_func_arg, after->a2);
if(after->opname)
- WM_operator_name_call(C, after->opname, after->opcontext, after->opptr);
+ WM_operator_name_call(C, after->opname, after->opcontext, after->opptr, NULL);
if(after->opptr) {
WM_operator_properties_free(after->opptr);
MEM_freeN(after->opptr);
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 72a0fd811d0..d32cad92569 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -1690,7 +1690,7 @@ static void operator_cb(bContext *C, void *arg, int retval)
const char *opname= arg;
if(opname && retval > 0)
- WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL);
+ WM_operator_name_call(C, opname, WM_OP_EXEC_DEFAULT, NULL, NULL);
}
static void vconfirm(bContext *C, char *opname, char *title, char *itemfmt, va_list ap)
diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c
index 406c9bf2147..e0e9a4d7a18 100644
--- a/source/blender/editors/space_action/action_header.c
+++ b/source/blender/editors/space_action/action_header.c
@@ -463,10 +463,10 @@ static void do_action_buttons(bContext *C, void *arg, int event)
break;
case B_ACTCOPYKEYS:
- WM_operator_name_call(C, "ACT_OT_keyframes_copy", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "ACT_OT_keyframes_copy", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
case B_ACTPASTEKEYS:
- WM_operator_name_call(C, "ACT_OT_keyframes_paste", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "ACT_OT_keyframes_paste", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
}
}
diff --git a/source/blender/editors/space_node/node_header.c b/source/blender/editors/space_node/node_header.c
index 7f818532301..7191bb2214c 100644
--- a/source/blender/editors/space_node/node_header.c
+++ b/source/blender/editors/space_node/node_header.c
@@ -592,13 +592,13 @@ static void do_node_viewmenu(bContext *C, void *arg, int event)
switch(event) {
case 1: /* Zoom in */
- WM_operator_name_call(C, "View2D_OT_view_zoomin", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "View2D_OT_view_zoomin", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
case 2: /* View all */
- WM_operator_name_call(C, "View2D_OT_view_zoomout", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "View2D_OT_view_zoomout", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
case 3: /* View all */
- WM_operator_name_call(C, "NODE_OT_fit_all", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "NODE_OT_fit_all", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
case 4: /* Grease Pencil */
// XXX add_blockhandler(sa, NODES_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW);
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index 1bb452cffb6..06eb00d75c8 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -443,7 +443,7 @@ static void do_view3d_view_alignviewmenu(bContext *C, void *arg, int event)
// XXX mainqenter(PADASTERKEY, 1);
break;
case 6: /* Center View and Cursor to Origin */
- WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL, NULL);
curs= give_cursor(scene, v3d);
curs[0]=curs[1]=curs[2]= 0.0;
break;
@@ -528,10 +528,10 @@ static void do_view3d_viewmenu(bContext *C, void *arg, int event)
endlocalview(scene, sa);
break;
case 9: /* View All (Home) */
- WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
case 11: /* View Selected */
- WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_viewcenter", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
case 13: /* Play Back Animation */
play_anim(0);
@@ -543,7 +543,7 @@ static void do_view3d_viewmenu(bContext *C, void *arg, int event)
add_blockhandler(sa, VIEW3D_HANDLER_PROPERTIES, UI_PNL_UNSTOW);
break;
case 17: /* Set Clipping Border */
- WM_operator_name_call(C, "VIEW3D_OT_clipping", WM_OP_INVOKE_REGION_WIN, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_clipping", WM_OP_INVOKE_REGION_WIN, NULL, NULL);
break;
case 18: /* render preview */
toggle_blockhandler(sa, VIEW3D_HANDLER_PREVIEW, 0);
@@ -5317,7 +5317,7 @@ static void do_view3d_buttons(bContext *C, void *arg, int event)
switch(event) {
case B_HOME:
- WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL);
+ WM_operator_name_call(C, "VIEW3D_OT_viewhome", WM_OP_EXEC_REGION_WIN, NULL, NULL);
break;
case B_SCENELOCK:
if(v3d->scenelock) {
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
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 8ec6078e1d9..f5cf17d6857 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -123,7 +123,7 @@ void WM_operatortype_append_ptr (void (*opfunc)(wmOperatorType*, void *), void
int WM_operatortype_remove(const char *idname);
int WM_operator_call (struct bContext *C, struct wmOperator *op);
-int WM_operator_name_call (struct bContext *C, const char *opstring, int context, struct PointerRNA *properties);
+int WM_operator_name_call (struct bContext *C, const char *opstring, int context, struct PointerRNA *properties, struct ReportList *reports);
void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring);
void WM_operator_properties_free(struct PointerRNA *ptr);
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 6dffc0ff29e..f7bb9877124 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -355,7 +355,7 @@ int WM_operator_call(bContext *C, wmOperator *op)
return retval;
}
-static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties)
+static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerRNA *properties, ReportList *reports)
{
wmWindowManager *wm= CTX_wm_manager(C);
int retval= OPERATOR_PASS_THROUGH;
@@ -372,8 +372,13 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
op->ptr->data= IDP_CopyProperty(properties->data);
RNA_pointer_create(&RNA_WindowManager, &wm->id, ot->srna, op->ptr->data, op->ptr);
- op->reports= MEM_callocN(sizeof(ReportList), "wmOperatorReportList");
- BKE_reports_init(op->reports, RPT_STORE);
+ if (reports) {
+ op->reports= reports; /* must be initialized alredy */
+ }
+ else {
+ op->reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList");
+ BKE_reports_init(op->reports, RPT_STORE);
+ }
if(op->type->invoke && event)
retval= (*op->type->invoke)(C, op, event);
@@ -386,13 +391,15 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
WM_operator_print(op);
if(!(retval & OPERATOR_RUNNING_MODAL))
- if(op->reports->list.first)
+ if(reports==NULL && op->reports->list.first) /* only show the report if the report list was not given in the function */
uiPupmenuReports(C, op->reports);
if((retval & OPERATOR_FINISHED) && (ot->flag & OPTYPE_REGISTER)) {
wm_operator_register(wm, op);
}
else if(!(retval & OPERATOR_RUNNING_MODAL)) {
+ if (reports)
+ op->reports= NULL; /* dont let the operator free reports given by the user */
WM_operator_free(op);
}
}
@@ -401,7 +408,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
}
/* invokes operator in context */
-int WM_operator_name_call(bContext *C, const char *opstring, int context, PointerRNA *properties)
+int WM_operator_name_call(bContext *C, const char *opstring, int context, PointerRNA *properties, ReportList *reports)
{
wmOperatorType *ot= WM_operatortype_find(opstring);
wmWindow *window= CTX_wm_window(C);
@@ -431,7 +438,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe
CTX_wm_region_set(C, ar1);
}
- retval= wm_operator_invoke(C, ot, event, properties);
+ retval= wm_operator_invoke(C, ot, event, properties, reports);
/* set region back */
CTX_wm_region_set(C, ar);
@@ -446,7 +453,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe
ARegion *ar= CTX_wm_region(C);
CTX_wm_region_set(C, NULL);
- retval= wm_operator_invoke(C, ot, event, properties);
+ retval= wm_operator_invoke(C, ot, event, properties, reports);
CTX_wm_region_set(C, ar);
return retval;
@@ -461,7 +468,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe
CTX_wm_region_set(C, NULL);
CTX_wm_area_set(C, NULL);
- retval= wm_operator_invoke(C, ot, window->eventstate, properties);
+ retval= wm_operator_invoke(C, ot, window->eventstate, properties, reports);
CTX_wm_region_set(C, ar);
CTX_wm_area_set(C, area);
@@ -470,7 +477,7 @@ int WM_operator_name_call(bContext *C, const char *opstring, int context, Pointe
case WM_OP_EXEC_DEFAULT:
event= NULL; /* pass on without break */
case WM_OP_INVOKE_DEFAULT:
- return wm_operator_invoke(C, ot, event, properties);
+ return wm_operator_invoke(C, ot, event, properties, reports);
}
}
@@ -665,7 +672,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
wmOperatorType *ot= WM_operatortype_find(event->keymap_idname);
if(ot)
- retval= wm_operator_invoke(C, ot, event, properties);
+ retval= wm_operator_invoke(C, ot, event, properties, NULL);
}
if(retval & OPERATOR_PASS_THROUGH)