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-05-26 22:06:09 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-05-26 22:06:09 +0400
commit25569b0f7df6c29033834c281f246523b42bf16c (patch)
treefadb78bd2684cff14d9ea3a563c7cb39a5e8a28a
parent74977721a4516bf29052ff927e4752376e795e77 (diff)
BGE PyAPI Bug reported by Pitel on blenderartist.
importing "pygame" failed when running the BGE for the second time. Rather then clearing modules, backup and restore them (as its doing with sys.path) This way the BGE will never remember any modules imported during game play (which can cause bugs/crashes), but it also wont break pythons state by possibly removing modules that are being used internally.
-rw-r--r--source/blender/python/api2_2x/bpy_internal_import.c3
-rw-r--r--source/blender/python/api2_2x/bpy_internal_import.h2
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp99
3 files changed, 38 insertions, 66 deletions
diff --git a/source/blender/python/api2_2x/bpy_internal_import.c b/source/blender/python/api2_2x/bpy_internal_import.c
index 3bc90eb4f54..4aa703e8be4 100644
--- a/source/blender/python/api2_2x/bpy_internal_import.c
+++ b/source/blender/python/api2_2x/bpy_internal_import.c
@@ -281,6 +281,7 @@ PyMethodDef bpy_reload_meth[] = { {"bpy_reload_meth", blender_reload, METH_VARAR
* even if we remove a python module a reimport will bring it back again.
*/
+#if 0 // not used anymore but may still come in handy later
#if defined(WIN32) || defined(WIN64)
#define SEPSTR "\\"
@@ -336,4 +337,4 @@ void bpy_text_clear_modules(int clear_all)
Py_DECREF(list); /* removes all references from append */
}
-
+#endif
diff --git a/source/blender/python/api2_2x/bpy_internal_import.h b/source/blender/python/api2_2x/bpy_internal_import.h
index 7220212f13e..c93d930dab0 100644
--- a/source/blender/python/api2_2x/bpy_internal_import.h
+++ b/source/blender/python/api2_2x/bpy_internal_import.h
@@ -37,7 +37,7 @@
PyObject* bpy_text_import( char *name, int *found );
PyObject* bpy_text_reimport( PyObject *module, int *found );
-void bpy_text_clear_modules( int clear_all ); /* Clear user modules */
+/* void bpy_text_clear_modules( int clear_all );*/ /* Clear user modules */
extern PyMethodDef bpy_import_meth[];
extern PyMethodDef bpy_reload_meth[];
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index 7c131d01cd1..ff5a37801f4 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -112,7 +112,6 @@ extern "C" {
#include "GPU_material.h"
static void setSandbox(TPythonSecurityLevel level);
-static void clearGameModules();
// 'local' copy of canvas ptr, for window height/width python scripts
static RAS_ICanvas* gp_Canvas = NULL;
@@ -122,6 +121,7 @@ static RAS_IRasterizer* gp_Rasterizer = NULL;
static char gp_GamePythonPath[FILE_MAXDIR + FILE_MAXFILE] = "";
static char gp_GamePythonPathOrig[FILE_MAXDIR + FILE_MAXFILE] = ""; // not super happy about this, but we need to remember the first loaded file for the global/dict load save
static PyObject *gp_OrigPythonSysPath= NULL;
+static PyObject *gp_OrigPythonSysModules= NULL;
void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
{
@@ -1465,9 +1465,9 @@ void setSandbox(TPythonSecurityLevel level)
/* Explanation of
*
- * - backupPySysPath() : stores sys.path in gp_OrigPythonSysPath
- * - initPySysPath(main) : initializes the blendfile and library paths
- * - restorePySysPath() : restores sys.path from gp_OrigPythonSysPath
+ * - backupPySysObjects() : stores sys.path in gp_OrigPythonSysPath
+ * - initPySysObjects(main) : initializes the blendfile and library paths
+ * - restorePySysObjects() : restores sys.path from gp_OrigPythonSysPath
*
* These exist so the current blend dir "//" can always be used to import modules from.
* the reason we need a few functions for this is that python is not only used by the game engine
@@ -1482,23 +1482,27 @@ void setSandbox(TPythonSecurityLevel level)
/**
* So we can have external modules mixed with our blend files.
*/
-static void backupPySysPath(void)
+static void backupPySysObjects(void)
{
PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
+ PyObject *sys_mods= PySys_GetObject("modules"); /* should never fail */
- /* just incase its set */
- Py_XDECREF(gp_OrigPythonSysPath);
- gp_OrigPythonSysPath= NULL;
-
+ /* paths */
+ Py_XDECREF(gp_OrigPythonSysPath); /* just incase its set */
gp_OrigPythonSysPath = PyList_GetSlice(sys_path, 0, INT_MAX); /* copy the list */
+
+ /* modules */
+ Py_XDECREF(gp_OrigPythonSysModules); /* just incase its set */
+ gp_OrigPythonSysModules = PyDict_Copy(sys_mods); /* copy the list */
+
}
-/* for initPySysPath only,
+/* for initPySysObjects only,
* takes a blend path and adds a scripts dir from it
*
* "/home/me/foo.blend" -> "/home/me/scripts"
*/
-static void initPySysPath__append(PyObject *sys_path, char *filename)
+static void initPySysObjects__append(PyObject *sys_path, char *filename)
{
PyObject *item;
char expanded[FILE_MAXDIR + FILE_MAXFILE];
@@ -1515,13 +1519,13 @@ static void initPySysPath__append(PyObject *sys_path, char *filename)
Py_DECREF(item);
}
-static void initPySysPath(Main *maggie)
+static void initPySysObjects(Main *maggie)
{
PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
if (gp_OrigPythonSysPath==NULL) {
/* backup */
- backupPySysPath();
+ backupPySysObjects();
}
else {
/* get the original sys path when the BGE started */
@@ -1531,27 +1535,36 @@ static void initPySysPath(Main *maggie)
Library *lib= (Library *)maggie->library.first;
while(lib) {
- initPySysPath__append(sys_path, lib->name);
+ initPySysObjects__append(sys_path, lib->name);
lib= (Library *)lib->id.next;
}
- initPySysPath__append(sys_path, gp_GamePythonPath);
+ initPySysObjects__append(sys_path, gp_GamePythonPath);
// fprintf(stderr, "\nNew Path: %d ", PyList_Size(sys_path));
// PyObject_Print(sys_path, stderr, 0);
}
-static void restorePySysPath(void)
+static void restorePySysObjects(void)
{
if (gp_OrigPythonSysPath==NULL)
return;
PyObject *sys_path= PySys_GetObject("path"); /* should never fail */
-
+ PyObject *sys_mods= PySys_GetObject("modules"); /* should never fail */
+
+ /* paths */
PyList_SetSlice(sys_path, 0, INT_MAX, gp_OrigPythonSysPath);
Py_DECREF(gp_OrigPythonSysPath);
gp_OrigPythonSysPath= NULL;
+ /* modules */
+ PyDict_Clear(sys_mods);
+ PyDict_Update(sys_mods, gp_OrigPythonSysModules);
+ Py_DECREF(gp_OrigPythonSysModules);
+ gp_OrigPythonSysModules= NULL;
+
+
// fprintf(stderr, "\nRestore Path: %d ", PyList_Size(sys_path));
// PyObject_Print(sys_path, stderr, 0);
}
@@ -1588,7 +1601,7 @@ PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
bpy_import_main_set(maggie);
- initPySysPath(maggie);
+ initPySysObjects(maggie);
first_time = false;
@@ -1599,11 +1612,9 @@ PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
}
void exitGamePlayerPythonScripting()
-{
- //clearGameModules(); // were closing python anyway
-
+{
/* since python restarts we cant let the python backup of the sys.path hang around in a global pointer */
- restorePySysPath(); /* get back the original sys.path and clear the backup */
+ restorePySysObjects(); /* get back the original sys.path and clear the backup */
Py_Finalize();
bpy_import_main_set(NULL);
@@ -1629,10 +1640,7 @@ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLev
bpy_import_main_set(maggie);
- initPySysPath(maggie);
-
- /* clear user defined modules that may contain data from the last run */
- clearGameModules();
+ initPySysObjects(maggie);
PyObjectPlus::NullDeprecationWarning();
@@ -1640,46 +1648,9 @@ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLev
return PyModule_GetDict(moduleobj);
}
-static void clearModule(PyObject *modules, const char *name)
-{
- PyObject *mod= PyDict_GetItemString(modules, name);
-
- if (mod==NULL)
- return;
-
- PyDict_Clear(PyModule_GetDict(mod)); /* incase there are any circular refs */
- PyDict_DelItemString(modules, name);
-}
-
-static void clearGameModules()
-{
- /* references to invalid BGE data is better supported in 2.49+ so dont clear dicts */
-#if 0
- /* Note, user modules could still reference these modules
- * but since the dict's are cleared their members wont be accessible */
-
- PyObject *modules= PySys_GetObject((char *)"modules");
- clearModule(modules, "Expression");
- clearModule(modules, "CValue");
- clearModule(modules, "PhysicsConstraints");
- clearModule(modules, "GameLogic");
- clearModule(modules, "Rasterizer");
- clearModule(modules, "GameKeys");
- clearModule(modules, "VideoTexture");
- clearModule(modules, "Mathutils");
- clearModule(modules, "Geometry");
- clearModule(modules, "BGL");
- PyErr_Clear(); // incase some of these were alredy removed.
-#endif
-
- /* clear user defined modules, arg '1' for clear external py modules too */
- bpy_text_clear_modules(1);
-}
-
void exitGamePythonScripting()
{
- clearGameModules();
- restorePySysPath(); /* get back the original sys.path and clear the backup */
+ restorePySysObjects(); /* get back the original sys.path and clear the backup */
bpy_import_main_set(NULL);
PyObjectPlus::ClearDeprecationWarning();
}