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.

debug.py 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import os
  2. import sys
  3. import pythoncom
  4. import win32api
  5. import win32com.client.connect
  6. import win32com.server.util
  7. import winerror
  8. from win32com.axdebug import adb, axdebug, contexts, documents, gateways, stackframe
  9. from win32com.axdebug.codecontainer import SourceCodeContainer
  10. from win32com.axdebug.util import _wrap, _wrap_remove
  11. from win32com.client.util import Enumerator
  12. from win32com.server.exception import COMException
  13. from win32com.util import IIDToInterfaceName
  14. from .framework import trace
  15. try:
  16. os.environ["DEBUG_AXDEBUG"]
  17. debuggingTrace = 1 # Should we print "trace" output?
  18. except KeyError:
  19. debuggingTrace = 0
  20. def trace(*args):
  21. """A function used instead of "print" for debugging output."""
  22. if not debuggingTrace:
  23. return
  24. print(win32api.GetCurrentThreadId(), end=" ")
  25. for arg in args:
  26. print(arg, end=" ")
  27. print()
  28. # Note that the DebugManager is not a COM gateway class for the
  29. # debugger - but it does create and manage them.
  30. class DebugManager:
  31. _debugger_interfaces_ = [axdebug.IID_IActiveScriptDebug]
  32. def __init__(self, scriptEngine):
  33. self.scriptEngine = scriptEngine
  34. self.adb = adb.Debugger()
  35. self.rootNode = None
  36. self.debugApplication = None
  37. self.ccProvider = documents.CodeContainerProvider()
  38. try:
  39. self.scriptSiteDebug = scriptEngine.GetScriptSite(
  40. axdebug.IID_IActiveScriptSiteDebug
  41. )
  42. except pythoncom.com_error:
  43. # No debugger interface (ie, dumb host). Do the extra work.
  44. trace("Scripting site has no debugger interface")
  45. self.scriptSiteDebug = None
  46. # Get the debug application object.
  47. self.debugApplication = None
  48. if self.scriptSiteDebug is not None:
  49. # Spec says that we should test for this, and if it fails revert to
  50. # PDM application.
  51. try:
  52. self.debugApplication = self.scriptSiteDebug.GetApplication()
  53. self.rootNode = self.scriptSiteDebug.GetRootApplicationNode()
  54. except pythoncom.com_error:
  55. self.debugApplication = None
  56. if self.debugApplication is None:
  57. # Try to get/create the default one
  58. # NOTE - Dont catch exceptions here - let the parent do it,
  59. # so it knows debug support is available.
  60. pdm = pythoncom.CoCreateInstance(
  61. axdebug.CLSID_ProcessDebugManager,
  62. None,
  63. pythoncom.CLSCTX_ALL,
  64. axdebug.IID_IProcessDebugManager,
  65. )
  66. self.debugApplication = pdm.GetDefaultApplication()
  67. self.rootNode = self.debugApplication.GetRootNode()
  68. assert (
  69. self.debugApplication is not None
  70. ), "Need to have a DebugApplication object by now!"
  71. self.activeScriptDebug = None
  72. if self.debugApplication is not None:
  73. self.adb.AttachApp(self.debugApplication, self.ccProvider)
  74. self.codeContainers = {}
  75. self.activeScriptDebug = _wrap(
  76. ActiveScriptDebug(self, self.codeContainers), axdebug.IID_IActiveScriptDebug
  77. )
  78. def Close(self):
  79. # Called by the language engine when it receives a close request
  80. if self.activeScriptDebug is not None:
  81. _wrap_remove(self.activeScriptDebug)
  82. self.activeScriptDebug = None
  83. self.scriptEngine = None
  84. self.rootNode = None
  85. self.debugApplication = None
  86. self.scriptSiteDebug = None
  87. if self.ccProvider is not None:
  88. self.ccProvider.Close()
  89. self.ccProvider = None
  90. self.codeContainers = {}
  91. if self.adb:
  92. self.adb.CloseApp()
  93. self.adb = None
  94. # print "Close complete"
  95. def IsAnyHost(self):
  96. "Do we have _any_ debugging interfaces installed?"
  97. return self.debugApplication is not None
  98. def IsSimpleHost(self):
  99. return self.scriptSiteDebug is None
  100. def HandleRuntimeError(self):
  101. """Called by the engine when a runtime error occurs. If we have a debugger,
  102. we let it know.
  103. The result is a boolean which indicates if the error handler should call
  104. IActiveScriptSite::OnScriptError()
  105. """
  106. # if self.IsAnyHost:
  107. # site = _wrap(self, axdebug.IID_IActiveScriptSite)
  108. # breakResume, errorResume, fCallOnError = self.debugApplication(activeScriptErrorDebug, site)
  109. # Do something with these!
  110. # else:
  111. trace("HandleRuntimeError")
  112. fCallOnError = 1
  113. return fCallOnError
  114. def _query_interface_for_debugger_(self, iid):
  115. if iid in self._debugger_interfaces_:
  116. return self.activeScriptDebug
  117. trace("DebugManager QI - unknown IID", iid)
  118. return 0
  119. def OnEnterScript(self):
  120. trace("OnEnterScript")
  121. try:
  122. 1 / 0
  123. except:
  124. # Bit of a hack - reach into engine.
  125. baseFrame = sys.exc_info()[2].tb_frame.f_back
  126. self.adb.SetupAXDebugging(baseFrame)
  127. def OnLeaveScript(self):
  128. trace("OnLeaveScript")
  129. self.adb.ResetAXDebugging()
  130. def AddScriptBlock(self, codeBlock):
  131. # If we dont have debugging support, dont bother.
  132. cc = DebugCodeBlockContainer(codeBlock, self.scriptSiteDebug)
  133. if self.IsSimpleHost():
  134. document = documents.DebugDocumentText(cc)
  135. document = _wrap(document, axdebug.IID_IDebugDocument)
  136. provider = documents.DebugDocumentProvider(document)
  137. provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
  138. cc.debugDocument = document
  139. newNode = self.debugApplication.CreateApplicationNode()
  140. newNode.SetDocumentProvider(provider)
  141. newNode.Attach(self.rootNode)
  142. else:
  143. newNode = None # Managed by smart host.
  144. self.codeContainers[cc.sourceContext] = cc
  145. self.ccProvider.AddCodeContainer(cc, newNode)
  146. class DebugCodeBlockContainer(SourceCodeContainer):
  147. def __init__(self, codeBlock, site):
  148. self.codeBlock = codeBlock
  149. SourceCodeContainer.__init__(
  150. self,
  151. codeBlock.codeText,
  152. codeBlock.GetFileName(),
  153. codeBlock.sourceContextCookie,
  154. codeBlock.startLineNumber,
  155. site,
  156. )
  157. def GetName(self, dnt):
  158. if dnt == axdebug.DOCUMENTNAMETYPE_APPNODE:
  159. return self.codeBlock.GetDisplayName()
  160. elif dnt == axdebug.DOCUMENTNAMETYPE_TITLE:
  161. return self.codeBlock.GetDisplayName()
  162. # elif dnt==axdebug.DOCUMENTNAMETYPE_FILE_TAIL:
  163. # elif dnt==axdebug.DOCUMENTNAMETYPE_URL:
  164. else:
  165. raise COMException(scode=winerror.S_FALSE)
  166. class EnumDebugCodeContexts(gateways.EnumDebugCodeContexts):
  167. def _wrap(self, ob):
  168. return ob
  169. class ActiveScriptDebug:
  170. """The class which implements the IActiveScriptDebug interface for the Active Script engine.
  171. Only ever used by smart hosts.
  172. """
  173. _public_methods_ = [
  174. "GetScriptTextAttributes",
  175. "GetScriptletTextAttributes",
  176. "EnumCodeContextsOfPosition",
  177. ]
  178. _com_interfaces_ = [axdebug.IID_IActiveScriptDebug]
  179. def __init__(self, debugMgr, codeContainers):
  180. self.debugMgr = debugMgr
  181. self.scriptSiteDebug = debugMgr.scriptSiteDebug
  182. self.codeContainers = codeContainers
  183. def _Close(self):
  184. self.debugMgr = None
  185. self.scriptSiteDebug = None
  186. self.codeContainers = {}
  187. def _query_interface_(self, iid):
  188. trace("DebuggerQI with", iid)
  189. return _wrap(self.debugMgr.scriptEngine, iid)
  190. def GetScriptTextAttributes(self, code, delim, flags):
  191. container = SourceCodeContainer(code, "<Temp Code Block>")
  192. return container.GetSyntaxColorAttributes()
  193. def GetScriptletTextAttributes(self, code, delim, flags):
  194. trace("GetScriptletTextAttributes", code, delim, flags)
  195. container = SourceCodeContainer(code, "<Temp Code Block>")
  196. return container.GetSyntaxColorAttributes()
  197. def EnumCodeContextsOfPosition(self, context, charOffset, numChars):
  198. trace("EnumCodeContextsOfPosition", context, charOffset, numChars)
  199. try:
  200. context = self.codeContainers[context].GetCodeContextAtPosition(charOffset)
  201. except KeyError:
  202. raise COMException(scode=winerror.E_UNEXPECTED)
  203. enum = EnumDebugCodeContexts([context])
  204. return _wrap(enum, axdebug.IID_IEnumDebugCodeContexts)