147 lines
5.7 KiB
Python
147 lines
5.7 KiB
Python
|
"""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")
|