156 lines
6.1 KiB
Python
156 lines
6.1 KiB
Python
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")
|