|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- import os
- import sys
-
- import pythoncom
- import win32api
- import win32com.client.connect
- import win32com.server.util
- import winerror
- from win32com.axdebug import adb, axdebug, contexts, documents, gateways, stackframe
- from win32com.axdebug.codecontainer import SourceCodeContainer
- from win32com.axdebug.util import _wrap, _wrap_remove
- from win32com.client.util import Enumerator
- from win32com.server.exception import COMException
- from win32com.util import IIDToInterfaceName
-
- from .framework import trace
-
- try:
- os.environ["DEBUG_AXDEBUG"]
- debuggingTrace = 1 # Should we print "trace" output?
- except KeyError:
- debuggingTrace = 0
-
-
- def trace(*args):
- """A function used instead of "print" for debugging output."""
- if not debuggingTrace:
- return
- print(win32api.GetCurrentThreadId(), end=" ")
- for arg in args:
- print(arg, end=" ")
- print()
-
-
- # Note that the DebugManager is not a COM gateway class for the
- # debugger - but it does create and manage them.
- class DebugManager:
- _debugger_interfaces_ = [axdebug.IID_IActiveScriptDebug]
-
- def __init__(self, scriptEngine):
- self.scriptEngine = scriptEngine
- self.adb = adb.Debugger()
- self.rootNode = None
- self.debugApplication = None
- self.ccProvider = documents.CodeContainerProvider()
- try:
- self.scriptSiteDebug = scriptEngine.GetScriptSite(
- axdebug.IID_IActiveScriptSiteDebug
- )
- except pythoncom.com_error:
- # No debugger interface (ie, dumb host). Do the extra work.
- trace("Scripting site has no debugger interface")
- self.scriptSiteDebug = None
- # Get the debug application object.
- self.debugApplication = None
- if self.scriptSiteDebug is not None:
- # Spec says that we should test for this, and if it fails revert to
- # PDM application.
- try:
- self.debugApplication = self.scriptSiteDebug.GetApplication()
- self.rootNode = self.scriptSiteDebug.GetRootApplicationNode()
- except pythoncom.com_error:
- self.debugApplication = None
-
- if self.debugApplication is None:
- # Try to get/create the default one
- # NOTE - Dont catch exceptions here - let the parent do it,
- # so it knows debug support is available.
- pdm = pythoncom.CoCreateInstance(
- axdebug.CLSID_ProcessDebugManager,
- None,
- pythoncom.CLSCTX_ALL,
- axdebug.IID_IProcessDebugManager,
- )
- self.debugApplication = pdm.GetDefaultApplication()
- self.rootNode = self.debugApplication.GetRootNode()
-
- assert (
- self.debugApplication is not None
- ), "Need to have a DebugApplication object by now!"
- self.activeScriptDebug = None
-
- if self.debugApplication is not None:
- self.adb.AttachApp(self.debugApplication, self.ccProvider)
- self.codeContainers = {}
- self.activeScriptDebug = _wrap(
- ActiveScriptDebug(self, self.codeContainers), axdebug.IID_IActiveScriptDebug
- )
-
- def Close(self):
- # Called by the language engine when it receives a close request
- if self.activeScriptDebug is not None:
- _wrap_remove(self.activeScriptDebug)
- self.activeScriptDebug = None
- self.scriptEngine = None
- self.rootNode = None
- self.debugApplication = None
- self.scriptSiteDebug = None
- if self.ccProvider is not None:
- self.ccProvider.Close()
- self.ccProvider = None
- self.codeContainers = {}
- if self.adb:
- self.adb.CloseApp()
- self.adb = None
-
- # print "Close complete"
-
- def IsAnyHost(self):
- "Do we have _any_ debugging interfaces installed?"
- return self.debugApplication is not None
-
- def IsSimpleHost(self):
- return self.scriptSiteDebug is None
-
- def HandleRuntimeError(self):
- """Called by the engine when a runtime error occurs. If we have a debugger,
- we let it know.
-
- The result is a boolean which indicates if the error handler should call
- IActiveScriptSite::OnScriptError()
- """
- # if self.IsAnyHost:
- # site = _wrap(self, axdebug.IID_IActiveScriptSite)
- # breakResume, errorResume, fCallOnError = self.debugApplication(activeScriptErrorDebug, site)
- # Do something with these!
- # else:
- trace("HandleRuntimeError")
- fCallOnError = 1
- return fCallOnError
-
- def _query_interface_for_debugger_(self, iid):
- if iid in self._debugger_interfaces_:
- return self.activeScriptDebug
- trace("DebugManager QI - unknown IID", iid)
- return 0
-
- def OnEnterScript(self):
- trace("OnEnterScript")
- try:
- 1 / 0
- except:
- # Bit of a hack - reach into engine.
- baseFrame = sys.exc_info()[2].tb_frame.f_back
- self.adb.SetupAXDebugging(baseFrame)
-
- def OnLeaveScript(self):
- trace("OnLeaveScript")
- self.adb.ResetAXDebugging()
-
- def AddScriptBlock(self, codeBlock):
- # If we dont have debugging support, dont bother.
- cc = DebugCodeBlockContainer(codeBlock, self.scriptSiteDebug)
- if self.IsSimpleHost():
- document = documents.DebugDocumentText(cc)
- document = _wrap(document, axdebug.IID_IDebugDocument)
- provider = documents.DebugDocumentProvider(document)
- provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
- cc.debugDocument = document
- newNode = self.debugApplication.CreateApplicationNode()
- newNode.SetDocumentProvider(provider)
- newNode.Attach(self.rootNode)
- else:
- newNode = None # Managed by smart host.
- self.codeContainers[cc.sourceContext] = cc
- self.ccProvider.AddCodeContainer(cc, newNode)
-
-
- class DebugCodeBlockContainer(SourceCodeContainer):
- def __init__(self, codeBlock, site):
- self.codeBlock = codeBlock
- SourceCodeContainer.__init__(
- self,
- codeBlock.codeText,
- codeBlock.GetFileName(),
- codeBlock.sourceContextCookie,
- codeBlock.startLineNumber,
- site,
- )
-
- def GetName(self, dnt):
- if dnt == axdebug.DOCUMENTNAMETYPE_APPNODE:
- return self.codeBlock.GetDisplayName()
- elif dnt == axdebug.DOCUMENTNAMETYPE_TITLE:
- return self.codeBlock.GetDisplayName()
- # elif dnt==axdebug.DOCUMENTNAMETYPE_FILE_TAIL:
- # elif dnt==axdebug.DOCUMENTNAMETYPE_URL:
- else:
- raise COMException(scode=winerror.S_FALSE)
-
-
- class EnumDebugCodeContexts(gateways.EnumDebugCodeContexts):
- def _wrap(self, ob):
- return ob
-
-
- class ActiveScriptDebug:
- """The class which implements the IActiveScriptDebug interface for the Active Script engine.
-
- Only ever used by smart hosts.
- """
-
- _public_methods_ = [
- "GetScriptTextAttributes",
- "GetScriptletTextAttributes",
- "EnumCodeContextsOfPosition",
- ]
- _com_interfaces_ = [axdebug.IID_IActiveScriptDebug]
-
- def __init__(self, debugMgr, codeContainers):
- self.debugMgr = debugMgr
- self.scriptSiteDebug = debugMgr.scriptSiteDebug
- self.codeContainers = codeContainers
-
- def _Close(self):
- self.debugMgr = None
- self.scriptSiteDebug = None
- self.codeContainers = {}
-
- def _query_interface_(self, iid):
- trace("DebuggerQI with", iid)
- return _wrap(self.debugMgr.scriptEngine, iid)
-
- def GetScriptTextAttributes(self, code, delim, flags):
- container = SourceCodeContainer(code, "<Temp Code Block>")
- return container.GetSyntaxColorAttributes()
-
- def GetScriptletTextAttributes(self, code, delim, flags):
- trace("GetScriptletTextAttributes", code, delim, flags)
- container = SourceCodeContainer(code, "<Temp Code Block>")
- return container.GetSyntaxColorAttributes()
-
- def EnumCodeContextsOfPosition(self, context, charOffset, numChars):
- trace("EnumCodeContextsOfPosition", context, charOffset, numChars)
- try:
- context = self.codeContainers[context].GetCodeContextAtPosition(charOffset)
- except KeyError:
- raise COMException(scode=winerror.E_UNEXPECTED)
- enum = EnumDebugCodeContexts([context])
- return _wrap(enum, axdebug.IID_IEnumDebugCodeContexts)
|