Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dispatcher.py 9.7KB

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