Revision: 20873
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20873
Author:   campbellbarton
Date:     2009-06-14 14:53:47 +0200 (Sun, 14 Jun 2009)

Log Message:
-----------
Blender/Python API
Send the full python stack trace to the reporting api,
added BPY_exception_buffer which temporarily overrides sys.stdout and 
sys.stderr to get the output (uses the io module in py3 StringIO in py2 to 
avoid writing into a real file), pity the Py/C api has no function to do this.

fix for crash when showing menu's that have no items.

Modified Paths:
--------------
    
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
    
branches/blender2.5/blender/source/blender/editors/space_script/script_edit.c
    branches/blender2.5/blender/source/blender/editors/space_text/text_ops.c
    branches/blender2.5/blender/source/blender/python/BPY_extern.h
    branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_util.c
    branches/blender2.5/blender/source/blender/python/intern/bpy_util.h
    branches/blender2.5/blender/source/creator/creator.c

Modified: 
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
===================================================================
--- 
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
    2009-06-14 10:59:54 UTC (rev 20872)
+++ 
branches/blender2.5/blender/source/blender/editors/interface/interface_regions.c
    2009-06-14 12:53:47 UTC (rev 20873)
@@ -1948,6 +1948,9 @@
        md= decompose_menu_string(info->instr);
 
        rows= md->nitems;
+       if(rows<1)
+               rows= 1;
+       
        columns= 1;
 
        /* size and location, title slightly bigger for bold */

Modified: 
branches/blender2.5/blender/source/blender/editors/space_script/script_edit.c
===================================================================
--- 
branches/blender2.5/blender/source/blender/editors/space_script/script_edit.c   
    2009-06-14 10:59:54 UTC (rev 20872)
+++ 
branches/blender2.5/blender/source/blender/editors/space_script/script_edit.c   
    2009-06-14 12:53:47 UTC (rev 20873)
@@ -62,15 +62,17 @@
 static int run_pyfile_exec(bContext *C, wmOperator *op)
 {
        ARegion *ar= CTX_wm_region(C);
+       
 
        char filename[512];
        RNA_string_get(op->ptr, "filename", filename);
 #ifndef DISABLE_PYTHON
-       BPY_run_python_script(C, filename, NULL);
+       if(BPY_run_python_script(C, filename, NULL, op->reports)) {
+               ED_region_tag_redraw(ar);
+               return OPERATOR_FINISHED;
+       }
 #endif
-       ED_region_tag_redraw(ar);
-
-       return OPERATOR_FINISHED;
+       return OPERATOR_CANCELLED; /* FAIL */
 }
 
 void SCRIPT_OT_python_file_run(wmOperatorType *ot)

Modified: 
branches/blender2.5/blender/source/blender/editors/space_text/text_ops.c
===================================================================
--- branches/blender2.5/blender/source/blender/editors/space_text/text_ops.c    
2009-06-14 10:59:54 UTC (rev 20872)
+++ branches/blender2.5/blender/source/blender/editors/space_text/text_ops.c    
2009-06-14 12:53:47 UTC (rev 20873)
@@ -521,7 +521,7 @@
 #else
        Text *text= CTX_data_edit_text(C);
 
-       if (BPY_run_python_script( C, NULL, text ))
+       if (BPY_run_python_script(C, NULL, text, op->reports))
                return OPERATOR_FINISHED;
        
        /* Dont report error messages while live editing */

Modified: branches/blender2.5/blender/source/blender/python/BPY_extern.h
===================================================================
--- branches/blender2.5/blender/source/blender/python/BPY_extern.h      
2009-06-14 10:59:54 UTC (rev 20872)
+++ branches/blender2.5/blender/source/blender/python/BPY_extern.h      
2009-06-14 12:53:47 UTC (rev 20873)
@@ -97,7 +97,7 @@
        int BPY_menu_invoke( struct BPyMenu *pym, short menutype );
        
        /* 2.5 UI Scripts */
-       int BPY_run_python_script( struct bContext *C, const char *filename, 
struct Text *text ); // 2.5 working
+       int BPY_run_python_script( struct bContext *C, const char *filename, 
struct Text *text, struct ReportList *reports ); // 2.5 working
        int BPY_run_script_space_draw(struct bContext *C, struct SpaceScript * 
sc); // 2.5 working
        void BPY_run_ui_scripts(struct bContext *C, int reload);
 //     int BPY_run_script_space_listener(struct bContext *C, struct 
SpaceScript * sc, struct ARegion *ar, struct wmNotifier *wmn); // 2.5 working

