215 lines
6.5 KiB
Python
215 lines
6.5 KiB
Python
import io
|
|
import string
|
|
import sys
|
|
import traceback
|
|
from pprint import pprint
|
|
|
|
import winerror
|
|
from win32com.server.exception import COMException
|
|
|
|
from . import axdebug, gateways
|
|
from .util import RaiseNotImpl, _wrap, _wrap_remove
|
|
|
|
|
|
# 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")
|