| Update of /cvsroot/pywin32/pywin32/Pythonwin
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18996
Modified Files:
	win32thread.cpp win32ui.h win32uimodule.cpp win32virt.cpp 
Log Message:
[ 977399 ] Support for user supplied exception handler
Index: win32ui.h
===================================================================
RCS file: /cvsroot/pywin32/pywin32/Pythonwin/win32ui.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** win32ui.h	6 Dec 1999 01:13:50 -0000	1.2
--- win32ui.h	7 Oct 2004 08:45:24 -0000	1.3
***************
*** 239,242 ****
--- 239,252 ----
  };
  
+ enum EnumExceptionHandlerAction {
+ 	EHA_PRINT_ERROR,
+ 	EHA_DISPLAY_DIALOG
+ };
+ 
+ typedef void (*ExceptionHandlerFunc)(int action, const char *context, const char *extraTitleMsg);
+ 
+ PYW_EXPORT void ExceptionHandler(int action, const char *context=NULL, const char *extraTitleMsg=NULL);
+ PYW_EXPORT ExceptionHandlerFunc SetExceptionHandler(ExceptionHandlerFunc handler);
+ 
  // A helper class for calling "virtual methods" - ie, given a C++ object
  // call a Python method of that name on the attached Python object.
Index: win32uimodule.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/Pythonwin/win32uimodule.cpp,v
retrieving revision 1.28
retrieving revision 1.29
diff -C2 -d -r1.28 -r1.29
*** win32uimodule.cpp	8 Sep 2004 23:31:12 -0000	1.28
--- win32uimodule.cpp	7 Oct 2004 08:45:24 -0000	1.29
***************
*** 50,53 ****
--- 50,59 ----
  static char BASED_CODE errorName[] = "win32ui";
  
+ // We can't init exceptionHandler in initwin32ui because the application using
+ // us could have called SetExceptionHandler earlier. We do a forward declaration
+ // of DefaultExceptionHandler here and assign it to exceptionHandler.
+ void DefaultExceptionHandler(int action, const char *context, const char *extraTitleMsg);
+ static ExceptionHandlerFunc exceptionHandler = DefaultExceptionHandler;
+ 
  PYW_EXPORT PyObject *ui_module_error;
  Win32uiHostGlue *pHostGlue = NULL;
