2024-10-02 22:15:59 +04:00

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")