Modified: 
branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c    
2009-06-14 10:59:54 UTC (rev 20872)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_interface.c    
2009-06-14 12:53:47 UTC (rev 20873)
@@ -150,7 +150,7 @@
 }
 
 /* Can run a file or text block */
-int BPY_run_python_script( bContext *C, const char *fn, struct Text *text )
+int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, 
struct ReportList *reports)
 {
        PyObject *py_dict, *py_result;
        PyGILState_STATE gilstate;
@@ -178,7 +178,7 @@
                        MEM_freeN( buf );
 
                        if( PyErr_Occurred(  ) ) {
-                               PyErr_Print(); PyErr_Clear();
+                               BPy_errors_to_report(reports);
                                BPY_free_compiled_text( text );
                                PyGILState_Release(gilstate);
                                return 0;
@@ -194,7 +194,7 @@
        }
        
        if (!py_result) {
-               PyErr_Print(); PyErr_Clear();
+               BPy_errors_to_report(reports);
        } else {
                Py_DECREF( py_result );
        }
@@ -221,7 +221,7 @@
        script = sc->script;
 
        if( err ) {
-               PyErr_Print(); PyErr_Clear();
+               BPy_errors_to_report(NULL); // TODO, reports
                script->flags = 0;      /* mark script struct for deletion */
                SCRIPT_SET_NULL(script);
                script->scriptname[0] = '\0';
@@ -250,7 +250,7 @@
                return 0;
        
        if (sc->script->py_draw==NULL && sc->script->scriptname[0] != '\0')
-               BPY_run_python_script(C, sc->script->scriptname, NULL);
+               BPY_run_python_script(C, sc->script->scriptname, NULL, NULL);
                
        if (sc->script->py_draw==NULL)
                return 0;
@@ -329,7 +329,7 @@
        }
        
        if (!py_result) {
-               PyErr_Print(); PyErr_Clear();
+               BPy_errors_to_report(NULL); // TODO - reports
        } else
                Py_DECREF( py_result );
        
@@ -410,7 +410,7 @@
                        if(mod) {
                                Py_DECREF(mod); /* could be NULL from reloading 
*/
                        } else {
-                               PyErr_Print(); PyErr_Clear();
+                               BPy_errors_to_report(NULL); // TODO - reports
                                fprintf(stderr, "unable to import \"%s\"  
%s/%s\n", path, dirname, de->d_name);
                        }
                }
@@ -530,7 +530,7 @@
        driver->flag |= DRIVER_FLAG_INVALID; /* py expression failed */
        fprintf(stderr, "\nError in Driver: The following Python expression 
failed:\n\t'%s'\n\n", driver->expression);
        
-       PyErr_Print(); PyErr_Clear();
+       BPy_errors_to_report(NULL); // TODO - reports
 
        return 0.0f;
 }
@@ -589,7 +589,7 @@
                        }
                        
                        fprintf(stderr, "\tBPY_pydriver_eval() - couldn't add 
variable '%s' to namespace \n", dtar->name);
-                       PyErr_Print(); PyErr_Clear();
+                       BPy_errors_to_report(NULL); // TODO - reports
                }
        }
        

Modified: 
branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.c
===================================================================
--- 
branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.c    
    2009-06-14 10:59:54 UTC (rev 20872)
+++ 
branches/blender2.5/blender/source/blender/python/intern/bpy_operator_wrap.c    
    2009-06-14 12:53:47 UTC (rev 20873)
@@ -137,54 +137,6 @@
        return dict;
 }
 
