Revision: 20434
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20434
Author:   campbellbarton
Date:     2009-05-26 20:06:09 +0200 (Tue, 26 May 2009)

Log Message:
-----------
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.

Modified Paths:
--------------
    trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c
    trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h
    trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp

Modified: trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c
===================================================================
--- trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c   
2009-05-26 17:20:22 UTC (rev 20433)
+++ trunk/blender/source/blender/python/api2_2x/bpy_internal_import.c   
2009-05-26 18:06:09 UTC (rev 20434)
@@ -281,6 +281,7 @@
  * 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 @@
        
        Py_DECREF(list); /* removes all references from append */
 }
-
+#endif

Modified: trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h
===================================================================
--- trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h   
2009-05-26 17:20:22 UTC (rev 20433)
+++ trunk/blender/source/blender/python/api2_2x/bpy_internal_import.h   
2009-05-26 18:06:09 UTC (rev 20434)
@@ -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[];
 

Modified: trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp    2009-05-26 
17:20:22 UTC (rev 20433)
+++ trunk/blender/source/gameengine/Ketsji/KX_PythonInit.cpp    2009-05-26 
18:06:09 UTC (rev 20434)
@@ -112,7 +112,6 @@
 #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 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 @@
 
 /* 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 @@
 /**
  * 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 @@
        
        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 @@
        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 @@
        
        bpy_import_main_set(maggie);
        
-       initPySysPath(maggie);
+       initPySysObjects(maggie);
        
        first_time = false;
        
@@ -1599,11 +1612,9 @@
 }
 
 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 @@
        
        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 @@
        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();
 }


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

Reply via email to