Spaces:
				
			
			
	
			
			
		Sleeping
		
	
	
	
			
			
	
	
	
	
		
		
		Sleeping
		
	| 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) | |