-/* TODO - a whole traceback would be ideal */
-static void pyop_error_report(ReportList *reports)
-{
-       const char *string;
-       PyObject *exception, *v, *tb;
-       PyErr_Fetch(&exception, &v, &tb);
-       if (exception == NULL)
-               return;
-       
-       /* get the string from the exception */
-       if(v==NULL) {
-               string= "py exception not set";
-       }
-       else if(string = _PyUnicode_AsString(v)) {
-               /* do nothing */
-       }
-       else { /* a valid PyObject but not a string, try get its string value */
-               PyObject *repr;
-               
-               Py_INCREF(v); /* incase clearing the error below somehow frees 
this */
-               PyErr_Clear();
-               
-               repr= PyObject_Repr(v);
-               
-               if(repr==NULL) {
-                       PyErr_Clear();
-                       string= "py exception found but can't be converted";
-               }
-               else {
-                       string = _PyUnicode_AsString(repr);
-                       Py_DECREF(repr);
-                       
-                       if(string==NULL) { /* unlikely to happen */
-                               PyErr_Clear();
-                               string= "py exception found but can't be 
converted";
-                       }
-               }
-               
-               Py_DECREF(v); /* finished dealing with v, PyErr_Clear isnt 
called anymore so can decref it */
-       }
-       /* done getting the string */
-       
-       /* Now we know v != NULL too */
-       BKE_report(reports, RPT_ERROR, string);
-       
-       PyErr_Print();
-}
-
 static struct BPY_flag_def pyop_ret_flags[] = {
        {"RUNNING_MODAL", OPERATOR_RUNNING_MODAL},
        {"CANCELLED", OPERATOR_CANCELLED},
@@ -291,13 +243,13 @@
        }
        
        if (ret == NULL) { /* covers py_class_instance failing too */
-               pyop_error_report(op->reports);
+               BPy_errors_to_report(op->reports);
        }
        else {
                if (mode==PYOP_POLL) {
                        if (PyBool_Check(ret) == 0) {
                                PyErr_SetString(PyExc_ValueError, "Python poll 
function return value ");
-                               pyop_error_report(op->reports);
+                               BPy_errors_to_report(op->reports);
                        }
                        else {
                                ret_flag= ret==Py_True ? 1:0;
@@ -305,7 +257,7 @@
                        
                } else if (BPY_flag_from_seq(pyop_ret_flags, ret, &ret_flag) == 
-1) {
                         /* the returned value could not be converted into a 
flag */
-                       pyop_error_report(op->reports);
+                       BPy_errors_to_report(op->reports);
                        
                }
                /* there is no need to copy the py keyword dict modified by

Modified: branches/blender2.5/blender/source/blender/python/intern/bpy_util.c
===================================================================
--- branches/blender2.5/blender/source/blender/python/intern/bpy_util.c 
2009-06-14 10:59:54 UTC (rev 20872)
+++ branches/blender2.5/blender/source/blender/python/intern/bpy_util.c 
2009-06-14 12:53:47 UTC (rev 20873)
@@ -168,6 +168,12 @@
                PyObject_Print(var, stderr, 0);
                fprintf(stderr, " ref:%d ", var->ob_refcnt);
                fprintf(stderr, " ptr:%ld", (long)var);
+               
+               fprintf(stderr, " type:");
+               if(Py_TYPE(var))
+                       fprintf(stderr, "%s", Py_TYPE(var)->tp_name);
+               else
+                       fprintf(stderr, "<NIL>");
        }
        fprintf(stderr, "\n");
 }
@@ -329,6 +335,72 @@
        return 0;
 }
 
+
+
+/* returns the exception string as a new PyUnicode object, depends on external 
StringIO module */
+PyObject *BPY_exception_buffer(void)
+{
+       PyObject *stdout_backup = PySys_GetObject("stdout"); /* borrowed */
+       PyObject *stderr_backup = PySys_GetObject("stderr"); /* borrowed */
+       PyObject *string_io = NULL;
+       PyObject *string_io_buf = NULL;
+       PyObject *string_io_mod;
+       PyObject *string_io_getvalue;
+       
+       PyObject *error_type, *error_value, *error_traceback;
+       
+       if (!PyErr_Occurred())
+               return NULL;
+       
+       PyErr_Fetch(&error_type, &error_value, &error_traceback);
+       
+       PyErr_Clear();
+       
+       /* import StringIO / io
+        * string_io = StringIO.StringIO()
+        */
+       
+#if PY_VERSION_HEX < 0x03000000
+       if(! (string_io_mod= PyImport_ImportModule("StringIO")) ) {
+#else
+       if(! (string_io_mod= PyImport_ImportModule("io")) ) {
+#endif
+               return NULL;
+       } else if (! (string_io = PyObject_CallMethod(string_io_mod, 
"StringIO", NULL))) {
+               Py_DECREF(string_io_mod);
+               return NULL;
+       } else if (! (string_io_getvalue= PyObject_GetAttrString(string_io, 
"getvalue"))) {
+               Py_DECREF(string_io_mod);
+               Py_DECREF(string_io);
+               return NULL;
+       }
+       
+       Py_INCREF(stdout_backup); // since these were borrowed we dont want 
them freed when replaced.
+       Py_INCREF(stderr_backup);
+       
+       PySys_SetObject("stdout", string_io); // both of these are free'd when 
restoring
+       PySys_SetObject("stderr", string_io);
+       
+       PyErr_Restore(error_type, error_value, error_traceback);
+       PyErr_Print(); /* print the error */
+       PyErr_Clear();
+       
+       string_io_buf = PyObject_CallObject(string_io_getvalue, NULL);
+       

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to