***************
*** 612,619 ****
  	v = PyRun_String((char *)command, file_input, d, d);
  	if (v == NULL) {
! 		PyObject *type, *value, *traceback;
! 		PyErr_Fetch(&type, &value, &traceback);
! 		DisplayPythonTraceback(type, value, traceback);
! 		PyErr_Restore(type, value, traceback);
  /*******
  		PyObject *fo = PyFile_FromString((char *)logFileName, "w" );
--- 618,622 ----
  	v = PyRun_String((char *)command, file_input, d, d);
  	if (v == NULL) {
! 		ExceptionHandler(EHA_DISPLAY_DIALOG);
  /*******
  		PyObject *fo = PyFile_FromString((char *)logFileName, "w" );
***************
*** 701,726 ****
  	// basic recursion control.
  	static BOOL bInError = FALSE;
! 	if (bInError) return;
  	bInError=TRUE;
  
! 	// Check if the exception is SystemExit - if so,
! 	// PyErr_Print will terminate then and there!  This is
! 	// not good (and not what we want!?
! 	PyObject *exception, *v, *tb;
! 	PyErr_Fetch(&exception, &v, &tb);
! 	PyErr_NormalizeException(&exception, &v, &tb);
  
! 	if (exception  && PyErr_GivenExceptionMatches(exception, PyExc_SystemExit)) {
! 		// Replace it with a RuntimeError.
! 		TRACE("WARNING!!  win32ui had a SystemError - Replacing with RuntimeError!!\n");
! 		Py_DECREF(exception);
! 		Py_XINCREF(PyExc_RuntimeError);
! 		PyErr_Restore(PyExc_RuntimeError, v, tb);
! 	} else
! 		PyErr_Restore(exception, v, tb);
! 	// Now print it.
  
! 	PyErr_Print();
! 	bInError=FALSE;
  }
  
--- 704,765 ----
  	// basic recursion control.
  	static BOOL bInError = FALSE;
! 	if (bInError) {
! 		TRACE("gui_print_error: recursive call!\n");
! 		return;
! 	}
  	bInError=TRUE;
+ 	ExceptionHandler(EHA_PRINT_ERROR);
+ 	bInError=FALSE;
+ }
  
! void DefaultExceptionHandler(int action, const char *context, const char *extraTitleMsg)
! {
! 	PyObject *type, *value, *traceback;
! 	PyErr_Fetch(&type, &value, &traceback);
! 	if (!type) {
! 		TRACE("DefaultExceptionHandler: no exception occured!\n");
! 		return;
! 	}
! 	if (action == EHA_PRINT_ERROR)
! 	{
! 		// Check if the exception is SystemExit - if so,
! 		// PyErr_Print will terminate then and there!  This is
! 		// not good (and not what we want!?
! 		PyErr_NormalizeException(&type, &value, &traceback);
  
! 		if (type && PyErr_GivenExceptionMatches(type, PyExc_SystemExit)) {
! 			// Replace it with a RuntimeError.
! 			TRACE("WARNING!!  win32ui had a SystemError - Replacing with RuntimeError!!\n");
! 			Py_DECREF(type);
! 			Py_XINCREF(PyExc_RuntimeError);
! 			PyErr_Restore(PyExc_RuntimeError, value, traceback);
! 		} else
! 			PyErr_Restore(type, value, traceback);
! 		fprintf(stderr, "%s\n", context);
! 		// Now print it.
! 		PyErr_Print();
! 	}
! 	else if (action == EHA_DISPLAY_DIALOG)
! 	{
! 		DisplayPythonTraceback(type, value, traceback, extraTitleMsg);
! 		PyErr_Restore(type, value, traceback);
! 	}
! 	else
! 		TRACE("DefaultExceptionHandler: unknown action (%d)\n", action);
! }
  
! void ExceptionHandler(int action, const char *context, const char *extraTitleMsg)
! {
! 	if (exceptionHandler)
! 		exceptionHandler(action, extraTitleMsg, context);
! 	else
! 		TRACE("ExceptionHandler: no exception handler available\n");
! }
! 
! ExceptionHandlerFunc SetExceptionHandler(ExceptionHandlerFunc handler)
! {
! 	ExceptionHandlerFunc oldHandler = exceptionHandler;
! 	exceptionHandler = handler;
! 	return oldHandler;
  }
  
Index: win32virt.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/Pythonwin/win32virt.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** win32virt.cpp	1 Sep 1999 23:33:03 -0000	1.1
--- win32virt.cpp	7 Oct 2004 08:45:24 -0000	1.2
***************
*** 16,20 ****
  //
  //////////////////////////////////////////////////////////////////////
- extern BOOL DisplayPythonTraceback(PyObject *exc_type, PyObject *exc_val, PyObject *exc_tb, const char *extraTitleMsg = NULL);
  
  extern BOOL bInFatalShutdown;
--- 16,19 ----
***************
*** 92,97 ****
  			TRACE("CallVirtual : callback failed with exception\n");
  			gui_print_error();
  			PyObject *obRepr = PyObject_Repr(handler);
! 			char *szRepr = PyString_AsString(obRepr);
  			wsprintf(msg, "%s() virtual handler (%s) raised an exception", (const char *)csHandlerName, szRepr);
  			Py_XDECREF(obRepr);
--- 91,99 ----
  			TRACE("CallVirtual : callback failed with exception\n");
  			gui_print_error();
+ 			// this will probably fail if we are already inside the exception handler
  			PyObject *obRepr = PyObject_Repr(handler);
! 			char *szRepr = "<no representation (PyObject_Repr failed)>";
! 			if (obRepr)
! 				szRepr = PyString_AsString(obRepr);
  			wsprintf(msg, "%s() virtual handler (%s) raised an exception", (const char *)csHandlerName, szRepr);
  			Py_XDECREF(obRepr);
***************
*** 108,115 ****
  			csAddnMsg += " handler";
  
! 			PyObject *type, *value, *traceback;
! 			PyErr_Fetch(&type, &value, &traceback);
! 			DisplayPythonTraceback(type, value, traceback, csAddnMsg);
! 			PyErr_Restore(type, value, traceback);
  		}
  		return FALSE;
--- 110,114 ----
  			csAddnMsg += " handler";
  
! 			ExceptionHandler(EHA_DISPLAY_DIALOG, NULL, csAddnMsg);
  		}
  		return FALSE;
Index: win32thread.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/Pythonwin/win32thread.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** win32thread.cpp	20 Jan 2004 22:28:58 -0000	1.5
--- win32thread.cpp	7 Oct 2004 08:45:24 -0000	1.6
***************
*** 160,165 ****
  			PyErr_Clear();
  		else {
! 			fprintf(stderr, "Unhandled exception in thread:\n");
! 			PyErr_Print();
  		}
  	}
--- 160,164 ----
  			PyErr_Clear();
  		else {
! 			ExceptionHandler(EHA_PRINT_ERROR, "Unhandled exception in thread");
  		}
  	}
 |