codekingpro/portable-devtools
114k
1"""Dispatcher2 3Please see policy.py for a discussion on dispatchers and policies4"""5import traceback6from sys import exc_info7 8import pythoncom9import win32api10import win32com11 12#13from win32com.server.exception import IsCOMServerException14from win32com.util import IIDToInterfaceName15 16 17class DispatcherBase:18 """The base class for all Dispatchers.19 20 This dispatcher supports wrapping all operations in exception handlers,21 and all the necessary delegation to the policy.22 23 This base class supports the printing of "unexpected" exceptions. Note, however,24 that exactly where the output of print goes may not be useful! A derived class may25 provide additional semantics for this.26 """27 28 def __init__(self, policyClass, object):29 self.policy = policyClass(object)30 # The logger we should dump to. If None, we should send to the31 # default location (typically 'print')32 self.logger = getattr(win32com, "logger", None)33 34 # Note the "return self._HandleException_()" is purely to stop pychecker35 # complaining - _HandleException_ will itself raise an exception for the36 # pythoncom framework, so the result will never be seen.37 def _CreateInstance_(self, clsid, reqIID):38 try:39 self.policy._CreateInstance_(clsid, reqIID)40 return pythoncom.WrapObject(self, reqIID)41 except:42 return self._HandleException_()43 44 def _QueryInterface_(self, iid):45 try:46 return self.policy._QueryInterface_(iid)47 except:48 return self._HandleException_()49 50 def _Invoke_(self, dispid, lcid, wFlags, args):51 try:52 return self.policy._Invoke_(dispid, lcid, wFlags, args)53 except:54 return self._HandleException_()55 56 def _GetIDsOfNames_(self, names, lcid):57 try:58 return self.policy._GetIDsOfNames_(names, lcid)59 except:60 return self._HandleException_()61 62 def _GetTypeInfo_(self, index, lcid):63 try:64 return self.policy._GetTypeInfo_(index, lcid)65 except:66 return self._HandleException_()67 68 def _GetTypeInfoCount_(self):69 try:70 return self.policy._GetTypeInfoCount_()71 except:72 return self._HandleException_()73 74 def _GetDispID_(self, name, fdex):75 try:76 return self.policy._GetDispID_(name, fdex)77 except:78 return self._HandleException_()79 80 def _InvokeEx_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider):81 try:82 return self.policy._InvokeEx_(83 dispid, lcid, wFlags, args, kwargs, serviceProvider84 )85 except:86 return self._HandleException_()87 88 def _DeleteMemberByName_(self, name, fdex):89 try:90 return self.policy._DeleteMemberByName_(name, fdex)91 except:92 return self._HandleException_()93 94 def _DeleteMemberByDispID_(self, id):95 try:96 return self.policy._DeleteMemberByDispID_(id)97 except:98 return self._HandleException_()99 100 def _GetMemberProperties_(self, id, fdex):101 try:102 return self.policy._GetMemberProperties_(id, fdex)103 except:104 return self._HandleException_()105 106 def _GetMemberName_(self, dispid):107 try:108 return self.policy._GetMemberName_(dispid)109 except:110 return self._HandleException_()111 112 def _GetNextDispID_(self, fdex, flags):113 try:114 return self.policy._GetNextDispID_(fdex, flags)115 except:116 return self._HandleException_()117 118 def _GetNameSpaceParent_(self):119 try:120 return self.policy._GetNameSpaceParent_()121 except:122 return self._HandleException_()123 124 def _HandleException_(self):125 """Called whenever an exception is raised.126 127 Default behaviour is to print the exception.128 """129 # If not a COM exception, print it for the developer.130 if not IsCOMServerException():131 if self.logger is not None:132 self.logger.exception("pythoncom server error")133 else:134 traceback.print_exc()135 # But still raise it for the framework.136 raise137 138 def _trace_(self, *args):139 if self.logger is not None:140 record = " ".join(map(str, args))141 self.logger.debug(record)142 else:143 for arg in args[:-1]:144 print(arg, end=" ")145 print(args[-1])146 147 148class DispatcherTrace(DispatcherBase):149 """A dispatcher, which causes a 'print' line for each COM function called."""150 151 def _QueryInterface_(self, iid):152 rc = DispatcherBase._QueryInterface_(self, iid)153 if not rc:154 self._trace_(155 "in %s._QueryInterface_ with unsupported IID %s (%s)"156 % (repr(self.policy._obj_), IIDToInterfaceName(iid), iid)157 )158 return rc159 160 def _GetIDsOfNames_(self, names, lcid):161 self._trace_("in _GetIDsOfNames_ with '%s' and '%d'\n" % (names, lcid))162 return DispatcherBase._GetIDsOfNames_(self, names, lcid)163 164 def _GetTypeInfo_(self, index, lcid):165 self._trace_("in _GetTypeInfo_ with index=%d, lcid=%d\n" % (index, lcid))166 return DispatcherBase._GetTypeInfo_(self, index, lcid)167 168 def _GetTypeInfoCount_(self):169 self._trace_("in _GetTypeInfoCount_\n")170 return DispatcherBase._GetTypeInfoCount_(self)171 172 def _Invoke_(self, dispid, lcid, wFlags, args):173 self._trace_("in _Invoke_ with", dispid, lcid, wFlags, args)174 return DispatcherBase._Invoke_(self, dispid, lcid, wFlags, args)175 176 def _GetDispID_(self, name, fdex):177 self._trace_("in _GetDispID_ with", name, fdex)178 return DispatcherBase._GetDispID_(self, name, fdex)179 180 def _InvokeEx_(self, dispid, lcid, wFlags, args, kwargs, serviceProvider):181 self._trace_(182 "in %r._InvokeEx_-%s%r [%x,%s,%r]"183 % (self.policy._obj_, dispid, args, wFlags, lcid, serviceProvider)184 )185 return DispatcherBase._InvokeEx_(186 self, dispid, lcid, wFlags, args, kwargs, serviceProvider187 )188 189 def _DeleteMemberByName_(self, name, fdex):190 self._trace_("in _DeleteMemberByName_ with", name, fdex)191 return DispatcherBase._DeleteMemberByName_(self, name, fdex)192 193 def _DeleteMemberByDispID_(self, id):194 self._trace_("in _DeleteMemberByDispID_ with", id)195 return DispatcherBase._DeleteMemberByDispID_(self, id)196 197 def _GetMemberProperties_(self, id, fdex):198 self._trace_("in _GetMemberProperties_ with", id, fdex)199 return DispatcherBase._GetMemberProperties_(self, id, fdex)200 201 def _GetMemberName_(self, dispid):202 self._trace_("in _GetMemberName_ with", dispid)203 return DispatcherBase._GetMemberName_(self, dispid)204 205 def _GetNextDispID_(self, fdex, flags):206 self._trace_("in _GetNextDispID_ with", fdex, flags)207 return DispatcherBase._GetNextDispID_(self, fdex, flags)208 209 def _GetNameSpaceParent_(self):210 self._trace_("in _GetNameSpaceParent_")211 return DispatcherBase._GetNameSpaceParent_(self)212 213 214class DispatcherWin32trace(DispatcherTrace):215 """A tracing dispatcher that sends its output to the win32trace remote collector."""216 217 def __init__(self, policyClass, object):218 DispatcherTrace.__init__(self, policyClass, object)219 if self.logger is None:220 # If we have no logger, setup our output.221 import win32traceutil # Sets up everything.222 self._trace_(223 "Object with win32trace dispatcher created (object=%s)" % repr(object)224 )225 226 227class DispatcherOutputDebugString(DispatcherTrace):228 """A tracing dispatcher that sends its output to win32api.OutputDebugString"""229 230 def _trace_(self, *args):231 for arg in args[:-1]:232 win32api.OutputDebugString(str(arg) + " ")233 win32api.OutputDebugString(str(args[-1]) + "\n")234 235 236class DispatcherWin32dbg(DispatcherBase):237 """A source-level debugger dispatcher238 239 A dispatcher which invokes the debugger as an object is instantiated, or240 when an unexpected exception occurs.241 242 Requires Pythonwin.243 """244 245 def __init__(self, policyClass, ob):246 # No one uses this, and it just causes py2exe to drag all of247 # pythonwin in.248 # import pywin.debugger249 pywin.debugger.brk()250 print("The DispatcherWin32dbg dispatcher is deprecated!")251 print("Please let me know if this is a problem.")252 print("Uncomment the relevant lines in dispatcher.py to re-enable")253 # DEBUGGER Note - You can either:254 # * Hit Run and wait for a (non Exception class) exception to occur!255 # * Set a breakpoint and hit run.256 # * Step into the object creation (a few steps away!)257 DispatcherBase.__init__(self, policyClass, ob)258 259 def _HandleException_(self):260 """Invoke the debugger post mortem capability"""261 # Save details away.262 typ, val, tb = exc_info()263 # import pywin.debugger, pywin.debugger.dbgcon264 debug = 0265 try:266 raise typ(val)267 except Exception: # AARG - What is this Exception???268 # Use some inside knowledge to borrow a Debugger option which dictates if we269 # stop at "expected" exceptions.270 debug = pywin.debugger.GetDebugger().get_option(271 pywin.debugger.dbgcon.OPT_STOP_EXCEPTIONS272 )273 except:274 debug = 1275 if debug:276 try:277 pywin.debugger.post_mortem(tb, typ, val) # The original exception278 except:279 traceback.print_exc()280 281 # But still raise it.282 del tb283 raise284 285 286try:287 import win32trace288 289 DefaultDebugDispatcher = DispatcherWin32trace290except ImportError: # no win32trace module - just use a print based one.291 DefaultDebugDispatcher = DispatcherTrace292 