180 lines
6.0 KiB
Python
180 lines
6.0 KiB
Python
"""Support for stack-frames.
|
|
|
|
Provides Implements a nearly complete wrapper for a stack frame.
|
|
"""
|
|
|
|
import pythoncom
|
|
from win32com.server.exception import COMException
|
|
|
|
from . import axdebug, expressions, gateways
|
|
from .util import RaiseNotImpl, _wrap, 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")
|