Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
3
venv/Lib/site-packages/win32comext/axdebug/__init__.py
Normal file
3
venv/Lib/site-packages/win32comext/axdebug/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
# See if we have a special directory for the binaries (for developers)
|
||||
import win32com
|
||||
win32com.__PackageSupportBuildPath__(__path__)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
416
venv/Lib/site-packages/win32comext/axdebug/adb.py
Normal file
416
venv/Lib/site-packages/win32comext/axdebug/adb.py
Normal file
|
@ -0,0 +1,416 @@
|
|||
"""The glue between the Python debugger interface and the Active Debugger interface
|
||||
"""
|
||||
from win32com.axdebug.util import trace, _wrap, _wrap_remove
|
||||
from win32com.server.util import unwrap
|
||||
import win32com.client.connect
|
||||
from . import gateways
|
||||
import sys, bdb, traceback
|
||||
from . import axdebug, stackframe
|
||||
import win32api, pythoncom
|
||||
import _thread, os
|
||||
|
||||
def fnull(*args):
|
||||
pass
|
||||
|
||||
try:
|
||||
os.environ["DEBUG_AXDEBUG"]
|
||||
debugging = 1
|
||||
except KeyError:
|
||||
debugging = 0
|
||||
|
||||
traceenter = fnull # trace enter of functions
|
||||
tracev = fnull # verbose trace
|
||||
|
||||
if debugging:
|
||||
traceenter = trace # trace enter of functions
|
||||
tracev = trace # verbose trace
|
||||
|
||||
class OutputReflector:
|
||||
def __init__(self, file, writefunc):
|
||||
self.writefunc = writefunc
|
||||
self.file = file
|
||||
def __getattr__(self,name):
|
||||
return getattr(self.file, name)
|
||||
def write(self,message):
|
||||
self.writefunc(message)
|
||||
self.file.write(message)
|
||||
|
||||
def _dumpf(frame):
|
||||
if frame is None:
|
||||
return "<None>"
|
||||
else:
|
||||
addn = "(with trace!)"
|
||||
if frame.f_trace is None:
|
||||
addn = " **No Trace Set **"
|
||||
return "Frame at %d, file %s, line: %d%s" % (id(frame), frame.f_code.co_filename, frame.f_lineno, addn)
|
||||
|
||||
g_adb = None
|
||||
|
||||
def OnSetBreakPoint(codeContext, breakPointState, lineNo):
|
||||
try:
|
||||
fileName = codeContext.codeContainer.GetFileName()
|
||||
# inject the code into linecache.
|
||||
import linecache
|
||||
linecache.cache[fileName] = 0, 0, codeContext.codeContainer.GetText(), fileName
|
||||
g_adb._OnSetBreakPoint(fileName, codeContext, breakPointState, lineNo+1)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
class Adb(bdb.Bdb,gateways.RemoteDebugApplicationEvents):
|
||||
def __init__(self):
|
||||
self.debugApplication = None
|
||||
self.debuggingThread = None
|
||||
self.debuggingThreadStateHandle = None
|
||||
self.stackSnifferCookie = self.stackSniffer = None
|
||||
self.codeContainerProvider = None
|
||||
self.debuggingThread = None
|
||||
self.breakFlags = None
|
||||
self.breakReason = None
|
||||
self.appDebugger = None
|
||||
self.appEventConnection = None
|
||||
self.logicalbotframe = None # Anything at this level or below does not exist!
|
||||
self.currentframe = None # The frame we are currently in.
|
||||
self.recursiveData = [] # Data saved for each reentery on this thread.
|
||||
bdb.Bdb.__init__(self)
|
||||
self._threadprotectlock = _thread.allocate_lock()
|
||||
self.reset()
|
||||
|
||||
def canonic(self, fname):
|
||||
if fname[0]=='<':
|
||||
return fname
|
||||
return bdb.Bdb.canonic(self, fname)
|
||||
|
||||
def reset(self):
|
||||
traceenter("adb.reset")
|
||||
bdb.Bdb.reset(self)
|
||||
|
||||
def __xxxxx__set_break(self, filename, lineno, cond = None):
|
||||
# As per standard one, except no linecache checking!
|
||||
if filename not in self.breaks:
|
||||
self.breaks[filename] = []
|
||||
list = self.breaks[filename]
|
||||
if lineno in list:
|
||||
return 'There is already a breakpoint there!'
|
||||
list.append(lineno)
|
||||
if cond is not None: self.cbreaks[filename, lineno]=cond
|
||||
|
||||
def stop_here(self, frame):
|
||||
traceenter("stop_here", _dumpf(frame), _dumpf(self.stopframe))
|
||||
# As per bdb.stop_here, except for logicalbotframe
|
||||
## if self.stopframe is None:
|
||||
## return 1
|
||||
if frame is self.stopframe:
|
||||
return 1
|
||||
|
||||
tracev("stop_here said 'No'!")
|
||||
return 0
|
||||
|
||||
def break_here(self, frame):
|
||||
traceenter("break_here", self.breakFlags, _dumpf(frame))
|
||||
self.breakReason = None
|
||||
if self.breakFlags==axdebug.APPBREAKFLAG_DEBUGGER_HALT:
|
||||
self.breakReason = axdebug.BREAKREASON_DEBUGGER_HALT
|
||||
elif self.breakFlags==axdebug.APPBREAKFLAG_DEBUGGER_BLOCK:
|
||||
self.breakReason = axdebug.BREAKREASON_DEBUGGER_BLOCK
|
||||
elif self.breakFlags==axdebug.APPBREAKFLAG_STEP:
|
||||
self.breakReason = axdebug.BREAKREASON_STEP
|
||||
else:
|
||||
print("Calling base 'break_here' with", self.breaks)
|
||||
if bdb.Bdb.break_here(self, frame):
|
||||
self.breakReason = axdebug.BREAKREASON_BREAKPOINT
|
||||
return self.breakReason is not None
|
||||
|
||||
def break_anywhere(self, frame):
|
||||
traceenter("break_anywhere", _dumpf(frame))
|
||||
if self.breakFlags==axdebug.APPBREAKFLAG_DEBUGGER_HALT:
|
||||
self.breakReason = axdebug.BREAKREASON_DEBUGGER_HALT
|
||||
return 1
|
||||
rc = bdb.Bdb.break_anywhere(self, frame)
|
||||
tracev("break_anywhere",_dumpf(frame),"returning",rc)
|
||||
return rc
|
||||
|
||||
def dispatch_return(self, frame, arg):
|
||||
traceenter("dispatch_return", _dumpf(frame), arg)
|
||||
if self.logicalbotframe is frame:
|
||||
# We dont want to debug parent frames.
|
||||
tracev("dispatch_return resetting sys.trace")
|
||||
sys.settrace(None)
|
||||
return
|
||||
# self.bSetTrace = 0
|
||||
self.currentframe = frame.f_back
|
||||
return bdb.Bdb.dispatch_return(self, frame, arg)
|
||||
|
||||
def dispatch_line(self, frame):
|
||||
traceenter("dispatch_line", _dumpf(frame), _dumpf(self.botframe))
|
||||
# trace("logbotframe is", _dumpf(self.logicalbotframe), "botframe is", self.botframe)
|
||||
if frame is self.logicalbotframe:
|
||||
trace("dispatch_line", _dumpf(frame), "for bottom frame returing tracer")
|
||||
# The next code executed in the frame above may be a builtin (eg, apply())
|
||||
# in which sys.trace needs to be set.
|
||||
sys.settrace(self.trace_dispatch)
|
||||
# And return the tracer incase we are about to execute Python code,
|
||||
# in which case sys tracer is ignored!
|
||||
return self.trace_dispatch
|
||||
|
||||
if self.codeContainerProvider.FromFileName(frame.f_code.co_filename) is None:
|
||||
trace("dispatch_line has no document for", _dumpf(frame), "- skipping trace!")
|
||||
return None
|
||||
self.currentframe = frame # So the stack sniffer knows our most recent, debuggable code.
|
||||
return bdb.Bdb.dispatch_line(self, frame)
|
||||
|
||||
def dispatch_call(self, frame, arg):
|
||||
traceenter("dispatch_call",_dumpf(frame))
|
||||
frame.f_locals['__axstack_address__'] = axdebug.GetStackAddress()
|
||||
if frame is self.botframe:
|
||||
trace("dispatch_call is self.botframe - returning tracer")
|
||||
return self.trace_dispatch
|
||||
# Not our bottom frame. If we have a document for it,
|
||||
# then trace it, otherwise run at full speed.
|
||||
if self.codeContainerProvider.FromFileName(frame.f_code.co_filename) is None:
|
||||
trace("dispatch_call has no document for", _dumpf(frame), "- skipping trace!")
|
||||
## sys.settrace(None)
|
||||
return None
|
||||
return self.trace_dispatch
|
||||
|
||||
# rc = bdb.Bdb.dispatch_call(self, frame, arg)
|
||||
# trace("dispatch_call", _dumpf(frame),"returned",rc)
|
||||
# return rc
|
||||
|
||||
def trace_dispatch(self, frame, event, arg):
|
||||
traceenter("trace_dispatch", _dumpf(frame), event, arg)
|
||||
if self.debugApplication is None:
|
||||
trace("trace_dispatch has no application!")
|
||||
return # None
|
||||
return bdb.Bdb.trace_dispatch(self, frame, event, arg)
|
||||
|
||||
|
||||
#
|
||||
# The user functions do bugger all!
|
||||
#
|
||||
# def user_call(self, frame, argument_list):
|
||||
# traceenter("user_call",_dumpf(frame))
|
||||
|
||||
def user_line(self, frame):
|
||||
traceenter("user_line",_dumpf(frame))
|
||||
# Traces at line zero
|
||||
if frame.f_lineno!=0:
|
||||
breakReason = self.breakReason
|
||||
if breakReason is None:
|
||||
breakReason = axdebug.BREAKREASON_STEP
|
||||
self._HandleBreakPoint(frame, None, breakReason)
|
||||
|
||||
def user_return(self, frame, return_value):
|
||||
# traceenter("user_return",_dumpf(frame),return_value)
|
||||
bdb.Bdb.user_return(self, frame, return_value)
|
||||
|
||||
def user_exception(self, frame, exc_info):
|
||||
# traceenter("user_exception")
|
||||
bdb.Bdb.user_exception(self, frame, exc_info)
|
||||
|
||||
|
||||
def _HandleBreakPoint(self, frame, tb, reason):
|
||||
traceenter("Calling HandleBreakPoint with reason", reason,"at frame", _dumpf(frame))
|
||||
traceenter(" Current frame is", _dumpf(self.currentframe))
|
||||
try:
|
||||
resumeAction = self.debugApplication.HandleBreakPoint(reason)
|
||||
tracev("HandleBreakPoint returned with ", resumeAction)
|
||||
except pythoncom.com_error as details:
|
||||
# Eeek - the debugger is dead, or something serious is happening.
|
||||
# Assume we should continue
|
||||
resumeAction = axdebug.BREAKRESUMEACTION_CONTINUE
|
||||
trace("HandleBreakPoint FAILED with", details)
|
||||
|
||||
self.stack = []
|
||||
self.curindex = 0
|
||||
if resumeAction == axdebug.BREAKRESUMEACTION_ABORT:
|
||||
self.set_quit()
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_CONTINUE:
|
||||
tracev("resume action is continue")
|
||||
self.set_continue()
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_STEP_INTO:
|
||||
tracev("resume action is step")
|
||||
self.set_step()
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_STEP_OVER:
|
||||
tracev("resume action is next")
|
||||
self.set_next(frame)
|
||||
elif resumeAction == axdebug.BREAKRESUMEACTION_STEP_OUT:
|
||||
tracev("resume action is stop out")
|
||||
self.set_return(frame)
|
||||
else:
|
||||
raise ValueError("unknown resume action flags")
|
||||
self.breakReason = None
|
||||
|
||||
def set_trace(self):
|
||||
self.breakReason = axdebug.BREAKREASON_LANGUAGE_INITIATED
|
||||
bdb.Bdb.set_trace(self)
|
||||
|
||||
def CloseApp(self):
|
||||
traceenter("ClosingApp")
|
||||
self.reset()
|
||||
self.logicalbotframe = None
|
||||
if self.stackSnifferCookie is not None:
|
||||
try:
|
||||
self.debugApplication.RemoveStackFrameSniffer(self.stackSnifferCookie)
|
||||
|
||||
except pythoncom.com_error:
|
||||
trace("*** Could not RemoveStackFrameSniffer %d" % (self.stackSnifferCookie))
|
||||
if self.stackSniffer:
|
||||
_wrap_remove(self.stackSniffer)
|
||||
self.stackSnifferCookie = self.stackSniffer = None
|
||||
|
||||
if self.appEventConnection is not None:
|
||||
self.appEventConnection.Disconnect()
|
||||
self.appEventConnection = None
|
||||
self.debugApplication = None
|
||||
self.appDebugger = None
|
||||
if self.codeContainerProvider is not None:
|
||||
self.codeContainerProvider.Close()
|
||||
self.codeContainerProvider = None
|
||||
|
||||
def AttachApp(self, debugApplication, codeContainerProvider):
|
||||
# traceenter("AttachApp", debugApplication, codeContainerProvider)
|
||||
self.codeContainerProvider = codeContainerProvider
|
||||
self.debugApplication = debugApplication
|
||||
self.stackSniffer = _wrap(stackframe.DebugStackFrameSniffer(self), axdebug.IID_IDebugStackFrameSniffer)
|
||||
self.stackSnifferCookie = debugApplication.AddStackFrameSniffer(self.stackSniffer)
|
||||
# trace("StackFrameSniffer added (%d)" % self.stackSnifferCookie)
|
||||
|
||||
# Connect to the application events.
|
||||
self.appEventConnection = win32com.client.connect.SimpleConnection(self.debugApplication, self, axdebug.IID_IRemoteDebugApplicationEvents)
|
||||
|
||||
def ResetAXDebugging(self):
|
||||
traceenter("ResetAXDebugging", self, "with refcount", len(self.recursiveData))
|
||||
if win32api.GetCurrentThreadId()!=self.debuggingThread:
|
||||
trace("ResetAXDebugging called on other thread")
|
||||
return
|
||||
|
||||
if len(self.recursiveData)==0:
|
||||
# print "ResetAXDebugging called for final time."
|
||||
self.logicalbotframe = None
|
||||
self.debuggingThread = None
|
||||
self.currentframe = None
|
||||
self.debuggingThreadStateHandle = None
|
||||
return
|
||||
|
||||
self.logbotframe, self.stopframe, self.currentframe, self.debuggingThreadStateHandle = self.recursiveData[0]
|
||||
self.recursiveData = self.recursiveData[1:]
|
||||
|
||||
def SetupAXDebugging(self, baseFrame = None, userFrame = None):
|
||||
"""Get ready for potential debugging. Must be called on the thread
|
||||
that is being debugged.
|
||||
"""
|
||||
# userFrame is for non AXScript debugging. This is the first frame of the
|
||||
# users code.
|
||||
if userFrame is None:
|
||||
userFrame = baseFrame
|
||||
else:
|
||||
# We have missed the "dispatch_call" function, so set this up now!
|
||||
userFrame.f_locals['__axstack_address__'] = axdebug.GetStackAddress()
|
||||
|
||||
traceenter("SetupAXDebugging", self)
|
||||
self._threadprotectlock.acquire()
|
||||
try:
|
||||
thisThread = win32api.GetCurrentThreadId()
|
||||
if self.debuggingThread is None:
|
||||
self.debuggingThread = thisThread
|
||||
else:
|
||||
if self.debuggingThread!=thisThread:
|
||||
trace("SetupAXDebugging called on other thread - ignored!")
|
||||
return
|
||||
# push our context.
|
||||
self.recursiveData.insert(0, (self.logicalbotframe,self.stopframe, self.currentframe,self.debuggingThreadStateHandle))
|
||||
finally:
|
||||
self._threadprotectlock.release()
|
||||
|
||||
trace("SetupAXDebugging has base frame as", _dumpf(baseFrame))
|
||||
self.botframe = baseFrame
|
||||
self.stopframe = userFrame
|
||||
self.logicalbotframe = baseFrame
|
||||
self.currentframe = None
|
||||
self.debuggingThreadStateHandle = axdebug.GetThreadStateHandle()
|
||||
|
||||
self._BreakFlagsChanged()
|
||||
|
||||
# RemoteDebugApplicationEvents
|
||||
def OnConnectDebugger(self, appDebugger):
|
||||
traceenter("OnConnectDebugger", appDebugger)
|
||||
self.appDebugger = appDebugger
|
||||
# Reflect output to appDebugger
|
||||
writefunc = lambda s: appDebugger.onDebugOutput(s)
|
||||
sys.stdout = OutputReflector(sys.stdout, writefunc)
|
||||
sys.stderr = OutputReflector(sys.stderr, writefunc)
|
||||
|
||||
def OnDisconnectDebugger(self):
|
||||
traceenter("OnDisconnectDebugger")
|
||||
# Stop reflecting output
|
||||
if isinstance(sys.stdout, OutputReflector):
|
||||
sys.stdout = sys.stdout.file
|
||||
if isinstance(sys.stderr, OutputReflector):
|
||||
sys.stderr = sys.stderr.file
|
||||
self.appDebugger = None
|
||||
self.set_quit()
|
||||
|
||||
def OnSetName(self, name):
|
||||
traceenter("OnSetName", name)
|
||||
def OnDebugOutput(self, string):
|
||||
traceenter("OnDebugOutput", string)
|
||||
def OnClose(self):
|
||||
traceenter("OnClose")
|
||||
def OnEnterBreakPoint(self, rdat):
|
||||
traceenter("OnEnterBreakPoint", rdat)
|
||||
def OnLeaveBreakPoint(self, rdat):
|
||||
traceenter("OnLeaveBreakPoint", rdat)
|
||||
def OnCreateThread(self, rdat):
|
||||
traceenter("OnCreateThread", rdat)
|
||||
def OnDestroyThread(self, rdat):
|
||||
traceenter("OnDestroyThread", rdat)
|
||||
def OnBreakFlagChange(self, abf, rdat):
|
||||
traceenter("Debugger OnBreakFlagChange", abf, rdat)
|
||||
self.breakFlags = abf
|
||||
self._BreakFlagsChanged()
|
||||
|
||||
def _BreakFlagsChanged(self):
|
||||
traceenter("_BreakFlagsChanged to %s with our thread = %s, and debugging thread = %s" % (self.breakFlags, self.debuggingThread, win32api.GetCurrentThreadId()))
|
||||
trace("_BreakFlagsChanged has breaks", self.breaks)
|
||||
# If a request comes on our debugging thread, then do it now!
|
||||
# if self.debuggingThread!=win32api.GetCurrentThreadId():
|
||||
# return
|
||||
|
||||
if len(self.breaks) or self.breakFlags:
|
||||
|
||||
if self.logicalbotframe:
|
||||
trace("BreakFlagsChange with bot frame", _dumpf(self.logicalbotframe))
|
||||
# We have frames not to be debugged (eg, Scripting engine frames
|
||||
# (sys.settrace will be set when out logicalbotframe is hit -
|
||||
# this may not be the right thing to do, as it may not cause the
|
||||
# immediate break we desire.)
|
||||
self.logicalbotframe.f_trace = self.trace_dispatch
|
||||
else:
|
||||
trace("BreakFlagsChanged, but no bottom frame")
|
||||
if self.stopframe is not None:
|
||||
self.stopframe.f_trace = self.trace_dispatch
|
||||
# If we have the thread-state for the thread being debugged, then
|
||||
# we dynamically set its trace function - it is possible that the thread
|
||||
# being debugged is in a blocked call (eg, a message box) and we
|
||||
# want to hit the debugger the instant we return
|
||||
if self.debuggingThreadStateHandle is not None and \
|
||||
self.breakFlags and \
|
||||
self.debuggingThread != win32api.GetCurrentThreadId():
|
||||
axdebug.SetThreadStateTrace(self.debuggingThreadStateHandle, self.trace_dispatch)
|
||||
def _OnSetBreakPoint(self, key, codeContext, bps, lineNo):
|
||||
traceenter("_OnSetBreakPoint", self, key, codeContext, bps, lineNo)
|
||||
if bps==axdebug.BREAKPOINT_ENABLED:
|
||||
problem = self.set_break(key, lineNo)
|
||||
if problem:
|
||||
print("*** set_break failed -", problem)
|
||||
trace("_OnSetBreakPoint just set BP and has breaks", self.breaks)
|
||||
else:
|
||||
self.clear_break(key, lineNo)
|
||||
self._BreakFlagsChanged()
|
||||
trace("_OnSetBreakPoint leaving with breaks", self.breaks)
|
||||
|
||||
def Debugger():
|
||||
global g_adb
|
||||
if g_adb is None:
|
||||
g_adb = Adb()
|
||||
return g_adb
|
BIN
venv/Lib/site-packages/win32comext/axdebug/axdebug.pyd
Normal file
BIN
venv/Lib/site-packages/win32comext/axdebug/axdebug.pyd
Normal file
Binary file not shown.
254
venv/Lib/site-packages/win32comext/axdebug/codecontainer.py
Normal file
254
venv/Lib/site-packages/win32comext/axdebug/codecontainer.py
Normal file
|
@ -0,0 +1,254 @@
|
|||
"""A utility class for a code container.
|
||||
|
||||
A code container is a class which holds source code for a debugger. It knows how
|
||||
to color the text, and also how to translate lines into offsets, and back.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from win32com.axdebug import axdebug
|
||||
import tokenize
|
||||
from .util import RaiseNotImpl, _wrap
|
||||
|
||||
from win32com.server.exception import Exception
|
||||
import win32api, winerror
|
||||
from . import contexts
|
||||
|
||||
_keywords = {} # set of Python keywords
|
||||
for name in """
|
||||
and assert break class continue def del elif else except exec
|
||||
finally for from global if import in is lambda not
|
||||
or pass print raise return try while
|
||||
""".split():
|
||||
_keywords[name] = 1
|
||||
|
||||
class SourceCodeContainer:
|
||||
def __init__(self, text, fileName = "<Remove Me!>", sourceContext = 0, startLineNumber = 0, site = None, debugDocument = None):
|
||||
self.sourceContext = sourceContext # The source context added by a smart host.
|
||||
self.text = text
|
||||
if text:
|
||||
self._buildlines()
|
||||
self.nextLineNo = 0
|
||||
self.fileName = fileName
|
||||
self.codeContexts = {}
|
||||
self.site = site
|
||||
self.startLineNumber = startLineNumber
|
||||
self.debugDocument = None
|
||||
def _Close(self):
|
||||
self.text = self.lines = self.lineOffsets = None
|
||||
self.codeContexts = None
|
||||
self.debugDocument = None
|
||||
self.site = None
|
||||
self.sourceContext = None
|
||||
|
||||
def GetText(self):
|
||||
return self.text
|
||||
def GetName(self, dnt):
|
||||
assert 0, "You must subclass this"
|
||||
def GetFileName(self):
|
||||
return self.fileName
|
||||
|
||||
def GetPositionOfLine(self, cLineNumber):
|
||||
self.GetText() # Prime us.
|
||||
try:
|
||||
return self.lineOffsets[cLineNumber]
|
||||
except IndexError:
|
||||
raise Exception(scode=winerror.S_FALSE)
|
||||
def GetLineOfPosition(self, charPos):
|
||||
self.GetText() # Prime us.
|
||||
lastOffset = 0
|
||||
lineNo = 0
|
||||
for lineOffset in self.lineOffsets[1:]:
|
||||
if lineOffset > charPos:
|
||||
break
|
||||
lastOffset = lineOffset
|
||||
lineNo = lineNo + 1
|
||||
else: # for not broken.
|
||||
# print "Cant find", charPos, "in", self.lineOffsets
|
||||
raise Exception(scode=winerror.S_FALSE)
|
||||
# print "GLOP ret=",lineNo, (charPos-lastOffset)
|
||||
return lineNo, (charPos-lastOffset)
|
||||
|
||||
def GetNextLine(self):
|
||||
if self.nextLineNo>=len(self.lines):
|
||||
self.nextLineNo = 0 # auto-reset.
|
||||
return ""
|
||||
rc = self.lines[self.nextLineNo]
|
||||
self.nextLineNo = self.nextLineNo + 1
|
||||
return rc
|
||||
|
||||
def GetLine(self, num):
|
||||
self.GetText() # Prime us.
|
||||
return self.lines[num]
|
||||
|
||||
def GetNumChars(self):
|
||||
return len(self.GetText())
|
||||
|
||||
def GetNumLines(self):
|
||||
self.GetText() # Prime us.
|
||||
return len(self.lines)
|
||||
|
||||
def _buildline(self, pos):
|
||||
i = self.text.find('\n', pos)
|
||||
if i < 0:
|
||||
newpos = len(self.text)
|
||||
else:
|
||||
newpos = i+1
|
||||
r = self.text[pos:newpos]
|
||||
return r, newpos
|
||||
|
||||
def _buildlines(self):
|
||||
self.lines = []
|
||||
self.lineOffsets = [0]
|
||||
line, pos = self._buildline(0)
|
||||
while line:
|
||||
self.lines.append(line)
|
||||
self.lineOffsets.append(pos)
|
||||
line, pos = self._buildline(pos)
|
||||
|
||||
def _ProcessToken(self, type, token, spos, epos, line):
|
||||
srow, scol = spos
|
||||
erow, ecol = epos
|
||||
self.GetText() # Prime us.
|
||||
linenum = srow - 1 # Lines zero based for us too.
|
||||
realCharPos = self.lineOffsets[linenum] + scol
|
||||
numskipped = realCharPos - self.lastPos
|
||||
if numskipped==0:
|
||||
pass
|
||||
elif numskipped==1:
|
||||
self.attrs.append(axdebug.SOURCETEXT_ATTR_COMMENT)
|
||||
else:
|
||||
self.attrs.append((axdebug.SOURCETEXT_ATTR_COMMENT, numskipped))
|
||||
kwSize = len(token)
|
||||
self.lastPos = realCharPos + kwSize
|
||||
attr = 0
|
||||
|
||||
if type==tokenize.NAME:
|
||||
if token in _keywords:
|
||||
attr = axdebug.SOURCETEXT_ATTR_KEYWORD
|
||||
elif type==tokenize.STRING:
|
||||
attr = axdebug.SOURCETEXT_ATTR_STRING
|
||||
elif type==tokenize.NUMBER:
|
||||
attr = axdebug.SOURCETEXT_ATTR_NUMBER
|
||||
elif type==tokenize.OP:
|
||||
attr = axdebug.SOURCETEXT_ATTR_OPERATOR
|
||||
elif type==tokenize.COMMENT:
|
||||
attr = axdebug.SOURCETEXT_ATTR_COMMENT
|
||||
# else attr remains zero...
|
||||
if kwSize==0:
|
||||
pass
|
||||
elif kwSize==1:
|
||||
self.attrs.append(attr)
|
||||
else:
|
||||
self.attrs.append((attr, kwSize))
|
||||
|
||||
def GetSyntaxColorAttributes(self):
|
||||
self.lastPos = 0
|
||||
self.attrs = []
|
||||
try:
|
||||
tokenize.tokenize(self.GetNextLine, self._ProcessToken)
|
||||
except tokenize.TokenError:
|
||||
pass # Ignore - will cause all subsequent text to be commented.
|
||||
numAtEnd = len(self.GetText()) - self.lastPos
|
||||
if numAtEnd:
|
||||
self.attrs.append((axdebug.SOURCETEXT_ATTR_COMMENT, numAtEnd))
|
||||
return self.attrs
|
||||
|
||||
# We also provide and manage DebugDocumentContext objects
|
||||
def _MakeDebugCodeContext(self, lineNo, charPos, len):
|
||||
return _wrap(contexts.DebugCodeContext(lineNo, charPos, len, self, self.site), axdebug.IID_IDebugCodeContext)
|
||||
# Make a context at the given position. It should take up the entire context.
|
||||
def _MakeContextAtPosition(self, charPos):
|
||||
lineNo, offset = self.GetLineOfPosition(charPos)
|
||||
try:
|
||||
endPos = self.GetPositionOfLine(lineNo+1)
|
||||
except:
|
||||
endPos = charPos
|
||||
codecontext = self._MakeDebugCodeContext(lineNo, charPos, endPos-charPos)
|
||||
return codecontext
|
||||
|
||||
# Returns a DebugCodeContext. debugDocument can be None for smart hosts.
|
||||
def GetCodeContextAtPosition(self, charPos):
|
||||
# trace("GetContextOfPos", charPos, maxChars)
|
||||
# Convert to line number.
|
||||
lineNo, offset = self.GetLineOfPosition(charPos)
|
||||
charPos = self.GetPositionOfLine(lineNo)
|
||||
try:
|
||||
cc = self.codeContexts[charPos]
|
||||
# trace(" GetContextOfPos using existing")
|
||||
except KeyError:
|
||||
cc = self._MakeContextAtPosition(charPos)
|
||||
self.codeContexts[charPos] = cc
|
||||
return cc
|
||||
|
||||
class SourceModuleContainer(SourceCodeContainer):
|
||||
def __init__(self, module):
|
||||
self.module = module
|
||||
if hasattr(module, '__file__'):
|
||||
fname = self.module.__file__
|
||||
# Check for .pyc or .pyo or even .pys!
|
||||
if fname[-1] in ['O','o','C','c', 'S', 's']: fname = fname[:-1]
|
||||
try:
|
||||
fname = win32api.GetFullPathName(fname)
|
||||
except win32api.error:
|
||||
pass
|
||||
else:
|
||||
if module.__name__=='__main__' and len(sys.argv)>0:
|
||||
fname = sys.argv[0]
|
||||
else:
|
||||
fname = "<Unknown!>"
|
||||
SourceCodeContainer.__init__(self, None, fname)
|
||||
|
||||
def GetText(self):
|
||||
if self.text is None:
|
||||
fname = self.GetFileName()
|
||||
if fname:
|
||||
try:
|
||||
self.text = open(fname, "r").read()
|
||||
except IOError as details:
|
||||
self.text = "# Exception opening file\n# %s" % (repr(details))
|
||||
else:
|
||||
self.text = "# No file available for module '%s'" % (self.module)
|
||||
self._buildlines()
|
||||
return self.text
|
||||
|
||||
def GetName(self, dnt):
|
||||
name = self.module.__name__
|
||||
try:
|
||||
fname = win32api.GetFullPathName(self.module.__file__)
|
||||
except win32api.error:
|
||||
fname = self.module.__file__
|
||||
except AttributeError:
|
||||
fname = name
|
||||
if dnt==axdebug.DOCUMENTNAMETYPE_APPNODE:
|
||||
return name.split(".")[-1]
|
||||
elif dnt==axdebug.DOCUMENTNAMETYPE_TITLE:
|
||||
return fname
|
||||
elif dnt==axdebug.DOCUMENTNAMETYPE_FILE_TAIL:
|
||||
return os.path.split(fname)[1]
|
||||
elif dnt==axdebug.DOCUMENTNAMETYPE_URL:
|
||||
return "file:%s" % fname
|
||||
else:
|
||||
raise Exception(scode=winerror.E_UNEXPECTED)
|
||||
|
||||
if __name__=='__main__':
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
import ttest
|
||||
sc = SourceModuleContainer(ttest)
|
||||
# sc = SourceCodeContainer(open(sys.argv[1], "rb").read(), sys.argv[1])
|
||||
attrs = sc.GetSyntaxColorAttributes()
|
||||
attrlen = 0
|
||||
for attr in attrs:
|
||||
if type(attr)==type(()):
|
||||
attrlen = attrlen + attr[1]
|
||||
else:
|
||||
attrlen = attrlen + 1
|
||||
text = sc.GetText()
|
||||
if attrlen!=len(text):
|
||||
print("Lengths dont match!!! (%d/%d)" % (attrlen, len(text)))
|
||||
|
||||
# print "Attributes:"
|
||||
# print attrs
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(0))
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(4))
|
||||
print("GetLineOfPos=", sc.GetLineOfPosition(10))
|
56
venv/Lib/site-packages/win32comext/axdebug/contexts.py
Normal file
56
venv/Lib/site-packages/win32comext/axdebug/contexts.py
Normal file
|
@ -0,0 +1,56 @@
|
|||
""" A module for managing the AXDebug I*Contexts
|
||||
|
||||
"""
|
||||
from . import gateways, axdebug
|
||||
import pythoncom, win32com.server.util
|
||||
|
||||
# Utility function for wrapping object created by this module.
|
||||
from .util import _wrap, _wrap_remove, trace
|
||||
from . import adb
|
||||
|
||||
class DebugCodeContext(gateways.DebugCodeContext, gateways.DebugDocumentContext):
|
||||
# NOTE: We also implement the IDebugDocumentContext interface for Simple Hosts.
|
||||
# Thus, debugDocument may be NULL when we have smart hosts - but in that case, we
|
||||
# wont be called upon to provide it.
|
||||
_public_methods_ = gateways.DebugCodeContext._public_methods_ + \
|
||||
gateways.DebugDocumentContext._public_methods_
|
||||
_com_interfaces_ = gateways.DebugCodeContext._com_interfaces_ + \
|
||||
gateways.DebugDocumentContext._com_interfaces_
|
||||
|
||||
def __init__(self, lineNo, charPos, len, codeContainer, debugSite):
|
||||
self.debugSite = debugSite
|
||||
self.offset = charPos
|
||||
self.length = len
|
||||
self.breakPointState = 0
|
||||
self.lineno = lineNo
|
||||
gateways.DebugCodeContext.__init__(self)
|
||||
self.codeContainer = codeContainer
|
||||
|
||||
def _Close(self):
|
||||
self.debugSite = None
|
||||
|
||||
def GetDocumentContext(self):
|
||||
if self.debugSite is not None:
|
||||
# We have a smart host - let him give it to us.
|
||||
return self.debugSite.GetDocumentContextFromPosition(
|
||||
self.codeContainer.sourceContext,
|
||||
self.offset,
|
||||
self.length)
|
||||
else:
|
||||
# Simple host - Fine - Ill do it myself!
|
||||
return _wrap(self, axdebug.IID_IDebugDocumentContext)
|
||||
|
||||
def SetBreakPoint(self, bps):
|
||||
self.breakPointState = bps
|
||||
adb.OnSetBreakPoint(self, bps, self.lineno)
|
||||
|
||||
# The DebugDocumentContext methods for simple hosts.
|
||||
def GetDocument(self):
|
||||
return self.codeContainer.debugDocument
|
||||
|
||||
def EnumCodeContexts(self):
|
||||
return _wrap(EnumDebugCodeContexts([self]), axdebug.IID_IEnumDebugCodeContexts)
|
||||
|
||||
class EnumDebugCodeContexts(gateways.EnumDebugCodeContexts):
|
||||
def _wrap(self, obj):
|
||||
return _wrap(obj, axdebug.IID_IDebugCodeContext)
|
203
venv/Lib/site-packages/win32comext/axdebug/debugger.py
Normal file
203
venv/Lib/site-packages/win32comext/axdebug/debugger.py
Normal file
|
@ -0,0 +1,203 @@
|
|||
import sys, traceback, string
|
||||
|
||||
from win32com.axscript import axscript
|
||||
from win32com.axdebug import codecontainer, axdebug, gateways, documents, contexts, adb, expressions
|
||||
from win32com.axdebug.util import trace, _wrap, _wrap_remove
|
||||
|
||||
import pythoncom
|
||||
import win32api, winerror
|
||||
import os
|
||||
|
||||
currentDebugger = None
|
||||
|
||||
class ModuleTreeNode:
|
||||
"""Helper class for building a module tree
|
||||
"""
|
||||
def __init__(self, module):
|
||||
modName = module.__name__
|
||||
self.moduleName = modName
|
||||
self.module = module
|
||||
self.realNode = None
|
||||
self.cont = codecontainer.SourceModuleContainer(module)
|
||||
def __repr__(self):
|
||||
return "<ModuleTreeNode wrapping %s>" % (self.module)
|
||||
def Attach(self, parentRealNode):
|
||||
self.realNode.Attach(parentRealNode)
|
||||
|
||||
def Close(self):
|
||||
self.module = None
|
||||
self.cont = None
|
||||
self.realNode = None
|
||||
|
||||
def BuildModule(module, built_nodes, rootNode, create_node_fn, create_node_args ):
|
||||
if module:
|
||||
keep = module.__name__
|
||||
keep = keep and (built_nodes.get(module) is None)
|
||||
if keep and hasattr(module, '__file__'):
|
||||
keep = string.lower(os.path.splitext(module.__file__)[1]) not in [".pyd", ".dll"]
|
||||
# keep = keep and module.__name__=='__main__'
|
||||
if module and keep:
|
||||
# print "keeping", module.__name__
|
||||
node = ModuleTreeNode(module)
|
||||
built_nodes[module] = node
|
||||
realNode = create_node_fn(*(node,)+create_node_args)
|
||||
node.realNode = realNode
|
||||
|
||||
# Split into parent nodes.
|
||||
parts = string.split(module.__name__, '.')
|
||||
if parts[-1][:8]=='__init__': parts = parts[:-1]
|
||||
parent = string.join(parts[:-1], '.')
|
||||
parentNode = rootNode
|
||||
if parent:
|
||||
parentModule = sys.modules[parent]
|
||||
BuildModule(parentModule, built_nodes, rootNode, create_node_fn, create_node_args)
|
||||
if parentModule in built_nodes:
|
||||
parentNode = built_nodes[parentModule].realNode
|
||||
node.Attach(parentNode)
|
||||
|
||||
def RefreshAllModules(builtItems, rootNode, create_node, create_node_args):
|
||||
for module in list(sys.modules.values()):
|
||||
BuildModule(module, builtItems, rootNode, create_node, create_node_args)
|
||||
|
||||
# realNode = pdm.CreateDebugDocumentHelper(None) # DebugDocumentHelper node?
|
||||
# app.CreateApplicationNode() # doc provider node.
|
||||
|
||||
class CodeContainerProvider(documents.CodeContainerProvider):
|
||||
def __init__(self, axdebugger):
|
||||
self.axdebugger = axdebugger
|
||||
documents.CodeContainerProvider.__init__(self)
|
||||
self.currentNumModules = len(sys.modules)
|
||||
self.nodes = {}
|
||||
self.axdebugger.RefreshAllModules(self.nodes, self)
|
||||
|
||||
def FromFileName(self, fname):
|
||||
### It appears we cant add modules during a debug session!
|
||||
# if self.currentNumModules != len(sys.modules):
|
||||
# self.axdebugger.RefreshAllModules(self.nodes, self)
|
||||
# self.currentNumModules = len(sys.modules)
|
||||
# for key in self.ccsAndNodes.keys():
|
||||
# print "File:", key
|
||||
return documents.CodeContainerProvider.FromFileName(self, fname)
|
||||
|
||||
def Close(self):
|
||||
documents.CodeContainerProvider.Close(self)
|
||||
self.axdebugger = None
|
||||
print("Closing %d nodes" % (len(self.nodes)))
|
||||
for node in self.nodes.values():
|
||||
node.Close()
|
||||
self.nodes = {}
|
||||
|
||||
class OriginalInterfaceMaker:
|
||||
def MakeInterfaces(self, pdm):
|
||||
app = self.pdm.CreateApplication()
|
||||
self.cookie = pdm.AddApplication(app)
|
||||
root = app.GetRootNode()
|
||||
return app, root
|
||||
|
||||
def CloseInterfaces(self, pdm):
|
||||
pdm.RemoveApplication(self.cookie)
|
||||
|
||||
class SimpleHostStyleInterfaceMaker:
|
||||
def MakeInterfaces(self, pdm):
|
||||
app = pdm.GetDefaultApplication()
|
||||
root = app.GetRootNode()
|
||||
return app, root
|
||||
|
||||
def CloseInterfaces(self, pdm):
|
||||
pass
|
||||
|
||||
|
||||
class AXDebugger:
|
||||
def __init__(self, interfaceMaker = None, processName = None):
|
||||
if processName is None: processName = "Python Process"
|
||||
if interfaceMaker is None: interfaceMaker = SimpleHostStyleInterfaceMaker()
|
||||
|
||||
self.pydebugger = adb.Debugger()
|
||||
|
||||
self.pdm=pythoncom.CoCreateInstance(axdebug.CLSID_ProcessDebugManager,None,pythoncom.CLSCTX_ALL, axdebug.IID_IProcessDebugManager)
|
||||
|
||||
self.app, self.root = interfaceMaker.MakeInterfaces(self.pdm)
|
||||
self.app.SetName(processName)
|
||||
self.interfaceMaker = interfaceMaker
|
||||
|
||||
expressionProvider = _wrap(expressions.ProvideExpressionContexts(), axdebug.IID_IProvideExpressionContexts)
|
||||
self.expressionCookie = self.app.AddGlobalExpressionContextProvider(expressionProvider)
|
||||
|
||||
contProvider = CodeContainerProvider(self)
|
||||
self.pydebugger.AttachApp(self.app, contProvider)
|
||||
|
||||
def Break(self):
|
||||
# Get the frame we start debugging from - this is the frame 1 level up
|
||||
try:
|
||||
1 + ''
|
||||
except:
|
||||
frame = sys.exc_info()[2].tb_frame.f_back
|
||||
|
||||
# Get/create the debugger, and tell it to break.
|
||||
self.app.StartDebugSession()
|
||||
# self.app.CauseBreak()
|
||||
|
||||
self.pydebugger.SetupAXDebugging(None, frame)
|
||||
self.pydebugger.set_trace()
|
||||
|
||||
def Close(self):
|
||||
self.pydebugger.ResetAXDebugging()
|
||||
self.interfaceMaker.CloseInterfaces(self.pdm)
|
||||
self.pydebugger.CloseApp()
|
||||
self.app.RemoveGlobalExpressionContextProvider(self.expressionCookie)
|
||||
self.expressionCookie = None
|
||||
|
||||
self.pdm = None
|
||||
self.app = None
|
||||
self.pydebugger = None
|
||||
self.root = None
|
||||
|
||||
def RefreshAllModules(self, nodes, containerProvider):
|
||||
RefreshAllModules(nodes, self.root, self.CreateApplicationNode, (containerProvider,))
|
||||
|
||||
def CreateApplicationNode(self, node, containerProvider):
|
||||
realNode = self.app.CreateApplicationNode()
|
||||
|
||||
document = documents.DebugDocumentText(node.cont)
|
||||
document = _wrap(document, axdebug.IID_IDebugDocument)
|
||||
|
||||
node.cont.debugDocument = document
|
||||
|
||||
provider = documents.DebugDocumentProvider(document)
|
||||
provider = _wrap(provider, axdebug.IID_IDebugDocumentProvider)
|
||||
realNode.SetDocumentProvider(provider)
|
||||
|
||||
containerProvider.AddCodeContainer(node.cont, realNode)
|
||||
return realNode
|
||||
|
||||
def _GetCurrentDebugger():
|
||||
global currentDebugger
|
||||
if currentDebugger is None:
|
||||
currentDebugger = AXDebugger()
|
||||
return currentDebugger
|
||||
|
||||
def Break():
|
||||
_GetCurrentDebugger().Break()
|
||||
|
||||
brk = Break
|
||||
set_trace = Break
|
||||
|
||||
def dosomethingelse():
|
||||
a=2
|
||||
b = "Hi there"
|
||||
|
||||
def dosomething():
|
||||
a=1
|
||||
b=2
|
||||
dosomethingelse()
|
||||
|
||||
def test():
|
||||
Break()
|
||||
input("Waiting...")
|
||||
dosomething()
|
||||
print("Done")
|
||||
|
||||
if __name__=='__main__':
|
||||
print("About to test the debugging interfaces!")
|
||||
test()
|
||||
print(" %d/%d com objects still alive" % (pythoncom._GetInterfaceCount(), pythoncom._GetGatewayCount()))
|
124
venv/Lib/site-packages/win32comext/axdebug/documents.py
Normal file
124
venv/Lib/site-packages/win32comext/axdebug/documents.py
Normal file
|
@ -0,0 +1,124 @@
|
|||
""" Management of documents for AXDebugging.
|
||||
"""
|
||||
|
||||
from . import axdebug, gateways
|
||||
import pythoncom
|
||||
from .util import _wrap, _wrap_remove, RaiseNotImpl, trace
|
||||
from win32com.server.util import unwrap
|
||||
from . import codecontainer
|
||||
from . import contexts
|
||||
from win32com.server.exception import Exception
|
||||
import win32api, winerror, os, string, sys
|
||||
|
||||
#def trace(*args):
|
||||
# pass
|
||||
|
||||
def GetGoodFileName(fname):
|
||||
if fname[0] != "<":
|
||||
return win32api.GetFullPathName(fname)
|
||||
return fname
|
||||
|
||||
class DebugDocumentProvider(gateways.DebugDocumentProvider):
|
||||
def __init__(self, doc):
|
||||
self.doc = doc
|
||||
|
||||
def GetName(self, dnt):
|
||||
return self.doc.GetName(dnt)
|
||||
|
||||
def GetDocumentClassId(self):
|
||||
return self.doc.GetDocumentClassId()
|
||||
|
||||
def GetDocument(self):
|
||||
return self.doc
|
||||
|
||||
class DebugDocumentText(gateways.DebugDocumentInfo, gateways.DebugDocumentText, gateways.DebugDocument):
|
||||
_com_interfaces_ = gateways.DebugDocumentInfo._com_interfaces_ + \
|
||||
gateways.DebugDocumentText._com_interfaces_ + \
|
||||
gateways.DebugDocument._com_interfaces_
|
||||
_public_methods_ = gateways.DebugDocumentInfo._public_methods_ + \
|
||||
gateways.DebugDocumentText._public_methods_ + \
|
||||
gateways.DebugDocument._public_methods_
|
||||
# A class which implements a DebugDocumentText, using the functionality
|
||||
# provided by a codeContainer
|
||||
def __init__(self, codeContainer):
|
||||
gateways.DebugDocumentText.__init__(self)
|
||||
gateways.DebugDocumentInfo.__init__(self)
|
||||
gateways.DebugDocument.__init__(self)
|
||||
self.codeContainer = codeContainer
|
||||
|
||||
def _Close(self):
|
||||
self.docContexts = None
|
||||
# self.codeContainer._Close()
|
||||
self.codeContainer = None
|
||||
# IDebugDocumentInfo
|
||||
def GetName(self, dnt):
|
||||
return self.codeContainer.GetName(dnt)
|
||||
|
||||
def GetDocumentClassId(self):
|
||||
return "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"
|
||||
|
||||
# IDebugDocument has no methods!
|
||||
#
|
||||
|
||||
# IDebugDocumentText methods.
|
||||
# def GetDocumentAttributes
|
||||
def GetSize(self):
|
||||
# trace("GetSize")
|
||||
return self.codeContainer.GetNumLines(), self.codeContainer.GetNumChars()
|
||||
def GetPositionOfLine(self, cLineNumber):
|
||||
return self.codeContainer.GetPositionOfLine(cLineNumber)
|
||||
def GetLineOfPosition(self, charPos):
|
||||
return self.codeContainer.GetLineOfPosition(charPos)
|
||||
def GetText(self, charPos, maxChars, wantAttr):
|
||||
# Get all the attributes, else the tokenizer will get upset.
|
||||
# XXX - not yet!
|
||||
# trace("GetText", charPos, maxChars, wantAttr)
|
||||
cont = self.codeContainer
|
||||
attr = cont.GetSyntaxColorAttributes()
|
||||
return cont.GetText(), attr
|
||||
|
||||
def GetPositionOfContext(self, context):
|
||||
trace("GetPositionOfContext", context)
|
||||
context = unwrap(context)
|
||||
return context.offset, context.length
|
||||
|
||||
# Return a DebugDocumentContext.
|
||||
def GetContextOfPosition(self, charPos, maxChars):
|
||||
# Make one
|
||||
doc = _wrap(self, axdebug.IID_IDebugDocument)
|
||||
rc = self.codeContainer.GetCodeContextAtPosition(charPos)
|
||||
return rc.QueryInterface(axdebug.IID_IDebugDocumentContext)
|
||||
|
||||
class CodeContainerProvider:
|
||||
"""An abstract Python class which provides code containers!
|
||||
|
||||
Given a Python file name (as the debugger knows it by) this will
|
||||
return a CodeContainer interface suitable for use.
|
||||
|
||||
This provides a simple base imlpementation that simply supports
|
||||
a dictionary of nodes and providers.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.ccsAndNodes = {}
|
||||
|
||||
def AddCodeContainer(self, cc, node = None):
|
||||
fname = GetGoodFileName(cc.fileName)
|
||||
self.ccsAndNodes[fname] = cc, node
|
||||
|
||||
def FromFileName(self, fname):
|
||||
cc, node = self.ccsAndNodes.get(GetGoodFileName(fname), (None, None))
|
||||
# if cc is None:
|
||||
# print "FromFileName for %s returning None" % fname
|
||||
return cc
|
||||
|
||||
def Close(self):
|
||||
for cc, node in self.ccsAndNodes.values():
|
||||
try:
|
||||
# Must close the node before closing the provider
|
||||
# as node may make calls on provider (eg Reset breakpoints etc)
|
||||
if node is not None:
|
||||
node.Close()
|
||||
cc._Close()
|
||||
except pythoncom.com_error:
|
||||
pass
|
||||
self.ccsAndNodes = {}
|
48
venv/Lib/site-packages/win32comext/axdebug/dump.py
Normal file
48
venv/Lib/site-packages/win32comext/axdebug/dump.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
import sys, string
|
||||
import traceback
|
||||
from win32com.axdebug import axdebug
|
||||
from win32com.client.util import Enumerator
|
||||
import pythoncom
|
||||
|
||||
def DumpDebugApplicationNode(node, level = 0):
|
||||
# Recursive dump of a DebugApplicationNode
|
||||
spacer = " " * level
|
||||
for desc, attr in [("Node Name", axdebug.DOCUMENTNAMETYPE_APPNODE),
|
||||
("Title", axdebug.DOCUMENTNAMETYPE_TITLE),
|
||||
("Filename", axdebug.DOCUMENTNAMETYPE_FILE_TAIL),
|
||||
("URL", axdebug.DOCUMENTNAMETYPE_URL),
|
||||
]:
|
||||
try:
|
||||
info = node.GetName(attr)
|
||||
except pythoncom.com_error:
|
||||
info = "<N/A>"
|
||||
print("%s%s: %s" % (spacer, desc, info))
|
||||
try:
|
||||
doc = node.GetDocument()
|
||||
except pythoncom.com_error:
|
||||
doc = None
|
||||
if doc:
|
||||
doctext = doc.QueryInterface(axdebug.IID_IDebugDocumentText)
|
||||
numLines, numChars = doctext.GetSize()
|
||||
# text, attr = doctext.GetText(0, 20, 1)
|
||||
text, attr = doctext.GetText(0, numChars, 1)
|
||||
print("%sText is %s, %d bytes long" % (spacer, repr(text[:40]+"..."), len(text)))
|
||||
else:
|
||||
print("%s%s" % (spacer, "<No document available>"))
|
||||
|
||||
for child in Enumerator(node.EnumChildren()):
|
||||
DumpDebugApplicationNode(child, level+1)
|
||||
|
||||
def dumpall():
|
||||
dm=pythoncom.CoCreateInstance(axdebug.CLSID_MachineDebugManager,None,pythoncom.CLSCTX_ALL, axdebug.IID_IMachineDebugManager)
|
||||
e=Enumerator(dm.EnumApplications())
|
||||
for app in e:
|
||||
print("Application: %s" % app.GetName())
|
||||
node = app.GetRootNode() # of type PyIDebugApplicationNode->PyIDebugDocumentProvider->PyIDebugDocumentInfo
|
||||
DumpDebugApplicationNode(node)
|
||||
|
||||
if __name__=='__main__':
|
||||
try:
|
||||
dumpall()
|
||||
except:
|
||||
traceback.print_exc()
|
156
venv/Lib/site-packages/win32comext/axdebug/expressions.py
Normal file
156
venv/Lib/site-packages/win32comext/axdebug/expressions.py
Normal file
|
@ -0,0 +1,156 @@
|
|||
from . import axdebug, gateways
|
||||
from .util import _wrap, _wrap_remove, RaiseNotImpl
|
||||
import io, traceback
|
||||
from pprint import pprint
|
||||
from win32com.server.exception import COMException
|
||||
import winerror
|
||||
import string
|
||||
import sys
|
||||
|
||||
# Given an object, return a nice string
|
||||
def MakeNiceString(ob):
|
||||
stream = io.StringIO()
|
||||
pprint(ob, stream)
|
||||
return string.strip(stream.getvalue())
|
||||
|
||||
class ProvideExpressionContexts(gateways.ProvideExpressionContexts):
|
||||
pass
|
||||
|
||||
class ExpressionContext(gateways.DebugExpressionContext):
|
||||
def __init__(self, frame):
|
||||
self.frame = frame
|
||||
def ParseLanguageText(self, code, radix, delim, flags):
|
||||
return _wrap(Expression(self.frame, code, radix, delim, flags), axdebug.IID_IDebugExpression)
|
||||
def GetLanguageInfo(self):
|
||||
# print "GetLanguageInfo"
|
||||
return "Python", "{DF630910-1C1D-11d0-AE36-8C0F5E000000}"
|
||||
|
||||
class Expression(gateways.DebugExpression):
|
||||
def __init__(self, frame, code, radix, delim, flags):
|
||||
self.callback = None
|
||||
self.frame = frame
|
||||
self.code = code
|
||||
self.radix = radix
|
||||
self.delim = delim
|
||||
self.flags = flags
|
||||
self.isComplete = 0
|
||||
self.result=None
|
||||
self.hresult = winerror.E_UNEXPECTED
|
||||
def Start(self, callback):
|
||||
try:
|
||||
try:
|
||||
try:
|
||||
self.result = eval(self.code, self.frame.f_globals, self.frame.f_locals)
|
||||
except SyntaxError:
|
||||
exec(self.code, self.frame.f_globals, self.frame.f_locals)
|
||||
self.result = ""
|
||||
self.hresult = 0
|
||||
except:
|
||||
l = traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1])
|
||||
# l is a list of strings with trailing "\n"
|
||||
self.result = string.join(map(lambda s:s[:-1], l), "\n")
|
||||
self.hresult = winerror.E_FAIL
|
||||
finally:
|
||||
self.isComplete = 1
|
||||
callback.onComplete()
|
||||
def Abort(self):
|
||||
print("** ABORT **")
|
||||
|
||||
def QueryIsComplete(self):
|
||||
return self.isComplete
|
||||
|
||||
def GetResultAsString(self):
|
||||
# print "GetStrAsResult returning", self.result
|
||||
return self.hresult, MakeNiceString(self.result)
|
||||
|
||||
def GetResultAsDebugProperty(self):
|
||||
result = _wrap(DebugProperty(self.code, self.result, None, self.hresult), axdebug.IID_IDebugProperty)
|
||||
return self.hresult, result
|
||||
|
||||
def MakeEnumDebugProperty(object, dwFieldSpec, nRadix, iid, stackFrame = None):
|
||||
name_vals = []
|
||||
if hasattr(object, "items") and hasattr(object, "keys"): # If it is a dict.
|
||||
name_vals = iter(object.items())
|
||||
dictionary = object
|
||||
elif hasattr(object, "__dict__"): #object with dictionary, module
|
||||
name_vals = iter(object.__dict__.items())
|
||||
dictionary = object.__dict__
|
||||
infos = []
|
||||
for name, val in name_vals:
|
||||
infos.append(GetPropertyInfo(name, val, dwFieldSpec, nRadix, 0, dictionary, stackFrame))
|
||||
return _wrap(EnumDebugPropertyInfo(infos), axdebug.IID_IEnumDebugPropertyInfo)
|
||||
|
||||
def GetPropertyInfo(obname, obvalue, dwFieldSpec, nRadix, hresult=0, dictionary = None, stackFrame = None):
|
||||
# returns a tuple
|
||||
name = typ = value = fullname = attrib = dbgprop = None
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_VALUE:
|
||||
value = MakeNiceString(obvalue)
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_NAME:
|
||||
name = obname
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_TYPE:
|
||||
if hresult:
|
||||
typ = "Error"
|
||||
else:
|
||||
try:
|
||||
typ = type(obvalue).__name__
|
||||
except AttributeError:
|
||||
typ = str(type(obvalue))
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_FULLNAME:
|
||||
fullname = obname
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_ATTRIBUTES:
|
||||
if hasattr(obvalue, "has_key") or hasattr(obvalue, "__dict__"): # If it is a dict or object
|
||||
attrib = axdebug.DBGPROP_ATTRIB_VALUE_IS_EXPANDABLE
|
||||
else:
|
||||
attrib = 0
|
||||
if dwFieldSpec & axdebug.DBGPROP_INFO_DEBUGPROP:
|
||||
dbgprop = _wrap(DebugProperty(name, obvalue, None, hresult, dictionary, stackFrame), axdebug.IID_IDebugProperty)
|
||||
return name, typ, value, fullname, attrib, dbgprop
|
||||
|
||||
from win32com.server.util import ListEnumeratorGateway
|
||||
class EnumDebugPropertyInfo(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugCodeContexts
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugCodeContexts interface for the object.
|
||||
|
||||
"""
|
||||
_public_methods_ = ListEnumeratorGateway._public_methods_ + ["GetCount"]
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugPropertyInfo]
|
||||
def GetCount(self):
|
||||
return len(self._list_)
|
||||
def _wrap(self, ob):
|
||||
return ob
|
||||
|
||||
class DebugProperty:
|
||||
_com_interfaces_ = [axdebug.IID_IDebugProperty]
|
||||
_public_methods_ = ['GetPropertyInfo', 'GetExtendedInfo', 'SetValueAsString',
|
||||
'EnumMembers', 'GetParent'
|
||||
]
|
||||
def __init__(self, name, value, parent = None, hresult = 0, dictionary = None, stackFrame = None):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.parent = parent
|
||||
self.hresult = hresult
|
||||
self.dictionary = dictionary
|
||||
self.stackFrame = stackFrame
|
||||
|
||||
def GetPropertyInfo(self, dwFieldSpec, nRadix):
|
||||
return GetPropertyInfo(self.name, self.value, dwFieldSpec, nRadix, self.hresult, dictionary, stackFrame)
|
||||
|
||||
def GetExtendedInfo(self): ### Note - not in the framework.
|
||||
RaiseNotImpl("DebugProperty::GetExtendedInfo")
|
||||
|
||||
def SetValueAsString(self, value, radix):
|
||||
if self.stackFrame and self.dictionary:
|
||||
self.dictionary[self.name]= eval(value,self.stackFrame.f_globals, self.stackFrame.f_locals)
|
||||
else:
|
||||
RaiseNotImpl("DebugProperty::SetValueAsString")
|
||||
|
||||
def EnumMembers(self, dwFieldSpec, nRadix, iid):
|
||||
# Returns IEnumDebugPropertyInfo
|
||||
return MakeEnumDebugProperty(self.value, dwFieldSpec, nRadix, iid, self.stackFrame)
|
||||
|
||||
def GetParent(self):
|
||||
# return IDebugProperty
|
||||
RaiseNotImpl("DebugProperty::GetParent")
|
452
venv/Lib/site-packages/win32comext/axdebug/gateways.py
Normal file
452
venv/Lib/site-packages/win32comext/axdebug/gateways.py
Normal file
|
@ -0,0 +1,452 @@
|
|||
# Classes which describe interfaces.
|
||||
|
||||
from win32com.server.exception import Exception
|
||||
from win32com.server.util import ListEnumeratorGateway
|
||||
from win32com.axdebug import axdebug
|
||||
from win32com.axdebug.util import RaiseNotImpl, _wrap
|
||||
import pythoncom
|
||||
import win32com.server.connect
|
||||
import winerror
|
||||
|
||||
class EnumDebugCodeContexts(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugCodeContexts
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugCodeContexts interface for the object.
|
||||
|
||||
"""
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugCodeContexts ]
|
||||
|
||||
class EnumDebugStackFrames(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugStackFrames
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugStackFrames interface for the object.
|
||||
|
||||
"""
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugStackFrames ]
|
||||
|
||||
class EnumDebugApplicationNodes(ListEnumeratorGateway):
|
||||
"""A class to expose a Python sequence as an EnumDebugStackFrames
|
||||
|
||||
Create an instance of this class passing a sequence (list, tuple, or
|
||||
any sequence protocol supporting object) and it will automatically
|
||||
support the EnumDebugApplicationNodes interface for the object.
|
||||
|
||||
"""
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumDebugApplicationNodes ]
|
||||
|
||||
class EnumRemoteDebugApplications(ListEnumeratorGateway):
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumRemoteDebugApplications ]
|
||||
|
||||
class EnumRemoteDebugApplicationThreads(ListEnumeratorGateway):
|
||||
_com_interfaces_ = [ axdebug.IID_IEnumRemoteDebugApplicationThreads ]
|
||||
|
||||
class DebugDocumentInfo:
|
||||
_public_methods_ = ["GetName", "GetDocumentClassId"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentInfo]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetName(self, dnt):
|
||||
""" Get the one of the name of the document
|
||||
dnt -- int DOCUMENTNAMETYPE
|
||||
"""
|
||||
RaiseNotImpl("GetName")
|
||||
def GetDocumentClassId(self):
|
||||
"""
|
||||
Result must be an IID object (or string representing one).
|
||||
"""
|
||||
RaiseNotImpl("GetDocumentClassId")
|
||||
|
||||
class DebugDocumentProvider(DebugDocumentInfo):
|
||||
_public_methods_ = DebugDocumentInfo._public_methods_ + ["GetDocument"]
|
||||
_com_interfaces_ = DebugDocumentInfo._com_interfaces_ + [axdebug.IID_IDebugDocumentProvider]
|
||||
def GetDocument(self):
|
||||
RaiseNotImpl("GetDocument")
|
||||
|
||||
class DebugApplicationNode(DebugDocumentProvider):
|
||||
"""Provides the functionality of IDebugDocumentProvider, plus a context within a project tree.
|
||||
"""
|
||||
_public_methods_ = """EnumChildren GetParent SetDocumentProvider
|
||||
Close Attach Detach""".split() + \
|
||||
DebugDocumentProvider._public_methods_
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentProvider] + \
|
||||
DebugDocumentProvider._com_interfaces_
|
||||
def __init__(self):
|
||||
DebugDocumentProvider.__init__(self)
|
||||
def EnumChildren(self):
|
||||
# Result is type PyIEnumDebugApplicationNodes
|
||||
RaiseNotImpl("EnumChildren")
|
||||
def GetParent(self):
|
||||
# result is type PyIDebugApplicationNode
|
||||
RaiseNotImpl("GetParent")
|
||||
def SetDocumentProvider(self, pddp): # PyIDebugDocumentProvider pddp
|
||||
# void result.
|
||||
RaiseNotImpl("SetDocumentProvider")
|
||||
def Close(self):
|
||||
# void result.
|
||||
RaiseNotImpl("Close")
|
||||
def Attach(self, parent): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("Attach")
|
||||
def Detach(self):
|
||||
# void result.
|
||||
RaiseNotImpl("Detach")
|
||||
|
||||
class DebugApplicationNodeEvents:
|
||||
"""Event interface for DebugApplicationNode object.
|
||||
"""
|
||||
_public_methods_ = "onAddChild onRemoveChild onDetach".split()
|
||||
_com_interfaces_ = [axdebug.IID_IDebugApplicationNodeEvents]
|
||||
def __init__(self):
|
||||
pass
|
||||
def onAddChild(self, child): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("onAddChild")
|
||||
def onRemoveChild(self, child): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("onRemoveChild")
|
||||
def onDetach(self):
|
||||
# void result.
|
||||
RaiseNotImpl("onDetach")
|
||||
def onAttach(self, parent): # PyIDebugApplicationNode
|
||||
# void result.
|
||||
RaiseNotImpl("onAttach")
|
||||
|
||||
class DebugDocument(DebugDocumentInfo):
|
||||
"""The base interface to all debug documents.
|
||||
"""
|
||||
_public_methods_ = DebugDocumentInfo._public_methods_
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocument] + DebugDocumentInfo._com_interfaces_
|
||||
|
||||
class DebugDocumentText(DebugDocument):
|
||||
"""The interface to a text only debug document.
|
||||
"""
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentText] + \
|
||||
DebugDocument._com_interfaces_
|
||||
_public_methods_ = ["GetDocumentAttributes", "GetSize",
|
||||
"GetPositionOfLine", "GetLineOfPosition", "GetText",
|
||||
"GetPositionOfContext", "GetContextOfPosition"] + \
|
||||
DebugDocument._public_methods_
|
||||
def __init__(self):
|
||||
pass
|
||||
# IDebugDocumentText
|
||||
def GetDocumentAttributes(self):
|
||||
# Result is int (TEXT_DOC_ATTR)
|
||||
RaiseNotImpl("GetDocumentAttributes")
|
||||
def GetSize(self):
|
||||
# Result is (numLines, numChars)
|
||||
RaiseNotImpl("GetSize")
|
||||
def GetPositionOfLine(self, cLineNumber):
|
||||
# Result is int char position
|
||||
RaiseNotImpl("GetPositionOfLine")
|
||||
def GetLineOfPosition(self, charPos):
|
||||
# Result is int, int (lineNo, offset)
|
||||
RaiseNotImpl("GetLineOfPosition")
|
||||
def GetText(self, charPos, maxChars, wantAttr):
|
||||
"""Params
|
||||
charPos -- integer
|
||||
maxChars -- integer
|
||||
wantAttr -- Should the function compute attributes.
|
||||
|
||||
Return value must be (string, attribtues). attributes may be
|
||||
None if(not wantAttr)
|
||||
"""
|
||||
RaiseNotImpl("GetText")
|
||||
def GetPositionOfContext(self, debugDocumentContext):
|
||||
"""Params
|
||||
debugDocumentContext -- a PyIDebugDocumentContext object.
|
||||
|
||||
Return value must be (charPos, numChars)
|
||||
"""
|
||||
RaiseNotImpl("GetPositionOfContext")
|
||||
def GetContextOfPosition(self, charPos, maxChars):
|
||||
"""Params are integers.
|
||||
Return value must be PyIDebugDocumentContext object
|
||||
"""
|
||||
print(self)
|
||||
RaiseNotImpl("GetContextOfPosition")
|
||||
|
||||
class DebugDocumentTextExternalAuthor:
|
||||
"""Allow external editors to edit file-based debugger documents, and to notify the document when the source file has been changed.
|
||||
"""
|
||||
_public_methods_ = ["GetPathName", "GetFileName", "NotifyChanged"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugDocumentTextExternalAuthor]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetPathName(self):
|
||||
"""Return the full path (including file name) to the document's source file.
|
||||
|
||||
Result must be (filename, fIsOriginal), where
|
||||
- if fIsOriginalPath is TRUE if the path refers to the original file for the document.
|
||||
- if fIsOriginalPath is FALSE if the path refers to a newly created temporary file.
|
||||
|
||||
raise Exception(winerror.E_FAIL) if no source file can be created/determined.
|
||||
"""
|
||||
RaiseNotImpl("GetPathName")
|
||||
|
||||
def GetFileName(self):
|
||||
"""Return just the name of the document, with no path information. (Used for "Save As...")
|
||||
|
||||
Result is a string
|
||||
"""
|
||||
RaiseNotImpl("GetFileName")
|
||||
|
||||
def NotifyChanged(self):
|
||||
""" Notify the host that the document's source file has been saved and
|
||||
that its contents should be refreshed.
|
||||
"""
|
||||
RaiseNotImpl("NotifyChanged")
|
||||
|
||||
|
||||
class DebugDocumentTextEvents:
|
||||
_public_methods_ = """onDestroy onInsertText onRemoveText
|
||||
onReplaceText onUpdateTextAttributes
|
||||
onUpdateDocumentAttributes""".split()
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugDocumentTextEvents ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def onDestroy(self):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onDestroy")
|
||||
def onInsertText(self, cCharacterPosition, cNumToInsert):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onInsertText")
|
||||
def onRemoveText(self, cCharacterPosition, cNumToRemove):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onRemoveText")
|
||||
def onReplaceText(self, cCharacterPosition, cNumToReplace):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onReplaceText")
|
||||
def onUpdateTextAttributes(self, cCharacterPosition, cNumToUpdate):
|
||||
# Result is void.
|
||||
RaiseNotImpl("onUpdateTextAttributes")
|
||||
def onUpdateDocumentAttributes(self,textdocattr): # TEXT_DOC_ATTR
|
||||
# Result is void.
|
||||
RaiseNotImpl("onUpdateDocumentAttributes")
|
||||
|
||||
class DebugDocumentContext:
|
||||
_public_methods_ = [ 'GetDocument', 'EnumCodeContexts']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugDocumentContext ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetDocument(self):
|
||||
"""Return value must be a PyIDebugDocument object
|
||||
"""
|
||||
RaiseNotImpl("GetDocument")
|
||||
|
||||
def EnumCodeContexts(self):
|
||||
"""Return value must be a PyIEnumDebugCodeContexts object
|
||||
"""
|
||||
RaiseNotImpl("EnumCodeContexts")
|
||||
|
||||
|
||||
class DebugCodeContext:
|
||||
_public_methods_ = [ 'GetDocumentContext', 'SetBreakPoint']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugCodeContext ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetDocumentContext(self):
|
||||
"""Return value must be a PyIDebugDocumentContext object
|
||||
"""
|
||||
RaiseNotImpl("GetDocumentContext")
|
||||
def SetBreakPoint(self, bps):
|
||||
"""bps -- an integer with flags.
|
||||
"""
|
||||
RaiseNotImpl("SetBreakPoint")
|
||||
|
||||
|
||||
class DebugStackFrame:
|
||||
"""Abstraction representing a logical stack frame on the stack of a thread."""
|
||||
_public_methods_ = [ 'GetCodeContext', 'GetDescriptionString', 'GetLanguageString', 'GetThread', 'GetDebugProperty']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugStackFrame ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetCodeContext(self):
|
||||
"""Returns the current code context associated with the stack frame.
|
||||
|
||||
Return value must be a IDebugCodeContext object
|
||||
"""
|
||||
RaiseNotImpl("GetCodeContext")
|
||||
def GetDescriptionString(self, fLong):
|
||||
"""Returns a textual description of the stack frame.
|
||||
|
||||
fLong -- A flag indicating if the long name is requested.
|
||||
"""
|
||||
RaiseNotImpl("GetDescriptionString")
|
||||
def GetLanguageString(self):
|
||||
"""Returns a short or long textual description of the language.
|
||||
|
||||
fLong -- A flag indicating if the long name is requested.
|
||||
"""
|
||||
RaiseNotImpl("GetLanguageString")
|
||||
def GetThread(self):
|
||||
""" Returns the thread associated with this stack frame.
|
||||
|
||||
Result must be a IDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("GetThread")
|
||||
def GetDebugProperty(self):
|
||||
RaiseNotImpl("GetDebugProperty")
|
||||
|
||||
|
||||
class DebugDocumentHost:
|
||||
"""The interface from the IDebugDocumentHelper back to
|
||||
the smart host or language engine. This interface
|
||||
exposes host specific functionality such as syntax coloring.
|
||||
"""
|
||||
_public_methods_ = [ 'GetDeferredText', 'GetScriptTextAttributes', 'OnCreateDocumentContext', 'GetPathName', 'GetFileName', 'NotifyChanged']
|
||||
_com_interfaces_ = [ axdebug.IID_IDebugDocumentHost ]
|
||||
def __init__(self):
|
||||
pass
|
||||
def GetDeferredText(self, dwTextStartCookie, maxChars, bWantAttr):
|
||||
RaiseNotImpl("GetDeferredText")
|
||||
|
||||
def GetScriptTextAttributes(self, codeText, delimterText, flags):
|
||||
# Result must be an attribute sequence of same "length" as the code.
|
||||
RaiseNotImpl("GetScriptTextAttributes")
|
||||
|
||||
def OnCreateDocumentContext(self):
|
||||
# Result must be a PyIUnknown
|
||||
RaiseNotImpl("OnCreateDocumentContext")
|
||||
|
||||
def GetPathName(self):
|
||||
# Result must be (string, int) where the int is a BOOL
|
||||
# - TRUE if the path refers to the original file for the document.
|
||||
# - FALSE if the path refers to a newly created temporary file.
|
||||
# - raise Exception(scode=E_FAIL) if no source file can be created/determined.
|
||||
RaiseNotImpl("GetPathName")
|
||||
|
||||
def GetFileName(self):
|
||||
# Result is a string with just the name of the document, no path information.
|
||||
RaiseNotImpl("GetFileName")
|
||||
|
||||
def NotifyChanged(self):
|
||||
RaiseNotImpl("NotifyChanged")
|
||||
|
||||
# Additional gateway related functions.
|
||||
|
||||
class DebugDocumentTextConnectServer:
|
||||
_public_methods_ = win32com.server.connect.IConnectionPointContainer_methods + win32com.server.connect.IConnectionPoint_methods
|
||||
_com_interfaces_ = [pythoncom.IID_IConnectionPoint, pythoncom.IID_IConnectionPointContainer]
|
||||
# IConnectionPoint interfaces
|
||||
def __init__(self):
|
||||
self.cookieNo = -1
|
||||
self.connections = {}
|
||||
def EnumConnections(self):
|
||||
RaiseNotImpl("EnumConnections")
|
||||
def GetConnectionInterface(self):
|
||||
RaiseNotImpl("GetConnectionInterface")
|
||||
def GetConnectionPointContainer(self):
|
||||
return _wrap(self)
|
||||
def Advise(self, pUnk):
|
||||
# Creates a connection to the client. Simply allocate a new cookie,
|
||||
# find the clients interface, and store it in a dictionary.
|
||||
interface = pUnk.QueryInterface(axdebug.IID_IDebugDocumentTextEvents,1)
|
||||
self.cookieNo = self.cookieNo + 1
|
||||
self.connections[self.cookieNo] = interface
|
||||
return self.cookieNo
|
||||
def Unadvise(self, cookie):
|
||||
# Destroy a connection - simply delete interface from the map.
|
||||
try:
|
||||
del self.connections[cookie]
|
||||
except KeyError:
|
||||
return Exception(scode=winerror.E_UNEXPECTED)
|
||||
# IConnectionPointContainer interfaces
|
||||
def EnumConnectionPoints(self):
|
||||
RaiseNotImpl("EnumConnectionPoints")
|
||||
def FindConnectionPoint(self, iid):
|
||||
# Find a connection we support. Only support the single event interface.
|
||||
if iid==axdebug.IID_IDebugDocumentTextEvents:
|
||||
return _wrap(self)
|
||||
raise Exception(scode=winerror.E_NOINTERFACE) # ??
|
||||
|
||||
class RemoteDebugApplicationEvents:
|
||||
_public_methods_ = ["OnConnectDebugger","OnDisconnectDebugger","OnSetName","OnDebugOutput","OnClose","OnEnterBreakPoint","OnLeaveBreakPoint","OnCreateThread","OnDestroyThread","OnBreakFlagChange"]
|
||||
_com_interfaces_ = [axdebug.IID_IRemoteDebugApplicationEvents]
|
||||
def OnConnectDebugger(self, appDebugger):
|
||||
"""appDebugger -- a PyIApplicationDebugger
|
||||
"""
|
||||
RaiseNotImpl("OnConnectDebugger")
|
||||
def OnDisconnectDebugger(self):
|
||||
RaiseNotImpl("OnDisconnectDebugger")
|
||||
def OnSetName(self, name):
|
||||
RaiseNotImpl("OnSetName")
|
||||
def OnDebugOutput(self, string):
|
||||
RaiseNotImpl("OnDebugOutput")
|
||||
def OnClose(self):
|
||||
RaiseNotImpl("OnClose")
|
||||
def OnEnterBreakPoint(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnEnterBreakPoint")
|
||||
def OnLeaveBreakPoint(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnLeaveBreakPoint")
|
||||
def OnCreateThread(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnCreateThread")
|
||||
def OnDestroyThread(self, rdat):
|
||||
"""rdat -- PyIRemoteDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("OnDestroyThread")
|
||||
def OnBreakFlagChange(self, abf, rdat):
|
||||
"""abf -- int - one of the axdebug.APPBREAKFLAGS constants
|
||||
rdat -- PyIRemoteDebugApplicationThread
|
||||
RaiseNotImpl("OnBreakFlagChange")
|
||||
"""
|
||||
class DebugExpressionContext:
|
||||
_public_methods_ = ["ParseLanguageText", "GetLanguageInfo"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugExpressionContext]
|
||||
def __init__(self):
|
||||
pass
|
||||
def ParseLanguageText(self, code, radix, delim, flags):
|
||||
"""
|
||||
result is IDebugExpression
|
||||
"""
|
||||
RaiseNotImpl("ParseLanguageText")
|
||||
def GetLanguageInfo(self):
|
||||
"""
|
||||
result is (string langName, iid langId)
|
||||
"""
|
||||
RaiseNotImpl("GetLanguageInfo")
|
||||
|
||||
class DebugExpression:
|
||||
_public_methods_ = ["Start", "Abort", "QueryIsComplete", "GetResultAsString", "GetResultAsDebugProperty"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugExpression]
|
||||
def Start(self, callback):
|
||||
"""
|
||||
callback -- an IDebugExpressionCallback
|
||||
|
||||
result - void
|
||||
"""
|
||||
RaiseNotImpl("Start")
|
||||
def Abort(self):
|
||||
"""
|
||||
no params
|
||||
result -- void
|
||||
"""
|
||||
RaiseNotImpl("Abort")
|
||||
|
||||
def QueryIsComplete(self):
|
||||
"""
|
||||
no params
|
||||
result -- void
|
||||
"""
|
||||
RaiseNotImpl("QueryIsComplete")
|
||||
|
||||
def GetResultAsString(self):
|
||||
RaiseNotImpl("GetResultAsString")
|
||||
|
||||
def GetResultAsDebugProperty(self):
|
||||
RaiseNotImpl("GetResultAsDebugProperty")
|
||||
|
||||
class ProvideExpressionContexts:
|
||||
_public_methods_ = ["EnumExpressionContexts"]
|
||||
_com_interfaces_ = [axdebug.IID_IProvideExpressionContexts]
|
||||
def EnumExpressionContexts(self):
|
||||
RaiseNotImpl("EnumExpressionContexts")
|
146
venv/Lib/site-packages/win32comext/axdebug/stackframe.py
Normal file
146
venv/Lib/site-packages/win32comext/axdebug/stackframe.py
Normal file
|
@ -0,0 +1,146 @@
|
|||
"""Support for stack-frames.
|
||||
|
||||
Provides Implements a nearly complete wrapper for a stack frame.
|
||||
"""
|
||||
import sys
|
||||
from .util import _wrap, RaiseNotImpl
|
||||
import expressions, gateways, axdebug, winerror
|
||||
import pythoncom
|
||||
from win32com.server.exception import COMException
|
||||
|
||||
from .util import trace
|
||||
#def trace(*args):
|
||||
# pass
|
||||
|
||||
class EnumDebugStackFrames(gateways.EnumDebugStackFrames):
|
||||
"""A class that given a debugger object, can return an enumerator
|
||||
of DebugStackFrame objects.
|
||||
"""
|
||||
def __init__(self, debugger):
|
||||
infos = []
|
||||
frame = debugger.currentframe
|
||||
# print "Stack check"
|
||||
while frame:
|
||||
# print " Checking frame", frame.f_code.co_filename, frame.f_lineno-1, frame.f_trace,
|
||||
# Get a DebugCodeContext for the stack frame. If we fail, then it
|
||||
# is not debuggable, and therefore not worth displaying.
|
||||
cc = debugger.codeContainerProvider.FromFileName(frame.f_code.co_filename)
|
||||
if cc is not None:
|
||||
try:
|
||||
address = frame.f_locals['__axstack_address__']
|
||||
except KeyError:
|
||||
# print "Couldnt find stack address for",frame.f_code.co_filename, frame.f_lineno-1
|
||||
# Use this one, even tho it is wrong :-(
|
||||
address = axdebug.GetStackAddress()
|
||||
frameInfo = DebugStackFrame(frame, frame.f_lineno-1, cc), address, address+1, 0, None
|
||||
infos.append(frameInfo)
|
||||
# print "- Kept!"
|
||||
# else:
|
||||
# print "- rejected"
|
||||
frame = frame.f_back
|
||||
|
||||
gateways.EnumDebugStackFrames.__init__(self, infos, 0)
|
||||
# def __del__(self):
|
||||
# print "EnumDebugStackFrames dieing"
|
||||
|
||||
def Next(self, count):
|
||||
return gateways.EnumDebugStackFrames.Next(self, count)
|
||||
|
||||
# def _query_interface_(self, iid):
|
||||
# from win32com.util import IIDToInterfaceName
|
||||
# print "EnumDebugStackFrames QI with %s (%s)" % (IIDToInterfaceName(iid), str(iid))
|
||||
# return 0
|
||||
def _wrap(self, obj):
|
||||
# This enum returns a tuple, with 2 com objects in it.
|
||||
obFrame, min, lim, fFinal, obFinal = obj
|
||||
obFrame = _wrap(obFrame, axdebug.IID_IDebugStackFrame)
|
||||
if obFinal:
|
||||
obFinal = _wrap(obFinal, pythoncom.IID_IUnknown)
|
||||
return obFrame, min, lim, fFinal, obFinal
|
||||
|
||||
class DebugStackFrame(gateways.DebugStackFrame):
|
||||
def __init__(self, frame, lineno, codeContainer):
|
||||
self.frame = frame
|
||||
self.lineno = lineno
|
||||
self.codeContainer = codeContainer
|
||||
self.expressionContext = None
|
||||
# def __del__(self):
|
||||
# print "DSF dieing"
|
||||
def _query_interface_(self, iid):
|
||||
if iid==axdebug.IID_IDebugExpressionContext:
|
||||
if self.expressionContext is None:
|
||||
self.expressionContext = _wrap(expressions.ExpressionContext(self.frame), axdebug.IID_IDebugExpressionContext)
|
||||
return self.expressionContext
|
||||
# from win32com.util import IIDToInterfaceName
|
||||
# print "DebugStackFrame QI with %s (%s)" % (IIDToInterfaceName(iid), str(iid))
|
||||
return 0
|
||||
#
|
||||
# The following need implementation
|
||||
def GetThread(self):
|
||||
""" Returns the thread associated with this stack frame.
|
||||
|
||||
Result must be a IDebugApplicationThread
|
||||
"""
|
||||
RaiseNotImpl("GetThread")
|
||||
|
||||
def GetCodeContext(self):
|
||||
offset = self.codeContainer.GetPositionOfLine(self.lineno)
|
||||
return self.codeContainer.GetCodeContextAtPosition(offset)
|
||||
#
|
||||
# The following are usefully implemented
|
||||
def GetDescriptionString(self, fLong):
|
||||
filename = self.frame.f_code.co_filename
|
||||
s = ""
|
||||
if 0: #fLong:
|
||||
s = s + filename
|
||||
if self.frame.f_code.co_name:
|
||||
s = s + self.frame.f_code.co_name
|
||||
else:
|
||||
s = s + "<lambda>"
|
||||
return s
|
||||
def GetLanguageString(self, fLong):
|
||||
if fLong:
|
||||
return "Python ActiveX Scripting Engine"
|
||||
else:
|
||||
return "Python"
|
||||
def GetDebugProperty(self):
|
||||
return _wrap(StackFrameDebugProperty(self.frame), axdebug.IID_IDebugProperty)
|
||||
|
||||
class DebugStackFrameSniffer:
|
||||
_public_methods_ = ["EnumStackFrames"]
|
||||
_com_interfaces_ = [axdebug.IID_IDebugStackFrameSniffer]
|
||||
def __init__(self, debugger):
|
||||
self.debugger = debugger
|
||||
trace("DebugStackFrameSniffer instantiated")
|
||||
# def __del__(self):
|
||||
# print "DSFS dieing"
|
||||
def EnumStackFrames(self):
|
||||
trace("DebugStackFrameSniffer.EnumStackFrames called")
|
||||
return _wrap(EnumDebugStackFrames(self.debugger), axdebug.IID_IEnumDebugStackFrames)
|
||||
|
||||
# A DebugProperty for a stack frame.
|
||||
class StackFrameDebugProperty:
|
||||
_com_interfaces_ = [axdebug.IID_IDebugProperty]
|
||||
_public_methods_ = ['GetPropertyInfo', 'GetExtendedInfo', 'SetValueAsString',
|
||||
'EnumMembers', 'GetParent'
|
||||
]
|
||||
def __init__(self, frame):
|
||||
self.frame = frame
|
||||
|
||||
def GetPropertyInfo(self, dwFieldSpec, nRadix):
|
||||
RaiseNotImpl("StackFrameDebugProperty::GetPropertyInfo")
|
||||
def GetExtendedInfo(self): ### Note - not in the framework.
|
||||
RaiseNotImpl("StackFrameDebugProperty::GetExtendedInfo")
|
||||
|
||||
def SetValueAsString(self, value, radix):
|
||||
#
|
||||
RaiseNotImpl("DebugProperty::SetValueAsString")
|
||||
|
||||
def EnumMembers(self, dwFieldSpec, nRadix, iid):
|
||||
print("EnumMembers", dwFieldSpec, nRadix, iid)
|
||||
from . import expressions
|
||||
return expressions.MakeEnumDebugProperty(self.frame.f_locals, dwFieldSpec, nRadix, iid, self.frame)
|
||||
|
||||
def GetParent(self):
|
||||
# return IDebugProperty
|
||||
RaiseNotImpl("DebugProperty::GetParent")
|
114
venv/Lib/site-packages/win32comext/axdebug/util.py
Normal file
114
venv/Lib/site-packages/win32comext/axdebug/util.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
# Utility function for wrapping objects. Centralising allows me to turn
|
||||
# debugging on and off for the entire package in a single spot.
|
||||
|
||||
import sys
|
||||
import win32com.server.util
|
||||
from win32com.server.exception import Exception
|
||||
import winerror
|
||||
import win32api
|
||||
import os
|
||||
|
||||
try:
|
||||
os.environ["DEBUG_AXDEBUG"]
|
||||
debugging = 1
|
||||
except KeyError:
|
||||
debugging = 0
|
||||
|
||||
def trace(*args):
|
||||
if not debugging: return
|
||||
print(str(win32api.GetCurrentThreadId()) + ":", end=' ')
|
||||
for arg in args:
|
||||
print(arg, end=' ')
|
||||
print()
|
||||
|
||||
# The AXDebugging implementation assumes that the returned COM pointers are in
|
||||
# some cases identical. Eg, from a C++ perspective:
|
||||
# p->GetSomeInterface( &p1 );
|
||||
# p->GetSomeInterface( &p2 );
|
||||
# p1==p2
|
||||
# By default, this is _not_ true for Python.
|
||||
# (Now this is only true for Document objects, and Python
|
||||
# now does ensure this.
|
||||
|
||||
all_wrapped = {}
|
||||
|
||||
def _wrap_nodebug(object, iid):
|
||||
return win32com.server.util.wrap(object, iid)
|
||||
|
||||
def _wrap_debug(object, iid):
|
||||
import win32com.server.policy
|
||||
dispatcher = win32com.server.policy.DispatcherWin32trace
|
||||
return win32com.server.util.wrap(object, iid, useDispatcher = dispatcher)
|
||||
|
||||
if debugging:
|
||||
_wrap = _wrap_debug
|
||||
else:
|
||||
_wrap = _wrap_nodebug
|
||||
|
||||
def _wrap_remove(object, iid = None):
|
||||
# Old - no longer used or necessary!
|
||||
return
|
||||
|
||||
def _dump_wrapped():
|
||||
from win32com.server.util import unwrap
|
||||
print("Wrapped items:")
|
||||
for key, items in all_wrapped.items():
|
||||
print(key, end=' ')
|
||||
try:
|
||||
ob = unwrap(key)
|
||||
print(ob, sys.getrefcount(ob))
|
||||
except:
|
||||
print("<error>")
|
||||
|
||||
|
||||
def RaiseNotImpl(who = None):
|
||||
if who is not None:
|
||||
print("********* Function %s Raising E_NOTIMPL ************" % (who))
|
||||
|
||||
# Print a sort-of "traceback", dumping all the frames leading to here.
|
||||
try:
|
||||
1/0
|
||||
except:
|
||||
frame = sys.exc_info()[2].tb_frame
|
||||
while frame:
|
||||
print("File: %s, Line: %d" % (frame.f_code.co_filename, frame.f_lineno))
|
||||
frame = frame.f_back
|
||||
|
||||
# and raise the exception for COM
|
||||
raise Exception(scode=winerror.E_NOTIMPL)
|
||||
|
||||
|
||||
import win32com.server.policy
|
||||
class Dispatcher(win32com.server.policy.DispatcherWin32trace):
|
||||
def __init__(self, policyClass, object):
|
||||
win32com.server.policy.DispatcherTrace.__init__(self, policyClass, object)
|
||||
import win32traceutil # Sets up everything.
|
||||
# print "Object with win32trace dispatcher created (object=%s)" % `object`
|
||||
|
||||
def _QueryInterface_(self, iid):
|
||||
rc = win32com.server.policy.DispatcherBase._QueryInterface_(self, iid)
|
||||
# if not rc:
|
||||
# self._trace_("in _QueryInterface_ with unsupported IID %s (%s)\n" % (IIDToInterfaceName(iid),iid))
|
||||
return rc
|
||||
|
||||
def _Invoke_(self, dispid, lcid, wFlags, args):
|
||||
print("In Invoke with", dispid, lcid, wFlags, args, "with object",self.policy._obj_)
|
||||
try:
|
||||
rc = win32com.server.policy.DispatcherBase._Invoke_(self, dispid, lcid, wFlags, args)
|
||||
# print "Invoke of", dispid, "returning", rc
|
||||
return rc
|
||||
except Exception:
|
||||
t, v, tb = sys.exc_info()
|
||||
tb = None # A cycle
|
||||
scode = v.scode
|
||||
try:
|
||||
desc = " (" + str(v.description) + ")"
|
||||
except AttributeError:
|
||||
desc = ""
|
||||
print("*** Invoke of %s raised COM exception 0x%x%s" % (dispid, scode, desc))
|
||||
except:
|
||||
print("*** Invoke of %s failed:" % dispid)
|
||||
typ, val, tb = sys.exc_info()
|
||||
import traceback
|
||||
traceback.print_exception(typ, val, tb)
|
||||
raise
|
Loading…
Add table
Add a link
Reference in a new issue