stackframe.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. """Support for stack-frames.
  2. Provides Implements a nearly complete wrapper for a stack frame.
  3. """
  4. import sys
  5. from .util import _wrap, RaiseNotImpl
  6. import expressions, gateways, axdebug, winerror
  7. import pythoncom
  8. from win32com.server.exception import COMException
  9. from .util import trace
  10. #def trace(*args):
  11. # pass
  12. class EnumDebugStackFrames(gateways.EnumDebugStackFrames):
  13. """A class that given a debugger object, can return an enumerator
  14. of DebugStackFrame objects.
  15. """
  16. def __init__(self, debugger):
  17. infos = []
  18. frame = debugger.currentframe
  19. # print "Stack check"
  20. while frame:
  21. # print " Checking frame", frame.f_code.co_filename, frame.f_lineno-1, frame.f_trace,
  22. # Get a DebugCodeContext for the stack frame. If we fail, then it
  23. # is not debuggable, and therefore not worth displaying.
  24. cc = debugger.codeContainerProvider.FromFileName(frame.f_code.co_filename)
  25. if cc is not None:
  26. try:
  27. address = frame.f_locals['__axstack_address__']
  28. except KeyError:
  29. # print "Couldnt find stack address for",frame.f_code.co_filename, frame.f_lineno-1
  30. # Use this one, even tho it is wrong :-(
  31. address = axdebug.GetStackAddress()
  32. frameInfo = DebugStackFrame(frame, frame.f_lineno-1, cc), address, address+1, 0, None
  33. infos.append(frameInfo)
  34. # print "- Kept!"
  35. # else:
  36. # print "- rejected"
  37. frame = frame.f_back
  38. gateways.EnumDebugStackFrames.__init__(self, infos, 0)
  39. # def __del__(self):
  40. # print "EnumDebugStackFrames dieing"
  41. def Next(self, count):
  42. return gateways.EnumDebugStackFrames.Next(self, count)
  43. # def _query_interface_(self, iid):
  44. # from win32com.util import IIDToInterfaceName
  45. # print "EnumDebugStackFrames QI with %s (%s)" % (IIDToInterfaceName(iid), str(iid))
  46. # return 0
  47. def _wrap(self, obj):
  48. # This enum returns a tuple, with 2 com objects in it.
  49. obFrame, min, lim, fFinal, obFinal = obj
  50. obFrame = _wrap(obFrame, axdebug.IID_IDebugStackFrame)
  51. if obFinal:
  52. obFinal = _wrap(obFinal, pythoncom.IID_IUnknown)
  53. return obFrame, min, lim, fFinal, obFinal
  54. class DebugStackFrame(gateways.DebugStackFrame):
  55. def __init__(self, frame, lineno, codeContainer):
  56. self.frame = frame
  57. self.lineno = lineno
  58. self.codeContainer = codeContainer
  59. self.expressionContext = None
  60. # def __del__(self):
  61. # print "DSF dieing"
  62. def _query_interface_(self, iid):
  63. if iid==axdebug.IID_IDebugExpressionContext:
  64. if self.expressionContext is None:
  65. self.expressionContext = _wrap(expressions.ExpressionContext(self.frame), axdebug.IID_IDebugExpressionContext)
  66. return self.expressionContext
  67. # from win32com.util import IIDToInterfaceName
  68. # print "DebugStackFrame QI with %s (%s)" % (IIDToInterfaceName(iid), str(iid))
  69. return 0
  70. #
  71. # The following need implementation
  72. def GetThread(self):
  73. """ Returns the thread associated with this stack frame.
  74. Result must be a IDebugApplicationThread
  75. """
  76. RaiseNotImpl("GetThread")
  77. def GetCodeContext(self):
  78. offset = self.codeContainer.GetPositionOfLine(self.lineno)
  79. return self.codeContainer.GetCodeContextAtPosition(offset)
  80. #
  81. # The following are usefully implemented
  82. def GetDescriptionString(self, fLong):
  83. filename = self.frame.f_code.co_filename
  84. s = ""
  85. if 0: #fLong:
  86. s = s + filename
  87. if self.frame.f_code.co_name:
  88. s = s + self.frame.f_code.co_name
  89. else:
  90. s = s + "<lambda>"
  91. return s
  92. def GetLanguageString(self, fLong):
  93. if fLong:
  94. return "Python ActiveX Scripting Engine"
  95. else:
  96. return "Python"
  97. def GetDebugProperty(self):
  98. return _wrap(StackFrameDebugProperty(self.frame), axdebug.IID_IDebugProperty)
  99. class DebugStackFrameSniffer:
  100. _public_methods_ = ["EnumStackFrames"]
  101. _com_interfaces_ = [axdebug.IID_IDebugStackFrameSniffer]
  102. def __init__(self, debugger):
  103. self.debugger = debugger
  104. trace("DebugStackFrameSniffer instantiated")
  105. # def __del__(self):
  106. # print "DSFS dieing"
  107. def EnumStackFrames(self):
  108. trace("DebugStackFrameSniffer.EnumStackFrames called")
  109. return _wrap(EnumDebugStackFrames(self.debugger), axdebug.IID_IEnumDebugStackFrames)
  110. # A DebugProperty for a stack frame.
  111. class StackFrameDebugProperty:
  112. _com_interfaces_ = [axdebug.IID_IDebugProperty]
  113. _public_methods_ = ['GetPropertyInfo', 'GetExtendedInfo', 'SetValueAsString',
  114. 'EnumMembers', 'GetParent'
  115. ]
  116. def __init__(self, frame):
  117. self.frame = frame
  118. def GetPropertyInfo(self, dwFieldSpec, nRadix):
  119. RaiseNotImpl("StackFrameDebugProperty::GetPropertyInfo")
  120. def GetExtendedInfo(self): ### Note - not in the framework.
  121. RaiseNotImpl("StackFrameDebugProperty::GetExtendedInfo")
  122. def SetValueAsString(self, value, radix):
  123. #
  124. RaiseNotImpl("DebugProperty::SetValueAsString")
  125. def EnumMembers(self, dwFieldSpec, nRadix, iid):
  126. print("EnumMembers", dwFieldSpec, nRadix, iid)
  127. from . import expressions
  128. return expressions.MakeEnumDebugProperty(self.frame.f_locals, dwFieldSpec, nRadix, iid, self.frame)
  129. def GetParent(self):
  130. # return IDebugProperty
  131. RaiseNotImpl("DebugProperty::GetParent")