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"
/* 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,12 +287,10 @@ 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;
}
}
if(text->compiled)
py_result = PyEval_EvalCode( text->compiled, py_dict, py_dict );
} else {
@ -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

@ -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;
}

@ -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;
}

@ -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