Index: Common/vtkPythonUtil.cxx
===================================================================
RCS file: /vtk/cvsroot/VTK/Common/vtkPythonUtil.cxx,v
retrieving revision 1.70
diff -u -r1.70 vtkPythonUtil.cxx
--- Common/vtkPythonUtil.cxx	15 Dec 2004 14:35:03 -0000	1.70
+++ Common/vtkPythonUtil.cxx	17 Jun 2005 08:20:13 -0000
@@ -1730,6 +1730,10 @@
 vtkPythonCommand::vtkPythonCommand()
 { 
   this->obj = NULL;
+#ifdef WITH_THREAD
+  // get ThreadState for the thread running this observer
+  this->ThreadState = PyThreadState_Get();
+#endif
 }
 
 vtkPythonCommand::~vtkPythonCommand()
@@ -1739,6 +1743,9 @@
     Py_DECREF(this->obj);
     }
   this->obj = NULL;
+#ifdef WITH_THREAD
+  this->ThreadState = NULL;
+#endif
 }
 
 void vtkPythonCommand::SetObject(PyObject *o)
@@ -1749,6 +1756,16 @@
 void vtkPythonCommand::Execute(vtkObject *ptr, unsigned long eventtype,
                                void *CallData)
 {
+#ifdef WITH_THREAD
+  // By definition, this method will be called from a running VTK method.
+  // The VTK wrapping code now gives up the GIL before calling VTK methods,
+  // so we have to reclaim it here before we can make any Python API calls.
+  // 1. first acquire the GIL
+  PyEval_AcquireLock();
+  // 2. then swap in the thread state of this observer
+  PyThreadState_Swap(this->ThreadState);
+#endif
+
   PyObject *arglist, *result, *obj2;
   const char *eventname;
 
@@ -1845,6 +1862,16 @@
       }
     PyErr_Print();
     }
+
+#ifdef WITH_THREAD
+  // We're returning to the VTK method, so we have to give up the GIL
+  // again.  Other Python threads will be able to execute.
+  // 1. swap out thread state of this observer
+  PyThreadState_Swap(NULL);
+  // 2. give the lock back so other Python threads can execute again
+  PyEval_ReleaseLock();
+#endif
+    
 }
 //--------------------------------------------------------------------
 
Index: Common/vtkPythonUtil.h
===================================================================
RCS file: /vtk/cvsroot/VTK/Common/vtkPythonUtil.h,v
retrieving revision 1.33
diff -u -r1.33 vtkPythonUtil.h
--- Common/vtkPythonUtil.h	17 Feb 2004 15:31:24 -0000	1.33
+++ Common/vtkPythonUtil.h	17 Jun 2005 08:20:13 -0000
@@ -167,6 +167,10 @@
   void Execute(vtkObject *ptr, unsigned long eventtype, void *CallData);
  
   PyObject *obj;
+#ifdef WITH_THREAD
+  PyThreadState *ThreadState;
+#endif
+   
 protected:
   vtkPythonCommand();
   ~vtkPythonCommand(); 
Index: Wrapping/vtkWrapPython.c
===================================================================
RCS file: /vtk/cvsroot/VTK/Wrapping/vtkWrapPython.c,v
retrieving revision 1.71
diff -u -r1.71 vtkWrapPython.c
--- Wrapping/vtkWrapPython.c	4 Jan 2005 21:47:48 -0000	1.71
+++ Wrapping/vtkWrapPython.c	17 Jun 2005 08:20:15 -0000
@@ -739,7 +739,12 @@
               fprintf(fp,"    else {\n");
               sprintf(methodname,"op->%s",currentFunction->Name);
               }
-                
+            
+            // Release GIL right before we call potentially long-running code
+            // but AFTER all Python API calls.  If we don't do this, no other
+            // Python thread can execute while VTK is processing.
+            fprintf(fp,"      Py_BEGIN_ALLOW_THREADS\n");
+
             switch (currentFunction->ReturnType%1000)
               {
               case 2:
@@ -773,6 +778,10 @@
                 }
               }
             fprintf(fp,");\n");
+                
+            // get GIL back right after call to long-running VTK code but
+            // BEFORE any calls to Python code
+            fprintf(fp,"      Py_END_ALLOW_THREADS\n");
           
             if (currentFunction->NumberOfArguments == 1 
                 && currentFunction->ArgTypes[0] == 5000)
