bpy_context_set and bpy_context_clear to replace a number of functions (some were...
authorCampbell Barton <ideasman42@gmail.com>
Fri, 7 Aug 2009 16:20:19 +0000 (16:20 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 7 Aug 2009 16:20:19 +0000 (16:20 +0000)
fix for a leak when trying to run a text with a syntax error too.

source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_operator_wrap.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_util.h

index 707c57693576c38a483073eb7200428ffa1bc75e..ed9dbdf28688a32bdfe4cb220309838b7d8cf9cd 100644 (file)
 #include "../generic/BGL.h"
 
 
+/* for internal use, when starting and ending python scripts */
+
+/* incase a python script triggers another python call, stop bpy_context_clear from invalidating */
+static int py_call_level= 0;
+
+void bpy_context_set(bContext *C, PyGILState_STATE *gilstate)
+{
+       py_call_level++;
+
+       if(gilstate)
+               *gilstate = PyGILState_Ensure();
+
+       if(py_call_level==1) {
+
+               BPY_update_modules(); /* can give really bad results if this isnt here */
+
+               if(C) { // XXX - should always be true.
+                       BPy_SetContext(C);
+                       bpy_import_main_set(CTX_data_main(C));
+               }
+               else {
+                       fprintf(stderr, "ERROR: Python context called with a NULL Context. this should not happen!\n");
+               }
+       }
+}
+
+void bpy_context_clear(bContext *C, PyGILState_STATE *gilstate)
+{
+       py_call_level--;
+
+       if(gilstate)
+               PyGILState_Release(*gilstate);
+
+       if(py_call_level < 0) {
+               fprintf(stderr, "ERROR: Python context internal state bug. this should not happen!\n");
+       }
+       else if(py_call_level==0) {
+               // XXX - Calling classes currently wont store the context :\, cant set NULL because of this. but this is very flakey still.
+               //BPy_SetContext(NULL);
+               //bpy_import_main_set(NULL);
+       }
+}
+
+
 void BPY_free_compiled_text( struct Text *text )
 {
        if( text->compiled ) {
@@ -106,9 +150,6 @@ static PyObject *CreateGlobalDictionary( bContext *C )
        PyDict_SetItemString( dict, "__name__", item );
        Py_DECREF(item);
        
-       // XXX - evil, need to access context
-       BPy_SetContext(C);
-       
        // XXX - put somewhere more logical
        {
                PyMethodDef *ml;
@@ -224,19 +265,14 @@ void BPY_end_python( void )
 /* Can run a file or text block */
 int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struct ReportList *reports)
 {
-       PyObject *py_dict, *py_result;
+       PyObject *py_dict, *py_result= NULL;
        PyGILState_STATE gilstate;
        
        if (fn==NULL && text==NULL) {
                return 0;
        }
        
-       //BPY_start_python();
-       
-       gilstate = PyGILState_Ensure();
-
-       BPY_update_modules(); /* can give really bad results if this isnt here */
-       bpy_import_main_set(CTX_data_main(C));
+       bpy_context_set(C, &gilstate);
        
        py_dict = CreateGlobalDictionary(C);
 
@@ -251,13 +287,11 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
                        MEM_freeN( buf );
 
                        if( PyErr_Occurred(  ) ) {
-                               BPy_errors_to_report(reports);
                                BPY_free_compiled_text( text );
-                               PyGILState_Release(gilstate);
-                               return 0;
                        }
                }
-               py_result =  PyEval_EvalCode( text->compiled, py_dict, py_dict );
+               if(text->compiled)
+                       py_result =  PyEval_EvalCode( text->compiled, py_dict, py_dict );
                
        } else {
 #if 0
@@ -287,10 +321,9 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
        }
        
        Py_DECREF(py_dict);
-       PyGILState_Release(gilstate);
-       bpy_import_main_set(NULL);
        
-       //BPY_end_python();
+       bpy_context_clear(C, &gilstate);
+
        return py_result ? 1:0;
 }
 
@@ -473,12 +506,7 @@ void BPY_run_ui_scripts(bContext *C, int reload)
        PyGILState_STATE gilstate;
        PyObject *sys_path;
 
-       gilstate = PyGILState_Ensure();
-       
-       // XXX - evil, need to access context
-       BPy_SetContext(C);
-       bpy_import_main_set(CTX_data_main(C));
-
+       bpy_context_set(C, &gilstate);
 
        sys_path= PySys_GetObject("path"); /* borrow */
        PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */
@@ -537,9 +565,8 @@ void BPY_run_ui_scripts(bContext *C, int reload)
        
        PyList_SetSlice(sys_path, 0, 1, NULL); /* remove the first item */
 
-       bpy_import_main_set(NULL);
+       bpy_context_clear(C, &gilstate);
        
-       PyGILState_Release(gilstate);
 #ifdef TIME_REGISTRATION
        printf("script time %f\n", (PIL_check_seconds_timer()-time));
 #endif
index 080d2e8ce6a1fb895e12c18b9c591f25d22fd0a0..7a92c747bd3036eafaa8339aca05b8c038eb9dbd 100644 (file)
@@ -93,11 +93,9 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
        PointerRNA ptr_event;
        PyObject *py_operator;
 
-       PyGILState_STATE gilstate = PyGILState_Ensure();
+       PyGILState_STATE gilstate;
 
-       bpy_import_main_set(CTX_data_main(C));
-       
-       BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solutuon for this.
+       bpy_context_set(C, &gilstate);
 
        args = PyTuple_New(1);
        PyTuple_SET_ITEM(args, 0, PyObject_GetAttrString(py_class, "__rna__")); // need to use an rna instance as the first arg
@@ -221,8 +219,7 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
        }
 #endif
 
-       PyGILState_Release(gilstate);
-       bpy_import_main_set(NULL);
+       bpy_context_clear(C, &gilstate);
 
        return ret_flag;
 }
index 27bfb89b9633489242a1fb308e86fea83d3a79b0..20164edc95a585b84f701eda52c2f499a3937dce 100644 (file)
@@ -2918,9 +2918,10 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
        void *retdata= NULL;
        int err= 0, i, flag;
 
-       PyGILState_STATE gilstate = PyGILState_Ensure();
+       PyGILState_STATE gilstate;
 
-       BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solution for this.
+       bContext *C= BPy_GetContext(); // XXX - NEEDS FIXING, QUITE BAD.
+       bpy_context_set(C, &gilstate);
 
        py_class= RNA_struct_py_type_get(ptr->type);
        
@@ -2996,7 +2997,7 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
                PyErr_Clear();
        }
 
-       PyGILState_Release(gilstate);
+       bpy_context_clear(C, &gilstate);
        
        return err;
 }
index 470dd4c2a45aade2bf82bcffb985570664a5d427..df204b7b90dc098a0d19e5b0816487a7a7310d63 100644 (file)
@@ -82,4 +82,8 @@ int BPy_errors_to_report(struct ReportList *reports);
 struct bContext *BPy_GetContext(void);
 void BPy_SetContext(struct bContext *C);
 
+extern void bpy_context_set(struct bContext *C, PyGILState_STATE *gilstate);
+extern void bpy_context_clear(struct bContext *C, PyGILState_STATE *gilstate);
+
+
 #endif