0001 """Dispatcher 0002 0003 Please see policy.py for a discussion on dispatchers and policies 0004 """ 0005 import pythoncom, traceback, win32api 0006 from sys import exc_info 0007 0008 # 0009 from win32com.server.exception import IsCOMServerException 0010 from win32com.util import IIDToInterfaceName 0011 import win32com 0012 0013 class DispatcherBase: 0014 """ The base class for all Dispatchers. 0015 0016 This dispatcher supports wrapping all operations in exception handlers, 0017 and all the necessary delegation to the policy. 0018 0019 This base class supports the printing of "unexpected" exceptions. Note, however, 0020 that exactly where the output of print goes may not be useful! A derived class may 0021 provide additional semantics for this. 0022 """ 0023 def __init__(self, policyClass, object): 0024 self.policy = policyClass(object) 0025 # The logger we should dump to. If None, we should send to the 0026 # default location (typically 'print') 0027 self.logger = getattr(win32com, "logger", None) 0028 0029 def _CreateInstance_(self, clsid, reqIID): 0030 try: 0031 self.policy._CreateInstance_(clsid, reqIID) 0032 return pythoncom.WrapObject(self, reqIID) 0033 except: 0034 self._HandleException_() 0035 0036 def _QueryInterface_(self, iid): 0037 try: 0038 return self.policy._QueryInterface_(iid) 0039 except: 0040 self._HandleException_() 0041 0042 def _Invoke_(self, dispid, lcid, wFlags, args): 0043 try: 0044 return self.policy._Invoke_(dispid, lcid, wFlags, args) 0045 except: 0046 self._HandleException_() 0047 0048 def _GetIDsOfNames_(self, names, lcid): 0049 try: 0050 return self.policy._GetIDsOfNames_(names, lcid) 0051 except: 0052 self._HandleException_() 0053 0054 def _GetTypeInfo_(self, index, lcid): 0055 try: 0056 return self.policy._GetTypeInfo_(index, lcid) 0057 except: 0058 self._HandleException_() 0059 0060 def _GetTypeInfoCount_(self): 0061 try: 0062 return self.policy._GetTypeInfoCount_() 0063 except: 0064 self._HandleException_() 0065 0066 def _GetDispID_(self, name, fdex): 0067 try: 0068 return self.policy._GetDispID_(name, fdex) 0069 except: 0070 self._HandleException_() 0071 0072 def _InvokeEx_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider): 0073 try: 0074 return self.policy._InvokeEx_(dispid, lcid, wFlags, args, kwargs, serviceProvider) 0075 except: 0076 self._HandleException_() 0077 0078 def _DeleteMemberByName_(self, name, fdex): 0079 try: 0080 return self.policy._DeleteMemberByName_(name, fdex) 0081 except: 0082 self._HandleException_() 0083 0084 def _DeleteMemberByDispID_(self, id): 0085 try: 0086 return self.policy._DeleteMemberByDispID_(id) 0087 except: 0088 self._HandleException_() 0089 0090 def _GetMemberProperties_(self, id, fdex): 0091 try: 0092 return self.policy._GetMemberProperties_(id, fdex) 0093 except: 0094 self._HandleException_() 0095 0096 def _GetMemberName_(self, dispid): 0097 try: 0098 return self.policy._GetMemberName_(dispid) 0099 except: 0100 self._HandleException_() 0101 0102 def _GetNextDispID_(self, fdex, flags): 0103 try: 0104 return self.policy._GetNextDispID_(fdex, flags) 0105 except: 0106 self._HandleException_() 0107 0108 def _GetNameSpaceParent_(self): 0109 try: 0110 return self.policy._GetNameSpaceParent_() 0111 except: 0112 self._HandleException_() 0113 0114 def _HandleException_(self): 0115 """Called whenever an exception is raised. 0116 0117 Default behaviour is to print the exception. 0118 """ 0119 # If not a COM exception, print it for the developer. 0120 if not IsCOMServerException(): 0121 if self.logger is not None: 0122 self.logger.exception("pythoncom server error") 0123 else: 0124 traceback.print_exc() 0125 # But still raise it for the framework. 0126 reraise() 0127 0128 def _trace_(self, *args): 0129 if self.logger is not None: 0130 record = " ".join(map(str, args)) 0131 self.logger.debug(record) 0132 else: 0133 for arg in args[:-1]: 0134 print arg, 0135 print args[-1] 0136 0137 class DispatcherTrace(DispatcherBase): 0138 """A dispatcher, which causes a 'print' line for each COM function called. 0139 """ 0140 def _QueryInterface_(self, iid): 0141 rc = DispatcherBase._QueryInterface_(self, iid) 0142 if not rc: 0143 self._trace_("in %s._QueryInterface_ with unsupported IID %s (%s)" % (`self.policy._obj_`, IIDToInterfaceName(iid),iid)) 0144 return rc 0145 0146 def _GetIDsOfNames_(self, names, lcid): 0147 self._trace_("in _GetIDsOfNames_ with '%s' and '%d'\n" % (names, lcid)) 0148 return DispatcherBase._GetIDsOfNames_(self, names, lcid) 0149 0150 def _GetTypeInfo_(self, index, lcid): 0151 self._trace_("in _GetTypeInfo_ with index=%d, lcid=%d\n" % (index, lcid)) 0152 return DispatcherBase._GetTypeInfo_(self, index, lcid) 0153 0154 def _GetTypeInfoCount_(self): 0155 self._trace_("in _GetTypeInfoCount_\n") 0156 return DispatcherBase._GetTypeInfoCount_(self) 0157 0158 def _Invoke_(self, dispid, lcid, wFlags, args): 0159 self._trace_("in _Invoke_ with", dispid, lcid, wFlags, args) 0160 return DispatcherBase._Invoke_(self, dispid, lcid, wFlags, args) 0161 0162 def _GetDispID_(self, name, fdex): 0163 self._trace_("in _GetDispID_ with", name, fdex) 0164 return DispatcherBase._GetDispID_(self, name, fdex) 0165 0166 def _InvokeEx_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider): 0167 self._trace_("in %r._InvokeEx_-%s%r [%x,%s,%r]" % (self.policy._obj_, dispid, args, wFlags, lcid, serviceProvider)) 0168 return DispatcherBase._InvokeEx_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider) 0169 0170 def _DeleteMemberByName_(self, name, fdex): 0171 self._trace_("in _DeleteMemberByName_ with", name, fdex) 0172 return DispatcherBase._DeleteMemberByName_(self, name, fdex) 0173 0174 def _DeleteMemberByDispID_(self, id): 0175 self._trace_("in _DeleteMemberByDispID_ with", id) 0176 return DispatcherBase._DeleteMemberByDispID_(self, id) 0177 0178 def _GetMemberProperties_(self, id, fdex): 0179 self._trace_("in _GetMemberProperties_ with", id, fdex) 0180 return DispatcherBase._GetMemberProperties_(self, id, fdex) 0181 0182 def _GetMemberName_(self, dispid): 0183 self._trace_("in _GetMemberName_ with", dispid) 0184 return DispatcherBase._GetMemberName_(self, dispid) 0185 0186 def _GetNextDispID_(self, fdex, flags): 0187 self._trace_("in _GetNextDispID_ with", fdex, flags) 0188 return DispatcherBase._GetNextDispID_(self, fdex, flags) 0189 0190 def _GetNameSpaceParent_(self): 0191 self._trace_("in _GetNameSpaceParent_") 0192 return DispatcherBase._GetNameSpaceParent_(self) 0193 0194 0195 class DispatcherWin32trace(DispatcherTrace): 0196 """A tracing dispatcher that sends its output to the win32trace remote collector. 0197 0198 """ 0199 def __init__(self, policyClass, object): 0200 DispatcherTrace.__init__(self, policyClass, object) 0201 if self.logger is None: 0202 # If we have no logger, setup our output. 0203 import win32traceutil # Sets up everything. 0204 self._trace_("Object with win32trace dispatcher created (object=%s)" % `object`) 0205 0206 0207 class DispatcherOutputDebugString(DispatcherTrace): 0208 """A tracing dispatcher that sends its output to win32api.OutputDebugString 0209 0210 """ 0211 def _trace_(self, *args): 0212 for arg in args[:-1]: 0213 win32api.OutputDebugString(str(arg)+" ") 0214 win32api.OutputDebugString(str(args[-1])+"\n") 0215 0216 0217 class DispatcherWin32dbg(DispatcherBase): 0218 """A source-level debugger dispatcher 0219 0220 A dispatcher which invokes the debugger as an object is instantiated, or 0221 when an unexpected exception occurs. 0222 0223 Requires Pythonwin. 0224 """ 0225 def __init__(self, policyClass, ob): 0226 # No one uses this, and it just causes py2exe to drag all of 0227 # pythonwin in. 0228 #import pywin.debugger 0229 pywin.debugger.brk() 0230 print "The DispatcherWin32dbg dispatcher is deprecated!" 0231 print "Please let me know if this is a problem." 0232 print "Uncomment the relevant lines in dispatcher.py to re-enable" 0233 # DEBUGGER Note - You can either: 0234 # * Hit Run and wait for a (non Exception class) exception to occur! 0235 # * Set a breakpoint and hit run. 0236 # * Step into the object creation (a few steps away!) 0237 DispatcherBase.__init__(self, policyClass, ob) 0238 0239 def _HandleException_(self): 0240 """ Invoke the debugger post mortem capability """ 0241 # Save details away. 0242 typ, val, tb = exc_info() 0243 #import pywin.debugger, pywin.debugger.dbgcon 0244 debug = 0 0245 try: 0246 raise typ, val 0247 except Exception: # AARG - What is this Exception??? 0248 # Use some inside knowledge to borrow a Debugger option which dictates if we 0249 # stop at "expected" exceptions. 0250 debug = pywin.debugger.GetDebugger().get_option(pywin.debugger.dbgcon.OPT_STOP_EXCEPTIONS) 0251 except: 0252 debug = 1 0253 if debug: 0254 try: 0255 pywin.debugger.post_mortem(tb, typ, val) # The original exception 0256 except: 0257 traceback.print_exc() 0258 0259 # But still raise it. 0260 del tb 0261 reraise() 0262 0263 def reraise(): 0264 """Handy function for re-raising errors. 0265 0266 Note: storing a traceback in a local variable can introduce reference 0267 loops if you aren't careful. Specifically, that local variable should 0268 not be within an execution context contained with the traceback. 0269 0270 By using a utility function, we ensure that our local variable holding 0271 the traceback is not referenced by the traceback itself. 0272 """ 0273 t, v, tb = exc_info() 0274 raise t, v, tb 0275 0276 try: 0277 import win32trace 0278 DefaultDebugDispatcher = DispatcherWin32trace 0279 except ImportError: # no win32trace module - just use a print based one. 0280 DefaultDebugDispatcher = DispatcherTrace 0281
Generated by PyXR 0.9.4