Spaces:
Sleeping
Sleeping
File size: 8,600 Bytes
10865e1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
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)
|