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