0001 # errorSemantics.py 0002 0003 # Test the Python error handling semantics. Specifically: 0004 # 0005 # * When a Python COM object is called via IDispatch, the nominated 0006 # scode is placed in the exception tuple, and the HRESULT is 0007 # DISP_E_EXCEPTION 0008 # * When the same interface is called via IWhatever, the 0009 # nominated scode is returned directly (with the scode also 0010 # reflected in the exception tuple) 0011 # * In all cases, the description etc end up in the exception tuple 0012 # * "Normal" Python exceptions resolve to an E_FAIL "internal error" 0013 0014 import pythoncom 0015 from win32com.server.exception import COMException 0016 from win32com.server.util import wrap 0017 from win32com.client import Dispatch 0018 import winerror 0019 from win32com.test.util import CaptureWriter 0020 0021 class error(Exception): 0022 def __init__(self, msg, com_exception=None): 0023 Exception.__init__(self, msg, str(com_exception)) 0024 0025 # Our COM server. 0026 class TestServer: 0027 _public_methods_ = [ 'Clone', 'Commit', 'LockRegion', 'Read'] 0028 _com_interfaces_ = [ pythoncom.IID_IStream ] 0029 0030 def Clone(self): 0031 raise COMException("Not today", scode=winerror.E_UNEXPECTED) 0032 0033 def Commit(self, flags): 0034 raise "foo" 0035 0036 def test(): 0037 # Call via a native interface. 0038 com_server = wrap(TestServer(), pythoncom.IID_IStream) 0039 try: 0040 com_server.Clone() 0041 except pythoncom.com_error, com_exc: 0042 hr, desc, exc, argErr = com_exc 0043 if hr != winerror.E_UNEXPECTED: 0044 raise error("Calling the object natively did not yield the correct scode", com_exc) 0045 if not exc or exc[-1] != winerror.E_UNEXPECTED: 0046 raise error("The scode element of the exception tuple did not yield the correct scode", com_exc) 0047 if exc[2] != "Not today": 0048 raise error("The description in the exception tuple did not yield the correct string", com_exc) 0049 cap = CaptureWriter() 0050 try: 0051 cap.capture() 0052 try: 0053 com_server.Commit(0) 0054 finally: 0055 cap.release() 0056 except pythoncom.com_error, com_exc: 0057 hr, desc, exc, argErr = com_exc 0058 if hr != winerror.E_FAIL: 0059 raise error("The hresult was not E_FAIL for an internal error", com_exc) 0060 if exc[1] != "Python COM Server Internal Error": 0061 raise error("The description in the exception tuple did not yield the correct string", com_exc) 0062 # Check we saw a traceback in stderr 0063 if cap.get_captured().find("Traceback")<0: 0064 raise error("Could not find a traceback in stderr: %r" % (cap.get_captured(),)) 0065 0066 # Now do it all again, but using IDispatch 0067 com_server = Dispatch(wrap(TestServer())) 0068 try: 0069 com_server.Clone() 0070 except pythoncom.com_error, com_exc: 0071 hr, desc, exc, argErr = com_exc 0072 if hr != winerror.DISP_E_EXCEPTION: 0073 raise error("Calling the object via IDispatch did not yield the correct scode", com_exc) 0074 if not exc or exc[-1] != winerror.E_UNEXPECTED: 0075 raise error("The scode element of the exception tuple did not yield the correct scode", com_exc) 0076 if exc[2] != "Not today": 0077 raise error("The description in the exception tuple did not yield the correct string", com_exc) 0078 0079 cap.clear() 0080 try: 0081 cap.capture() 0082 try: 0083 com_server.Commit(0) 0084 finally: 0085 cap.release() 0086 except pythoncom.com_error, com_exc: 0087 hr, desc, exc, argErr = com_exc 0088 if hr != winerror.DISP_E_EXCEPTION: 0089 raise error("Calling the object via IDispatch did not yield the correct scode", com_exc) 0090 if not exc or exc[-1] != winerror.E_FAIL: 0091 raise error("The scode element of the exception tuple did not yield the correct scode", com_exc) 0092 if exc[1] != "Python COM Server Internal Error": 0093 raise error("The description in the exception tuple did not yield the correct string", com_exc) 0094 # Check we saw a traceback in stderr 0095 if cap.get_captured().find("Traceback")<0: 0096 raise error("Could not find a traceback in stderr: %r" % (cap.get_captured(),)) 0097 0098 try: 0099 import logging 0100 except ImportError: 0101 logging = None 0102 if logging is not None: 0103 import win32com 0104 class TestLogHandler(logging.Handler): 0105 def __init__(self): 0106 self.num_emits = 0 0107 logging.Handler.__init__(self) 0108 def emit(self, record): 0109 self.num_emits += 1 0110 return 0111 print "--- record start" 0112 print self.format(record) 0113 print "--- record end" 0114 0115 def testLogger(): 0116 assert not hasattr(win32com, "logger") 0117 handler = TestLogHandler() 0118 formatter = logging.Formatter('%(message)s') 0119 handler.setFormatter(formatter) 0120 log = logging.getLogger("win32com_test") 0121 log.addHandler(handler) 0122 win32com.logger = log 0123 # Now throw some exceptions! 0124 # Native interfaces 0125 com_server = wrap(TestServer(), pythoncom.IID_IStream) 0126 try: 0127 com_server.Commit(0) 0128 raise RuntimeError, "should have failed" 0129 except pythoncom.error: 0130 pass 0131 assert handler.num_emits == 1, handler.num_emits 0132 handler.num_emits = 0 # reset 0133 0134 com_server = Dispatch(wrap(TestServer())) 0135 try: 0136 com_server.Commit(0) 0137 raise RuntimeError, "should have failed" 0138 except pythoncom.error: 0139 pass 0140 assert handler.num_emits == 1, handler.num_emits 0141 0142 if __name__=='__main__': 0143 test() 0144 if logging is not None: 0145 testLogger() 0146 from util import CheckClean 0147 CheckClean() 0148 print "error semantic tests worked" 0149
Generated by PyXR 0.9.4