Update of /cvsroot/pywin32/pywin32/com/win32com/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10047
Modified Files:
ErrorUtils.cpp PyGatewayBase.cpp
Log Message:
The gateway/server functions all now will write exception to a
win32com.logger object if it exists (or to sys.stdout, like previously, if
it does not).
By default, no win32com.logger is created - this is designed for people
who want integrated logging for their entire Python application.
Index: PyGatewayBase.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/com/win32com/src/PyGatewayBase.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -C2 -d -r1.13 -r1.14
*** PyGatewayBase.cpp 2 Jul 2004 04:04:54 -0000 1.13
--- PyGatewayBase.cpp 7 Sep 2004 02:19:27 -0000 1.14
***************
*** 23,27 ****
// Helper function to handle the IDispatch results
! static HRESULT GetIDispatchErrorResult(EXCEPINFO *pexcepinfo)
{
HRESULT hr;
--- 23,27 ----
// Helper function to handle the IDispatch results
! static HRESULT GetIDispatchErrorResult(PyObject *logProvider, EXCEPINFO *pexcepinfo)
{
HRESULT hr;
***************
*** 34,38 ****
bCleanupExcepInfo = FALSE;
// Log the error
! PyCom_LogNonServerError("Python error invoking COM method.");
// Fill the EXCEPINFO with the details.
--- 34,38 ----
bCleanupExcepInfo = FALSE;
// Log the error
! PyCom_LoggerNonServerException(logProvider, "Python error invoking COM method.");
// Fill the EXCEPINFO with the details.
***************
*** 444,447 ****
--- 444,448 ----
static HRESULT invoke_finish(
+ PyObject *dispatcher, /* The dispatcher for the gateway */
PyObject *result, /* The PyObject returned from the Python call */
VARIANT FAR* pVarResult, /* Result variant passed by the caller */
***************
*** 578,582 ****
// clears the Python error condition.
if (PyErr_Occurred())
! hr = GetIDispatchErrorResult(einfo);
Py_DECREF(result);
--- 579,583 ----
// clears the Python error condition.
if (PyErr_Occurred())
! hr = GetIDispatchErrorResult(dispatcher, einfo);
Py_DECREF(result);
***************
*** 638,644 ****
if ( result==NULL )
! return GetIDispatchErrorResult(pexcepinfo);
else
! hr = invoke_finish(result, pVarResult, puArgErr, pexcepinfo, IID_IDispatch, params, true);
}
return hr;
--- 639,645 ----
if ( result==NULL )
! return GetIDispatchErrorResult(m_pPyObject, pexcepinfo);
else
! hr = invoke_finish(m_pPyObject, result, pVarResult, puArgErr, pexcepinfo, IID_IDispatch, params, true);
}
return hr;
***************
*** 704,708 ****
PyObject *obISP = PyCom_PyObjectFromIUnknown(pspCaller, IID_IServiceProvider, TRUE);
if (obISP==NULL)
! return GetIDispatchErrorResult(pexcepinfo);
PyObject *argList;
--- 705,709 ----
PyObject *obISP = PyCom_PyObjectFromIUnknown(pspCaller, IID_IServiceProvider, TRUE);
if (obISP==NULL)
! return GetIDispatchErrorResult(m_pPyObject, pexcepinfo);
PyObject *argList;
***************
*** 722,728 ****
if ( result==NULL )
! hr = GetIDispatchErrorResult(pexcepinfo);
else {
! hr = invoke_finish(result, pVarResult, NULL, pexcepinfo, IID_IDispatchEx, params, false);
}
}
--- 723,729 ----
if ( result==NULL )
! hr = GetIDispatchErrorResult(m_pPyObject, pexcepinfo);
else {
! hr = invoke_finish(m_pPyObject, result, pVarResult, NULL, pexcepinfo, IID_IDispatchEx, params, false);
}
}
***************
*** 909,915 ****
va_end(va);
! if (result==NULL)
! PyCom_LogNonServerError("Python error calling method %s\n", szMethodName);
! HRESULT hr = PyCom_SetAndLogCOMErrorFromPyException(szMethodName, GetIID());
if ( ppResult )
--- 910,914 ----
va_end(va);
! HRESULT hr = PyCom_SetAndLogCOMErrorFromPyExceptionEx(m_pPyObject, szMethodName, GetIID());
if ( ppResult )
Index: ErrorUtils.cpp
===================================================================
RCS file: /cvsroot/pywin32/pywin32/com/win32com/src/ErrorUtils.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** ErrorUtils.cpp 24 Nov 2003 09:14:53 -0000 1.20
--- ErrorUtils.cpp 7 Sep 2004 02:19:27 -0000 1.21
***************
*** 21,24 ****
--- 21,26 ----
static PyObject *PyCom_PyObjectFromIErrorInfo(IErrorInfo *, HRESULT errorhr);
+ static const char *traceback_prefix = "Traceback (most recent call last):\n";
+
////////////////////////////////////////////////////////////////////////
//
***************
*** 346,349 ****
--- 348,360 ----
}
+ PYCOM_EXPORT HRESULT PyCom_SetAndLogCOMErrorFromPyExceptionEx(PyObject *provider, const char *methodName, REFIID riid /* = IID_NULL */)
+ {
+ if (!PyErr_Occurred())
+ // No error occurred
+ return S_OK;
+ PyCom_LoggerNonServerException(provider, "Unexpected exception in gateway method '%s'", methodName);
+ return PyCom_SetCOMErrorFromPyException(riid);
+ }
+
////////////////////////////////////////////////////////////////////////
// Some logging functions
***************
*** 458,461 ****
--- 469,512 ----
PyErr_Restore(typ, val, tb);
}
+ BOOL VLogF_Logger(PyObject *logger, const char *log_method,
+ const TCHAR *prefix, const TCHAR *fmt, va_list argptr)
+ {
+ // Protected by Python lock
+ static TCHAR buff[8196];
+ int buf_len = sizeof(buff) / sizeof(buff[0]);
+ int prefix_len = strlen(prefix);
+ assert(prefix_len<100);
+ strcpy(buff, prefix);
+ wvsprintf(buff+prefix_len, fmt, argptr);
+
+ PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
+ PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
+
+ // Python 2.3 has an issue in that attempting to make the call with
+ // an exception set causes the call itself to fail - but
+ // 2.3's logger provides no way of passing the exception!
+ // We make no attempt to worm around this - if you really want this feature
+ // in Python 2.3, simply use the Python 2.4 logging package (or at least
+ // a logger from that package)
+ PyObject *kw = PyDict_New();
+ PyObject *exc_info = Py_BuildValue("OOO", exc_typ, exc_val, exc_tb);
+ if (kw)
+ PyDict_SetItemString(kw, "exc_info", exc_info);
+ Py_XDECREF(exc_info);
+ PyObject *args = Py_BuildValue("(s)", buff);
+ PyObject *method = PyObject_GetAttrString(logger, (char *)log_method);
+ PyObject *result = NULL;
+ if (method && kw && args)
+ result = PyObject_Call(method, args, kw);
+ Py_XDECREF(method);
+ Py_XDECREF(kw);
+ Py_XDECREF(args);
+ if (!result)
+ PyErr_Print();
+ BOOL rc = result != NULL;
+ Py_XDECREF(result);
+ PyErr_Restore( exc_typ, exc_val, exc_tb);
+ return rc;
+ }
void VLogF(const TCHAR *fmt, va_list argptr)
***************
*** 484,488 ****
PyCom_StreamMessage("Can't get the traceback info!");
else {
! PyCom_StreamMessage("Traceback (most recent call last):\n");
PyCom_StreamMessage(szTraceback);
PyMem_Free((void *)szTraceback);
--- 535,539 ----
PyCom_StreamMessage("Can't get the traceback info!");
else {
! PyCom_StreamMessage(traceback_prefix);
PyCom_StreamMessage(szTraceback);
PyMem_Free((void *)szTraceback);
***************
*** 507,517 ****
}
! PYCOM_EXPORT
! void PyCom_LogError(const char *fmt, ...)
{
- va_list marker;
- va_start(marker, fmt);
PyCom_StreamMessage("pythoncom error: ");
! VLogF(fmt, marker);
PyCom_StreamMessage("\n");
// If we have a Python exception, also log that:
--- 558,565 ----
}
! void _DoLogError(const char *fmt, va_list argptr)
{
PyCom_StreamMessage("pythoncom error: ");
! VLogF(fmt, argptr);
PyCom_StreamMessage("\n");
// If we have a Python exception, also log that:
***************
*** 520,523 ****
--- 568,572 ----
if (exc_typ) {
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
+ PyCom_StreamMessage("\n");
_LogException(exc_typ, exc_val, exc_tb);
}
***************
*** 525,551 ****
}
-
PYCOM_EXPORT
! void PyCom_LogNonServerError(const char *fmt, ...)
{
! // See if our gateway exception
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
if (exc_typ) {
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
! if (!PyErr_GivenExceptionMatches(exc_val, PyWinExc_COMError) ||
! ((PyInstance_Check(exc_val) &&
! (PyObject *)(((PyInstanceObject *)exc_val)->in_class)==PyWinExc_COMError))) {
! va_list marker;
! va_start(marker, fmt);
! PyCom_StreamMessage("pythoncom error: ");
! VLogF(fmt, marker);
! PyCom_StreamMessage("\n");
! _LogException(exc_typ, exc_val, exc_tb);
}
}
PyErr_Restore(exc_typ, exc_val, exc_tb);
}
////////////////////////////////////////////////////////////////////////
--- 574,654 ----
}
PYCOM_EXPORT
! void PyCom_LogError(const char *fmt, ...)
{
! va_list marker;
! va_start(marker, fmt);
! _DoLogError(fmt, marker);
! }
!
! BOOL IsNonServerErrorCurrent() {
! BOOL rc = FALSE;
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
if (exc_typ) {
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
! rc = (!PyErr_GivenExceptionMatches(exc_val, PyWinExc_COMError) ||
! ((PyInstance_Check(exc_val) &&
! (PyObject *)(((PyInstanceObject *)exc_val)->in_class)==PyWinExc_COMError)));
! }
! PyErr_Restore(exc_typ, exc_val, exc_tb);
! return rc;
! }
!
! PYCOM_EXPORT
! void PyCom_LogNonServerError(const char *fmt, ...)
! {
! // If any error other than our explicit 'com server error' is current,
! // assume it is unintended, and log it.
! if (IsNonServerErrorCurrent()) {
! va_list marker;
! va_start(marker, fmt);
! _DoLogError(fmt, marker);
! }
! }
!
! void _DoLogger(PyObject *logProvider, char *log_method, const char *fmt, va_list argptr)
! {
! PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
! PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
! PyObject *logger = NULL;
! if (logProvider)
! logger = PyObject_CallMethod(logProvider, "_GetLogger_", NULL);
! if (logger == NULL) {
! PyObject *mod = PyImport_ImportModule("win32com");
! if (mod) {
! logger = PyObject_GetAttrString(mod, "logger");
! Py_DECREF(mod);
}
}
+ // Returning a logger of None means "no logger"
+ if (logger == Py_None) {
+ Py_DECREF(logger);
+ logger = NULL;
+ }
PyErr_Restore(exc_typ, exc_val, exc_tb);
+ if (!logger ||
+ !VLogF_Logger(logger, log_method, "pythoncom error: ", fmt, argptr))
+ // No logger, or logger error - normal stdout stream.
+ _DoLogError(fmt, argptr);
+ Py_XDECREF(logger);
}
+ PYCOM_EXPORT void PyCom_LoggerException(PyObject *logProvider, const char *fmt, ...)
+ {
+ va_list marker;
+ va_start(marker, fmt);
+ _DoLogger(logProvider, "error", fmt, marker);
+ }
+
+ PYCOM_EXPORT
+ void PyCom_LoggerNonServerException(PyObject *logProvider, const char *fmt, ...)
+ {
+ if (!IsNonServerErrorCurrent())
+ return;
+ va_list marker;
+ va_start(marker, fmt);
+ _DoLogger(logProvider, "error", fmt, marker);
+ }
////////////////////////////////////////////////////////////////////////
|