bpy_context_set and bpy_context_clear to replace a number of functions (some were not always called causing bugs).

fix for a leak when trying to run a text with a syntax error too.
This commit is contained in:
Campbell Barton 2009-08-07 16:20:19 +00:00
parent ce273aee08
commit 70f011bbce
4 changed files with 63 additions and 34 deletions

@ -45,6 +45,50 @@
#include "../generic/BGL.h" #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 ) void BPY_free_compiled_text( struct Text *text )
{ {
if( text->compiled ) { if( text->compiled ) {
@ -106,9 +150,6 @@ static PyObject *CreateGlobalDictionary( bContext *C )
PyDict_SetItemString( dict, "__name__", item ); PyDict_SetItemString( dict, "__name__", item );
Py_DECREF(item); Py_DECREF(item);
// XXX - evil, need to access context
BPy_SetContext(C);
// XXX - put somewhere more logical // XXX - put somewhere more logical
{ {
PyMethodDef *ml; PyMethodDef *ml;
@ -224,19 +265,14 @@ void BPY_end_python( void )
/* Can run a file or text block */ /* Can run a file or text block */
int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struct ReportList *reports) 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; PyGILState_STATE gilstate;
if (fn==NULL && text==NULL) { if (fn==NULL && text==NULL) {
return 0; return 0;
} }
//BPY_start_python(); bpy_context_set(C, &gilstate);
gilstate = PyGILState_Ensure();
BPY_update_modules(); /* can give really bad results if this isnt here */
bpy_import_main_set(CTX_data_main(C));
py_dict = CreateGlobalDictionary(C); py_dict = CreateGlobalDictionary(C);
@ -251,12 +287,10 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
MEM_freeN( buf ); MEM_freeN( buf );
if( PyErr_Occurred( ) ) { if( PyErr_Occurred( ) ) {
BPy_errors_to_report(reports);
BPY_free_compiled_text( text ); BPY_free_compiled_text( text );
PyGILState_Release(gilstate);
return 0;
} }
} }
if(text->compiled)
py_result = PyEval_EvalCode( text->compiled, py_dict, py_dict ); py_result = PyEval_EvalCode( text->compiled, py_dict, py_dict );
} else { } else {
@ -287,10 +321,9 @@ int BPY_run_python_script( bContext *C, const char *fn, struct Text *text, struc
} }
Py_DECREF(py_dict); 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; return py_result ? 1:0;
} }
@ -473,12 +506,7 @@ void BPY_run_ui_scripts(bContext *C, int reload)
PyGILState_STATE gilstate; PyGILState_STATE gilstate;
PyObject *sys_path; PyObject *sys_path;
gilstate = PyGILState_Ensure(); bpy_context_set(C, &gilstate);
// XXX - evil, need to access context
BPy_SetContext(C);
bpy_import_main_set(CTX_data_main(C));
sys_path= PySys_GetObject("path"); /* borrow */ sys_path= PySys_GetObject("path"); /* borrow */
PyList_Insert(sys_path, 0, Py_None); /* place holder, resizes the list */ 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 */ 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 #ifdef TIME_REGISTRATION
printf("script time %f\n", (PIL_check_seconds_timer()-time)); printf("script time %f\n", (PIL_check_seconds_timer()-time));
#endif #endif

@ -93,11 +93,9 @@ static int PYTHON_OT_generic(int mode, bContext *C, wmOperator *op, wmEvent *eve
PointerRNA ptr_event; PointerRNA ptr_event;
PyObject *py_operator; PyObject *py_operator;
PyGILState_STATE gilstate = PyGILState_Ensure(); PyGILState_STATE gilstate;
bpy_import_main_set(CTX_data_main(C)); bpy_context_set(C, &gilstate);
BPY_update_modules(); // XXX - the RNA pointers can change so update before running, would like a nicer solutuon for this.
args = PyTuple_New(1); args = PyTuple_New(1);
PyTuple_SET_ITEM(args, 0, PyObject_GetAttrString(py_class, "__rna__")); // need to use an rna instance as the first arg 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 #endif
PyGILState_Release(gilstate); bpy_context_clear(C, &gilstate);
bpy_import_main_set(NULL);
return ret_flag; return ret_flag;
} }

@ -2918,9 +2918,10 @@ static int bpy_class_call(PointerRNA *ptr, FunctionRNA *func, ParameterList *par
void *retdata= NULL; void *retdata= NULL;
int err= 0, i, flag; 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); 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(); PyErr_Clear();
} }
PyGILState_Release(gilstate); bpy_context_clear(C, &gilstate);
return err; return err;
} }

@ -82,4 +82,8 @@ int BPy_errors_to_report(struct ReportList *reports);
struct bContext *BPy_GetContext(void); struct bContext *BPy_GetContext(void);
void BPy_SetContext(struct bContext *C); 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 #endif