Debugger: Some dumper code cosmetics

Mostly quotes, remove some unneeded comments, ...

Change-Id: Ie3f410ac84e6cfe48e7971af948326abc21f2554
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
hjk
2016-11-01 09:03:45 +01:00
parent 67505423e6
commit 5fb2dc6e47
2 changed files with 233 additions and 242 deletions

View File

@@ -48,13 +48,13 @@ def safePrint(output):
try: try:
print(output) print(output)
except: except:
out = "" out = ''
for c in output: for c in output:
cc = ord(c) cc = ord(c)
if cc > 127: if cc > 127:
out += "\\\\%d" % cc out += '\\\\%d' % cc
elif cc < 0: elif cc < 0:
out += "\\\\%d" % (cc + 256) out += '\\\\%d' % (cc + 256)
else: else:
out += c out += c
print(out) print(out)
@@ -80,7 +80,7 @@ def registerCommand(name, func):
# Just convienience for 'python print ...' # Just convienience for 'python print ...'
class PPCommand(gdb.Command): class PPCommand(gdb.Command):
def __init__(self): def __init__(self):
super(PPCommand, self).__init__("pp", gdb.COMMAND_OBSCURE) super(PPCommand, self).__init__('pp', gdb.COMMAND_OBSCURE)
def invoke(self, args, from_tty): def invoke(self, args, from_tty):
print(eval(args)) print(eval(args))
@@ -89,7 +89,7 @@ PPCommand()
# Just convienience for 'python print gdb.parse_and_eval(...)' # Just convienience for 'python print gdb.parse_and_eval(...)'
class PPPCommand(gdb.Command): class PPPCommand(gdb.Command):
def __init__(self): def __init__(self):
super(PPPCommand, self).__init__("ppp", gdb.COMMAND_OBSCURE) super(PPPCommand, self).__init__('ppp', gdb.COMMAND_OBSCURE)
def invoke(self, args, from_tty): def invoke(self, args, from_tty):
print(gdb.parse_and_eval(args)) print(gdb.parse_and_eval(args))
@@ -100,20 +100,20 @@ def scanStack(p, n):
p = int(p) p = int(p)
r = [] r = []
for i in xrange(n): for i in xrange(n):
f = gdb.parse_and_eval("{void*}%s" % p) f = gdb.parse_and_eval('{void*}%s' % p)
m = gdb.execute("info symbol %s" % f, to_string=True) m = gdb.execute('info symbol %s' % f, to_string=True)
if not m.startswith("No symbol matches"): if not m.startswith('No symbol matches'):
r.append(m) r.append(m)
p += f.type.sizeof p += f.type.sizeof
return r return r
class ScanStackCommand(gdb.Command): class ScanStackCommand(gdb.Command):
def __init__(self): def __init__(self):
super(ScanStackCommand, self).__init__("scanStack", gdb.COMMAND_OBSCURE) super(ScanStackCommand, self).__init__('scanStack', gdb.COMMAND_OBSCURE)
def invoke(self, args, from_tty): def invoke(self, args, from_tty):
if len(args) == 0: if len(args) == 0:
args = 20 args = 20
safePrint(scanStack(gdb.parse_and_eval("$sp"), int(args))) safePrint(scanStack(gdb.parse_and_eval('$sp'), int(args)))
ScanStackCommand() ScanStackCommand()
@@ -134,7 +134,7 @@ class PlainDumper:
printer = self.printer.gen_printer(value) printer = self.printer.gen_printer(value)
except: except:
printer = self.printer.invoke(value) printer = self.printer.invoke(value)
lister = getattr(printer, "children", None) lister = getattr(printer, 'children', None)
children = [] if lister is None else list(lister()) children = [] if lister is None else list(lister())
d.putType(self.printer.name) d.putType(self.printer.name)
val = printer.to_string() val = printer.to_string()
@@ -152,16 +152,16 @@ class PlainDumper:
d.putSubItem(child[0], child[1]) d.putSubItem(child[0], child[1])
def importPlainDumpers(args): def importPlainDumpers(args):
if args == "off": if args == 'off':
try: try:
gdb.execute("disable pretty-printer .* .*") gdb.execute('disable pretty-printer .* .*')
except: except:
# Might occur in non-ASCII directories # Might occur in non-ASCII directories
warn("COULD NOT DISABLE PRETTY PRINTERS") warn('COULD NOT DISABLE PRETTY PRINTERS')
else: else:
theDumper.importPlainDumpers() theDumper.importPlainDumpers()
registerCommand("importPlainDumpers", importPlainDumpers) registerCommand('importPlainDumpers', importPlainDumpers)
@@ -175,7 +175,7 @@ class OutputSafer:
def __exit__(self, exType, exValue, exTraceBack): def __exit__(self, exType, exValue, exTraceBack):
if self.d.passExceptions and not exType is None: if self.d.passExceptions and not exType is None:
showException("OUTPUTSAFER", exType, exValue, exTraceBack) showException('OUTPUTSAFER', exType, exValue, exTraceBack)
self.d.output = self.savedOutput self.d.output = self.savedOutput
else: else:
self.savedOutput.extend(self.d.output) self.savedOutput.extend(self.d.output)
@@ -206,7 +206,7 @@ class Dumper(DumperBase):
self.setVariableFetchingOptions(args) self.setVariableFetchingOptions(args)
def fromFrameValue(self, nativeValue): def fromFrameValue(self, nativeValue):
#warn("FROM FRAME VALUE: %s" % nativeValue.address) #warn('FROM FRAME VALUE: %s' % nativeValue.address)
val = nativeValue val = nativeValue
try: try:
val = nativeValue.cast(nativeValue.dynamic_type) val = nativeValue.cast(nativeValue.dynamic_type)
@@ -215,14 +215,14 @@ class Dumper(DumperBase):
return self.fromNativeValue(val) return self.fromNativeValue(val)
def fromNativeValue(self, nativeValue): def fromNativeValue(self, nativeValue):
#warn("FROM NATIVE VALUE: %s" % nativeValue.address) #warn('FROM NATIVE VALUE: %s' % nativeValue)
self.check(isinstance(nativeValue, gdb.Value)) self.check(isinstance(nativeValue, gdb.Value))
nativeType = nativeValue.type nativeType = nativeValue.type
code = nativeType.code code = nativeType.code
if code == gdb.TYPE_CODE_REF: if code == gdb.TYPE_CODE_REF:
targetType = self.fromNativeType(nativeType.target().unqualified(), nativeValue) targetType = self.fromNativeType(nativeType.target().unqualified(), nativeValue)
val = self.createReferenceValue(toInteger(nativeValue.address), targetType) val = self.createReferenceValue(toInteger(nativeValue.address), targetType)
#warn("CREATED REF: %s" % val) #warn('CREATED REF: %s' % val)
return val return val
if code == gdb.TYPE_CODE_PTR: if code == gdb.TYPE_CODE_PTR:
try: try:
@@ -231,14 +231,14 @@ class Dumper(DumperBase):
nativeTargetValue = None nativeTargetValue = None
targetType = self.fromNativeType(nativeType.target().unqualified(), nativeTargetValue) targetType = self.fromNativeType(nativeType.target().unqualified(), nativeTargetValue)
val = self.createPointerValue(toInteger(nativeValue), targetType) val = self.createPointerValue(toInteger(nativeValue), targetType)
#warn("CREATED PTR 1: %s" % val) #warn('CREATED PTR 1: %s' % val)
if not nativeValue.address is None: if not nativeValue.address is None:
val.laddress = toInteger(nativeValue.address) val.laddress = toInteger(nativeValue.address)
#warn("CREATED PTR 2: %s" % val) #warn('CREATED PTR 2: %s' % val)
return val return val
if code == gdb.TYPE_CODE_TYPEDEF: if code == gdb.TYPE_CODE_TYPEDEF:
targetType = nativeType.strip_typedefs().unqualified() targetType = nativeType.strip_typedefs().unqualified()
#warn("TARGET TYPE: %s" % targetType) #warn('TARGET TYPE: %s' % targetType)
if targetType.code == gdb.TYPE_CODE_ARRAY: if targetType.code == gdb.TYPE_CODE_ARRAY:
val = self.Value(self) val = self.Value(self)
val.laddress = toInteger(nativeValue.address) val.laddress = toInteger(nativeValue.address)
@@ -246,7 +246,7 @@ class Dumper(DumperBase):
# Cast may fail (e.g for arrays, see test for Bug5799) # Cast may fail (e.g for arrays, see test for Bug5799)
val = self.fromNativeValue(nativeValue.cast(targetType)) val = self.fromNativeValue(nativeValue.cast(targetType))
val.type = self.fromNativeType(nativeType, nativeValue) val.type = self.fromNativeType(nativeType, nativeValue)
#warn("CREATED TYPEDEF: %s" % val) #warn('CREATED TYPEDEF: %s' % val)
return val return val
val = self.Value(self) val = self.Value(self)
@@ -254,7 +254,7 @@ class Dumper(DumperBase):
val.laddress = toInteger(nativeValue.address) val.laddress = toInteger(nativeValue.address)
else: else:
size = nativeType.sizeof size = nativeType.sizeof
chars = self.lookupNativeType("unsigned char") chars = self.lookupNativeType('unsigned char')
y = nativeValue.cast(chars.array(0, int(nativeType.sizeof - 1))) y = nativeValue.cast(chars.array(0, int(nativeType.sizeof - 1)))
buf = bytearray(struct.pack('x' * size)) buf = bytearray(struct.pack('x' * size))
for i in range(size): for i in range(size):
@@ -400,7 +400,7 @@ class Dumper(DumperBase):
def nativeStructAlignment(self, nativeType): def nativeStructAlignment(self, nativeType):
self.preping('align ' + str(nativeType)) self.preping('align ' + str(nativeType))
#warn("NATIVE ALIGN FOR %s" % nativeType.name) #warn('NATIVE ALIGN FOR %s' % nativeType.name)
def handleItem(nativeFieldType, align): def handleItem(nativeFieldType, align):
a = self.fromNativeType(nativeFieldType).alignment() a = self.fromNativeType(nativeFieldType).alignment()
return a if a > align else align return a if a > align else align
@@ -460,7 +460,7 @@ class Dumper(DumperBase):
return None return None
def listMembers(self, nativeType, nativeValue): def listMembers(self, nativeType, nativeValue):
#warn("LISTING MEMBERS OF %s" % nativeType) #warn('LISTING MEMBERS OF %s' % nativeType)
try: try:
nativeValueAddress = toInteger(nativeValue.address) nativeValueAddress = toInteger(nativeValue.address)
except: except:
@@ -565,13 +565,13 @@ class Dumper(DumperBase):
#warn(' NATIVE MEMBER ADDRESS: 0x%x' % nativeMemberAddress) #warn(' NATIVE MEMBER ADDRESS: 0x%x' % nativeMemberAddress)
offset = nativeMemberAddress - nativeBaseAddress offset = nativeMemberAddress - nativeBaseAddress
#offset = bpbase + nativeField.bitpos #offset = bpbase + nativeField.bitpos
#warn("DEEP OFFSET: %s POS: %s" % (offset // 8, field.lbitpos // 8)) #warn('DEEP OFFSET: %s POS: %s' % (offset // 8, field.lbitpos // 8))
field.lbitpos = offset * 8 field.lbitpos = offset * 8
except: except:
field.lbitpos = None field.lbitpos = None
field.lvalue = "XXX" field.lvalue = 'XXX'
#else: #else:
# warn("REUSING BITPOS %s FOR %s" % (field.lbitpos, field.name)) # warn('REUSING BITPOS %s FOR %s' % (field.lbitpos, field.name))
fields.append(field) fields.append(field)
return fields return fields
@@ -601,20 +601,20 @@ class Dumper(DumperBase):
if symbol.is_variable or symbol.is_argument: if symbol.is_variable or symbol.is_argument:
name = symbol.print_name name = symbol.print_name
if name == "__in_chrg" or name == "__PRETTY_FUNCTION__": if name in ('__in_chrg', '__PRETTY_FUNCTION__'):
continue continue
if not partialVar is None and partialVar != name: if not partialVar is None and partialVar != name:
continue continue
# "NotImplementedError: Symbol type not yet supported in # 'NotImplementedError: Symbol type not yet supported in
# Python scripts." # Python scripts.'
#warn("SYMBOL %s (%s, %s)): " % (symbol, name, symbol.name)) #warn('SYMBOL %s (%s, %s)): ' % (symbol, name, symbol.name))
if self.passExceptions and not self.isTesting: if self.passExceptions and not self.isTesting:
nativeValue = frame.read_var(name, block) nativeValue = frame.read_var(name, block)
value = self.fromFrameValue(nativeValue) value = self.fromFrameValue(nativeValue)
value.name = name value.name = name
#warn("READ 0: %s" % value.stringify()) #warn('READ 0: %s' % value.stringify())
items.append(value) items.append(value)
continue continue
@@ -623,14 +623,14 @@ class Dumper(DumperBase):
nativeValue = frame.read_var(name, block) nativeValue = frame.read_var(name, block)
value = self.fromFrameValue(nativeValue) value = self.fromFrameValue(nativeValue)
value.name = name value.name = name
#warn('READ 1: %s' % value.stringify())
items.append(value) items.append(value)
#warn("READ 1: %s" % value.stringify())
continue continue
except: except:
pass pass
try: try:
#warn("READ 2: %s" % item.value) #warn('READ 2: %s' % item.value)
value = self.fromFrameValue(frame.read_var(name)) value = self.fromFrameValue(frame.read_var(name))
value.name = name value.name = name
items.append(value) items.append(value)
@@ -644,15 +644,15 @@ class Dumper(DumperBase):
pass pass
try: try:
#warn("READ 3: %s %s" % (name, item.value)) #warn('READ 3: %s %s' % (name, item.value))
#warn("ITEM 3: %s" % item.value) #warn('ITEM 3: %s' % item.value)
value = self.fromFrameValue(gdb.parse_and_eval(name)) value = self.fromFrameValue(gdb.parse_and_eval(name))
value.name = name value.name = name
items.append(value) items.append(value)
except: except:
# Can happen in inlined code (see last line of # Can happen in inlined code (see last line of
# RowPainter::paintChars(): "RuntimeError: # RowPainter::paintChars(): 'RuntimeError:
# No symbol \"__val\" in current context.\n" # No symbol '__val' in current context.\n'
pass pass
# The outermost block in a function has the function member # The outermost block in a function has the function member
@@ -686,19 +686,19 @@ class Dumper(DumperBase):
self.output.append('data=[') self.output.append('data=[')
partialVar = args.get("partialvar", "") partialVar = args.get('partialvar', '')
isPartial = len(partialVar) > 0 isPartial = len(partialVar) > 0
partialName = partialVar.split('.')[1].split('@')[0] if isPartial else None partialName = partialVar.split('.')[1].split('@')[0] if isPartial else None
variables = self.listLocals(partialName) variables = self.listLocals(partialName)
#warn("VARIABLES: %s" % variables) #warn('VARIABLES: %s' % variables)
# Take care of the return value of the last function call. # Take care of the return value of the last function call.
if len(self.resultVarName) > 0: if len(self.resultVarName) > 0:
try: try:
value = self.parseAndEvaluate(self.resultVarName) value = self.parseAndEvaluate(self.resultVarName)
value.name = self.resultVarName value.name = self.resultVarName
value.iname = "return." + self.resultVarName value.iname = 'return.' + self.resultVarName
variables.append(value) variables.append(value)
except: except:
# Don't bother. It's only supplementary information anyway. # Don't bother. It's only supplementary information anyway.
@@ -732,7 +732,7 @@ class Dumper(DumperBase):
safePrint('"%s"' % str(self.dumpStats())) safePrint('"%s"' % str(self.dumpStats()))
def parseAndEvaluate(self, exp): def parseAndEvaluate(self, exp):
#warn("EVALUATE '%s'" % exp) #warn('EVALUATE '%s'' % exp)
try: try:
val = gdb.parse_and_eval(exp) val = gdb.parse_and_eval(exp)
except RuntimeError as error: except RuntimeError as error:
@@ -743,7 +743,7 @@ class Dumper(DumperBase):
def callHelper(self, rettype, value, function, args): def callHelper(self, rettype, value, function, args):
# args is a tuple. # args is a tuple.
arg = "" arg = ''
for i in range(len(args)): for i in range(len(args)):
if i: if i:
arg += ',' arg += ','
@@ -753,41 +753,38 @@ class Dumper(DumperBase):
else: else:
arg += a arg += a
#warn("CALL: %s -> %s(%s)" % (value, function, arg)) #warn('CALL: %s -> %s(%s)' % (value, function, arg))
typeName = value.type.name typeName = value.type.name
if typeName.find(":") >= 0: if typeName.find(':') >= 0:
typeName = "'" + typeName + "'" typeName = "'" + typeName + "'"
# 'class' is needed, see http://sourceware.org/bugzilla/show_bug.cgi?id=11912 # 'class' is needed, see http://sourceware.org/bugzilla/show_bug.cgi?id=11912
#exp = "((class %s*)%s)->%s(%s)" % (typeName, value.laddress, function, arg) #exp = '((class %s*)%s)->%s(%s)' % (typeName, value.laddress, function, arg)
addr = value.laddress addr = value.laddress
if addr is None: if addr is None:
addr = self.pokeValue(value) addr = self.pokeValue(value)
#warn("PTR: %s -> %s(%s)" % (value, function, addr)) #warn('PTR: %s -> %s(%s)' % (value, function, addr))
exp = "((%s*)0x%x)->%s(%s)" % (typeName, addr, function, arg) exp = '((%s*)0x%x)->%s(%s)' % (typeName, addr, function, arg)
#warn("CALL: %s" % exp) #warn("CALL: %s" % exp)
result = gdb.parse_and_eval(exp) result = gdb.parse_and_eval(exp)
warn(" -> %s" % result) #warn(' -> %s' % result)
res = self.fromNativeValue(result) res = self.fromNativeValue(result)
if value.laddress is None: if value.laddress is None:
self.releaseValue(addr) self.releaseValue(addr)
return res return res
def makeExpression(self, value): def makeExpression(self, value):
typename = "::" + value.type.name typename = '::' + value.type.name
#warn(" TYPE: %s" % typename) #warn(' TYPE: %s' % typename)
exp = "(*(%s*)(0x%x))" % (typename, value.address()) exp = '(*(%s*)(0x%x))' % (typename, value.address())
#warn(" EXP: %s" % exp) #warn(' EXP: %s' % exp)
return exp return exp
def makeStdString(init): def makeStdString(init):
# Works only for small allocators, but they are usually empty. # Works only for small allocators, but they are usually empty.
gdb.execute("set $d=(std::string*)calloc(sizeof(std::string), 2)"); gdb.execute('set $d=(std::string*)calloc(sizeof(std::string), 2)');
gdb.execute("call($d->basic_string(\"" + init + gdb.execute('call($d->basic_string("' + init +
"\",*(std::allocator<char>*)(1+$d)))") '",*(std::allocator<char>*)(1+$d)))')
value = gdb.parse_and_eval("$d").dereference() value = gdb.parse_and_eval('$d').dereference()
#warn(" TYPE: %s" % value.type)
#warn(" ADDR: %s" % value.address)
#warn(" VALUE: %s" % value)
return value return value
def pokeValue(self, value): def pokeValue(self, value):
@@ -801,20 +798,20 @@ class Dumper(DumperBase):
string = ''.join("\\x" + h[2*i:2*i+2] for i in range(size)) string = ''.join("\\x" + h[2*i:2*i+2] for i in range(size))
exp = '(%s*)memcpy(calloc(%d, 1), "%s", %d)' \ exp = '(%s*)memcpy(calloc(%d, 1), "%s", %d)' \
% (value.type.name, size, string, size) % (value.type.name, size, string, size)
#warn("EXP: %s" % exp) #warn('EXP: %s' % exp)
res = gdb.parse_and_eval(exp) res = gdb.parse_and_eval(exp)
#warn("RES: %s" % res) #warn('RES: %s' % res)
return toInteger(res) return toInteger(res)
def releaseValue(self, address): def releaseValue(self, address):
gdb.parse_and_eval('free(0x%x)' % address) gdb.parse_and_eval('free(0x%x)' % address)
def setValue(self, address, typename, value): def setValue(self, address, typename, value):
cmd = "set {%s}%s=%s" % (typename, address, value) cmd = 'set {%s}%s=%s' % (typename, address, value)
gdb.execute(cmd) gdb.execute(cmd)
def setValues(self, address, typename, values): def setValues(self, address, typename, values):
cmd = "set {%s[%s]}%s={%s}" \ cmd = 'set {%s[%s]}%s={%s}' \
% (typename, len(values), address, ','.join(map(str, values))) % (typename, len(values), address, ','.join(map(str, values)))
gdb.execute(cmd) gdb.execute(cmd)
@@ -840,7 +837,7 @@ class Dumper(DumperBase):
return res return res
def findStaticMetaObject(self, typename): def findStaticMetaObject(self, typename):
symbolName = typename + "::staticMetaObject" symbolName = typename + '::staticMetaObject'
symbol = gdb.lookup_global_symbol(symbolName, gdb.SYMBOL_VAR_DOMAIN) symbol = gdb.lookup_global_symbol(symbolName, gdb.SYMBOL_VAR_DOMAIN)
if not symbol: if not symbol:
return 0 return 0
@@ -877,7 +874,7 @@ class Dumper(DumperBase):
def qtVersionString(self): def qtVersionString(self):
try: try:
return str(gdb.lookup_symbol("qVersion")[0].value()()) return str(gdb.lookup_symbol('qVersion')[0].value()())
except: except:
pass pass
try: try:
@@ -890,7 +887,7 @@ class Dumper(DumperBase):
def qtVersion(self): def qtVersion(self):
try: try:
# Only available with Qt 5.3+ # Only available with Qt 5.3+
qtversion = int(str(gdb.parse_and_eval("((void**)&qtHookData)[2]")), 16) qtversion = int(str(gdb.parse_and_eval('((void**)&qtHookData)[2]')), 16)
self.qtVersion = lambda: qtversion self.qtVersion = lambda: qtversion
return qtversion return qtversion
except: except:
@@ -922,24 +919,24 @@ class Dumper(DumperBase):
# FIXME: ns is accessed too early. gdb.Breakpoint() has no # FIXME: ns is accessed too early. gdb.Breakpoint() has no
# 'rbreak' replacement, and breakpoints created with # 'rbreak' replacement, and breakpoints created with
# 'gdb.execute("rbreak...") cannot be made invisible. # 'gdb.execute('rbreak...') cannot be made invisible.
# So let's ignore the existing of namespaced builds for this # So let's ignore the existing of namespaced builds for this
# fringe feature here for now. # fringe feature here for now.
ns = self.qtNamespace() ns = self.qtNamespace()
if args.get('breakonabort', 0): if args.get('breakonabort', 0):
self.specialBreakpoints.append(newSpecial("abort")) self.specialBreakpoints.append(newSpecial('abort'))
if args.get('breakonwarning', 0): if args.get('breakonwarning', 0):
self.specialBreakpoints.append(newSpecial(ns + "qWarning")) self.specialBreakpoints.append(newSpecial(ns + 'qWarning'))
self.specialBreakpoints.append(newSpecial(ns + "QMessageLogger::warning")) self.specialBreakpoints.append(newSpecial(ns + 'QMessageLogger::warning'))
if args.get('breakonfatal', 0): if args.get('breakonfatal', 0):
self.specialBreakpoints.append(newSpecial(ns + "qFatal")) self.specialBreakpoints.append(newSpecial(ns + 'qFatal'))
self.specialBreakpoints.append(newSpecial(ns + "QMessageLogger::fatal")) self.specialBreakpoints.append(newSpecial(ns + 'QMessageLogger::fatal'))
#def threadname(self, maximalStackDepth, objectPrivateType): #def threadname(self, maximalStackDepth, objectPrivateType):
# e = gdb.selected_frame() # e = gdb.selected_frame()
# out = "" # out = ''
# ns = self.qtNamespace() # ns = self.qtNamespace()
# while True: # while True:
# maximalStackDepth -= 1 # maximalStackDepth -= 1
@@ -948,17 +945,16 @@ class Dumper(DumperBase):
# e = e.older() # e = e.older()
# if e == None or e.name() == None: # if e == None or e.name() == None:
# break # break
# if e.name() == ns + "QThreadPrivate::start" \ # if e.name() in (ns + 'QThreadPrivate::start', '_ZN14QThreadPrivate5startEPv@4'):
# or e.name() == "_ZN14QThreadPrivate5startEPv@4":
# try: # try:
# thrptr = e.read_var("thr").dereference() # thrptr = e.read_var('thr').dereference()
# d_ptr = thrptr["d_ptr"]["d"].cast(objectPrivateType).dereference() # d_ptr = thrptr['d_ptr']['d'].cast(objectPrivateType).dereference()
# try: # try:
# objectName = d_ptr["objectName"] # objectName = d_ptr['objectName']
# except: # Qt 5 # except: # Qt 5
# p = d_ptr["extraData"] # p = d_ptr['extraData']
# if not self.isNull(p): # if not self.isNull(p):
# objectName = p.dereference()["objectName"] # objectName = p.dereference()['objectName']
# if not objectName is None: # if not objectName is None:
# (data, size, alloc) = self.stringData(objectName) # (data, size, alloc) = self.stringData(objectName)
# if size > 0: # if size > 0:
@@ -997,9 +993,9 @@ class Dumper(DumperBase):
def importPlainDumper(self, printer): def importPlainDumper(self, printer):
name = printer.name.replace("::", "__") name = printer.name.replace('::', '__')
self.qqDumpers[name] = PlainDumper(printer) self.qqDumpers[name] = PlainDumper(printer)
self.qqFormats[name] = "" self.qqFormats[name] = ''
def importPlainDumpers(self): def importPlainDumpers(self):
for obj in gdb.objfiles(): for obj in gdb.objfiles():
@@ -1019,7 +1015,7 @@ class Dumper(DumperBase):
# This only works when called from a valid frame. # This only works when called from a valid frame.
try: try:
cand = "QArrayData::shared_null" cand = 'QArrayData::shared_null'
symbol = gdb.lookup_symbol(cand)[0] symbol = gdb.lookup_symbol(cand)[0]
if symbol: if symbol:
ns = symbol.name[:-len(cand)] ns = symbol.name[:-len(cand)]
@@ -1031,7 +1027,7 @@ class Dumper(DumperBase):
try: try:
# This is Qt, but not 5.x. # This is Qt, but not 5.x.
cand = "QByteArray::shared_null" cand = 'QByteArray::shared_null'
symbol = gdb.lookup_symbol(cand)[0] symbol = gdb.lookup_symbol(cand)[0]
if symbol: if symbol:
ns = symbol.name[:-len(cand)] ns = symbol.name[:-len(cand)]
@@ -1053,7 +1049,7 @@ class Dumper(DumperBase):
ns = self.qtNamespace() ns = self.qtNamespace()
if typeName.startswith(ns): if typeName.startswith(ns):
typeName = typeName[len(ns):] typeName = typeName[len(ns):]
typeName = typeName.replace("::", "__") typeName = typeName.replace('::', '__')
pos = typeName.find('<') pos = typeName.find('<')
if pos != -1: if pos != -1:
typeName = typeName[0:pos] typeName = typeName[0:pos]
@@ -1062,7 +1058,7 @@ class Dumper(DumperBase):
expr = gdb.parse_and_eval(expr) expr = gdb.parse_and_eval(expr)
self.qqEditable[typeName](self, expr, value) self.qqEditable[typeName](self, expr, value)
else: else:
cmd = "set variable (%s)=%s" % (expr, value) cmd = 'set variable (%s)=%s' % (expr, value)
gdb.execute(cmd) gdb.execute(cmd)
def nativeDynamicTypeName(self, address, baseType): def nativeDynamicTypeName(self, address, baseType):
@@ -1075,14 +1071,14 @@ class Dumper(DumperBase):
val = nativeValue.cast(nativeValue.dynamic_type) val = nativeValue.cast(nativeValue.dynamic_type)
return str(val.type) return str(val.type)
#try: #try:
# vtbl = gdb.execute("info symbol {%s*}0x%x" % (baseType.name, address), to_string = True) # vtbl = gdb.execute('info symbol {%s*}0x%x' % (baseType.name, address), to_string = True)
#except: #except:
# return None # return None
#pos1 = vtbl.find("vtable ") #pos1 = vtbl.find('vtable ')
#if pos1 == -1: #if pos1 == -1:
# return None # return None
#pos1 += 11 #pos1 += 11
#pos2 = vtbl.find(" +", pos1) #pos2 = vtbl.find(' +', pos1)
#if pos2 == -1: #if pos2 == -1:
# return None # return None
#return vtbl[pos1 : pos2] #return vtbl[pos1 : pos2]
@@ -1097,7 +1093,7 @@ class Dumper(DumperBase):
return self.fromNativeType(nativeValue.dynamic_type) return self.fromNativeType(nativeValue.dynamic_type)
def enumExpression(self, enumType, enumValue): def enumExpression(self, enumType, enumValue):
return self.qtNamespace() + "Qt::" + enumValue return self.qtNamespace() + 'Qt::' + enumValue
def lookupNativeType(self, typeName): def lookupNativeType(self, typeName):
nativeType = self.lookupNativeTypeHelper(typeName) nativeType = self.lookupNativeTypeHelper(typeName)
@@ -1107,18 +1103,18 @@ class Dumper(DumperBase):
def lookupNativeTypeHelper(self, typeName): def lookupNativeTypeHelper(self, typeName):
typeobj = self.typeCache.get(typeName) typeobj = self.typeCache.get(typeName)
#warn("LOOKUP 1: %s -> %s" % (typeName, typeobj)) #warn('LOOKUP 1: %s -> %s' % (typeName, typeobj))
if not typeobj is None: if not typeobj is None:
return typeobj return typeobj
if typeName == "void": if typeName == 'void':
typeobj = gdb.lookup_type(typeName) typeobj = gdb.lookup_type(typeName)
self.typeCache[typeName] = typeobj self.typeCache[typeName] = typeobj
self.typesToReport[typeName] = typeobj self.typesToReport[typeName] = typeobj
return typeobj return typeobj
#try: #try:
# typeobj = gdb.parse_and_eval("{%s}&main" % typeName).typeobj # typeobj = gdb.parse_and_eval('{%s}&main' % typeName).typeobj
# if not typeobj is None: # if not typeobj is None:
# self.typeCache[typeName] = typeobj # self.typeCache[typeName] = typeobj
# self.typesToReport[typeName] = typeobj # self.typesToReport[typeName] = typeobj
@@ -1127,12 +1123,12 @@ class Dumper(DumperBase):
# pass # pass
# See http://sourceware.org/bugzilla/show_bug.cgi?id=13269 # See http://sourceware.org/bugzilla/show_bug.cgi?id=13269
# gcc produces "{anonymous}", gdb "(anonymous namespace)" # gcc produces '{anonymous}', gdb '(anonymous namespace)'
# "<unnamed>" has been seen too. The only thing gdb # '<unnamed>' has been seen too. The only thing gdb
# understands when reading things back is "(anonymous namespace)" # understands when reading things back is '(anonymous namespace)'
if typeName.find("{anonymous}") != -1: if typeName.find('{anonymous}') != -1:
ts = typeName ts = typeName
ts = ts.replace("{anonymous}", "(anonymous namespace)") ts = ts.replace('{anonymous}', '(anonymous namespace)')
typeobj = self.lookupNativeType(ts) typeobj = self.lookupNativeType(ts)
if not typeobj is None: if not typeobj is None:
self.typeCache[typeName] = typeobj self.typeCache[typeName] = typeobj
@@ -1147,24 +1143,23 @@ class Dumper(DumperBase):
ts = typeName ts = typeName
while True: while True:
#warn("TS: '%s'" % ts) if ts.startswith('class '):
if ts.startswith("class "):
ts = ts[6:] ts = ts[6:]
elif ts.startswith("struct "): elif ts.startswith('struct '):
ts = ts[7:] ts = ts[7:]
elif ts.startswith("const "): elif ts.startswith('const '):
ts = ts[6:] ts = ts[6:]
elif ts.startswith("volatile "): elif ts.startswith('volatile '):
ts = ts[9:] ts = ts[9:]
elif ts.startswith("enum "): elif ts.startswith('enum '):
ts = ts[5:] ts = ts[5:]
elif ts.endswith(" const"): elif ts.endswith(' const'):
ts = ts[:-6] ts = ts[:-6]
elif ts.endswith(" volatile"): elif ts.endswith(' volatile'):
ts = ts[:-9] ts = ts[:-9]
elif ts.endswith("*const"): elif ts.endswith('*const'):
ts = ts[:-5] ts = ts[:-5]
elif ts.endswith("*volatile"): elif ts.endswith('*volatile'):
ts = ts[:-8] ts = ts[:-8]
else: else:
break break
@@ -1188,19 +1183,19 @@ class Dumper(DumperBase):
typeobj = self.parse_and_eval(exp).type.target() typeobj = self.parse_and_eval(exp).type.target()
#warn("LOOKING UP 3 '%s'" % typeobj) #warn("LOOKING UP 3 '%s'" % typeobj)
except: except:
# Can throw "RuntimeError: No type named class Foo." # Can throw 'RuntimeError: No type named class Foo.'
pass pass
except: except:
#warn("LOOKING UP '%s' FAILED" % ts) #warn("LOOKING UP '%s' FAILED" % ts)
pass pass
if not typeobj is None: if not typeobj is None:
#warn("CACHING: %s" % typeobj) #warn('CACHING: %s' % typeobj)
self.typeCache[typeName] = typeobj self.typeCache[typeName] = typeobj
self.typesToReport[typeName] = typeobj self.typesToReport[typeName] = typeobj
# This could still be None as gdb.lookup_type("char[3]") generates # This could still be None as gdb.lookup_type('char[3]') generates
# "RuntimeError: No type named char[3]" # 'RuntimeError: No type named char[3]'
#self.typeCache[typeName] = typeobj #self.typeCache[typeName] = typeobj
#self.typesToReport[typeName] = typeobj #self.typesToReport[typeName] = typeobj
return typeobj return typeobj
@@ -1225,7 +1220,7 @@ class Dumper(DumperBase):
frame = gdb.newest_frame() frame = gdb.newest_frame()
ns = self.qtNamespace() ns = self.qtNamespace()
needle = self.qtNamespace() + 'QV4::ExecutionEngine' needle = self.qtNamespace() + 'QV4::ExecutionEngine'
pat = "%sqt_v4StackTrace(((%sQV4::ExecutionEngine *)0x%x)->currentContext)" pat = '%sqt_v4StackTrace(((%sQV4::ExecutionEngine *)0x%x)->currentContext)'
done = False done = False
while i < limit and frame and not done: while i < limit and frame and not done:
block = None block = None
@@ -1260,10 +1255,10 @@ class Dumper(DumperBase):
while i < limit and frame: while i < limit and frame:
with OutputSafer(self): with OutputSafer(self):
name = frame.name() name = frame.name()
functionName = "??" if name is None else name functionName = '??' if name is None else name
fileName = "" fileName = ''
objfile = "" objfile = ''
symtab = "" symtab = ''
pc = frame.pc() pc = frame.pc()
sal = frame.find_sal() sal = frame.find_sal()
line = -1 line = -1
@@ -1274,13 +1269,13 @@ class Dumper(DumperBase):
objfile = fromNativePath(symtab.objfile.filename) objfile = fromNativePath(symtab.objfile.filename)
fullname = symtab.fullname() fullname = symtab.fullname()
if fullname is None: if fullname is None:
fileName = "" fileName = ''
else: else:
fileName = fromNativePath(fullname) fileName = fromNativePath(fullname)
if self.nativeMixed and functionName == "qt_qmlDebugMessageAvailable": if self.nativeMixed and functionName == 'qt_qmlDebugMessageAvailable':
interpreterStack = self.extractInterpreterStack() interpreterStack = self.extractInterpreterStack()
#print("EXTRACTED INTEPRETER STACK: %s" % interpreterStack) #print('EXTRACTED INTEPRETER STACK: %s' % interpreterStack)
for interpreterFrame in interpreterStack.get('frames', []): for interpreterFrame in interpreterStack.get('frames', []):
function = interpreterFrame.get('function', '') function = interpreterFrame.get('function', '')
fileName = interpreterFrame.get('file', '') fileName = interpreterFrame.get('file', '')
@@ -1315,7 +1310,7 @@ class Dumper(DumperBase):
def __init__(self, dumper, args): def __init__(self, dumper, args):
self.dumper = dumper self.dumper = dumper
self.args = args self.args = args
spec = "qt_qmlDebugConnectorOpen" spec = 'qt_qmlDebugConnectorOpen'
super(Resolver, self).\ super(Resolver, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True, temporary=False) __init__(spec, gdb.BP_BREAKPOINT, internal=True, temporary=False)
@@ -1327,16 +1322,16 @@ class Dumper(DumperBase):
self.interpreterBreakpointResolvers.append(Resolver(self, args)) self.interpreterBreakpointResolvers.append(Resolver(self, args))
def exitGdb(self, _): def exitGdb(self, _):
gdb.execute("quit") gdb.execute('quit')
def reportResult(self, msg, args): def reportResult(self, msg, args):
print(msg) print(msg)
def profile1(self, args): def profile1(self, args):
"""Internal profiling""" '''Internal profiling'''
import tempfile import tempfile
import cProfile import cProfile
tempDir = tempfile.gettempdir() + "/bbprof" tempDir = tempfile.gettempdir() + '/bbprof'
cProfile.run('theDumper.fetchVariables(%s)' % args, tempDir) cProfile.run('theDumper.fetchVariables(%s)' % args, tempDir)
import pstats import pstats
pstats.Stats(tempDir).sort_stats('time').print_stats() pstats.Stats(tempDir).sort_stats('time').print_stats()
@@ -1398,7 +1393,7 @@ theDumper = Dumper()
def threadnames(arg): def threadnames(arg):
return theDumper.threadnames(int(arg)) return theDumper.threadnames(int(arg))
registerCommand("threadnames", threadnames) registerCommand('threadnames', threadnames)
####################################################################### #######################################################################
# #
@@ -1408,12 +1403,12 @@ registerCommand("threadnames", threadnames)
class InterpreterMessageBreakpoint(gdb.Breakpoint): class InterpreterMessageBreakpoint(gdb.Breakpoint):
def __init__(self): def __init__(self):
spec = "qt_qmlDebugMessageAvailable" spec = 'qt_qmlDebugMessageAvailable'
super(InterpreterMessageBreakpoint, self).\ super(InterpreterMessageBreakpoint, self).\
__init__(spec, gdb.BP_BREAKPOINT, internal=True) __init__(spec, gdb.BP_BREAKPOINT, internal=True)
def stop(self): def stop(self):
print("Interpreter event received.") print('Interpreter event received.')
return theDumper.handleInterpreterMessage() return theDumper.handleInterpreterMessage()
#InterpreterMessageBreakpoint() #InterpreterMessageBreakpoint()

View File

@@ -231,18 +231,18 @@ class Dumper:
# Hex decoding operating on str, return str. # Hex decoding operating on str, return str.
def hexdecode(self, s): def hexdecode(self, s):
if sys.version_info[0] == 2: if sys.version_info[0] == 2:
return s.decode("hex") return s.decode('hex')
return bytes.fromhex(s).decode("utf8") return bytes.fromhex(s).decode('utf8')
# Hex encoding operating on str or bytes, return str. # Hex encoding operating on str or bytes, return str.
def hexencode(self, s): def hexencode(self, s):
if sys.version_info[0] == 2: if sys.version_info[0] == 2:
return s.encode("hex") return s.encode('hex')
if isinstance(s, str): if isinstance(s, str):
s = s.encode("utf8") s = s.encode('utf8')
return base64.b16encode(s).decode("utf8") return base64.b16encode(s).decode('utf8')
def canonic(self, filename): def canonic(self, filename):
if filename == "<" + filename[1:-1] + ">": if filename == '<' + filename[1:-1] + '>':
return filename return filename
canonic = self.fncache.get(filename) canonic = self.fncache.get(filename)
if not canonic: if not canonic:
@@ -572,7 +572,7 @@ class Dumper:
locals = globals locals = globals
self.reset() self.reset()
if isinstance(cmd, str): if isinstance(cmd, str):
cmd = compile(cmd, "<string>", "exec") cmd = compile(cmd, '<string>', 'exec')
sys.settrace(self.trace_dispatch) sys.settrace(self.trace_dispatch)
try: try:
exec(cmd, globals, locals) exec(cmd, globals, locals)
@@ -641,7 +641,7 @@ class Dumper:
line = 'EOF' line = 'EOF'
else: else:
line = line.rstrip('\r\n') line = line.rstrip('\r\n')
print("LINE: %s" % line) print('LINE: %s' % line)
stop = self.onecmd(line) stop = self.onecmd(line)
finally: finally:
pass pass
@@ -674,9 +674,9 @@ class Dumper:
commands by the interpreter should stop. commands by the interpreter should stop.
""" """
line = str(line) line = str(line)
print("LINE 0: %s" % line) print('LINE 0: %s' % line)
cmd, arg, line = self.parseline(line) cmd, arg, line = self.parseline(line)
print("LINE 1: %s" % line) print('LINE 1: %s' % line)
if cmd is None: if cmd is None:
return self.default(line) return self.default(line)
self.lastcmd = line self.lastcmd = line
@@ -693,15 +693,15 @@ class Dumper:
def runit(self): def runit(self):
print("DIR: %s" % dir()) print('DIR: %s' % dir())
if sys.argv[0] == '-c': if sys.argv[0] == '-c':
sys.argv = sys.argv[2:] sys.argv = sys.argv[2:]
else: else:
sys.argv = sys.argv[1:] sys.argv = sys.argv[1:]
print("ARGV: %s" % sys.argv) print('ARGV: %s' % sys.argv)
mainpyfile = sys.argv[0] # Get script filename mainpyfile = sys.argv[0] # Get script filename
sys.path.append(os.path.dirname(mainpyfile)) sys.path.append(os.path.dirname(mainpyfile))
print("MAIN: %s" % mainpyfile) print('MAIN: %s' % mainpyfile)
while True: while True:
try: try:
@@ -713,9 +713,9 @@ class Dumper:
#import __main__ #import __main__
#__main__.__dict__.clear() #__main__.__dict__.clear()
#__main__.__dict__.update({"__name__" : "__main__", #__main__.__dict__.update({'__name__' : '__main__',
# "__file__" : mainpyfile, # '__file__' : mainpyfile,
# "__builtins__": __builtins__, # '__builtins__': __builtins__,
# }) # })
# When bdb sets tracing, a number of call and line events happens # When bdb sets tracing, a number of call and line events happens
@@ -726,26 +726,26 @@ class Dumper:
self._wait_for_mainpyfile = True self._wait_for_mainpyfile = True
self.mainpyfile = self.canonic(mainpyfile) self.mainpyfile = self.canonic(mainpyfile)
self._user_requested_quit = False self._user_requested_quit = False
with open(mainpyfile, "rb") as fp: with open(mainpyfile, 'rb') as fp:
statement = "exec(compile(%r, %r, 'exec'))" % \ statement = "exec(compile(%r, %r, 'exec'))" % \
(fp.read(), self.mainpyfile) (fp.read(), self.mainpyfile)
self.run(statement) self.run(statement)
if self._user_requested_quit: if self._user_requested_quit:
break break
print("The program finished") print('The program finished')
except SystemExit: except SystemExit:
# In most cases SystemExit does not warrant a post-mortem session. # In most cases SystemExit does not warrant a post-mortem session.
print("The program exited via sys.exit(). Exit status:") print('The program exited via sys.exit(). Exit status:')
print(sys.exc_info()[1]) print(sys.exc_info()[1])
except: except:
traceback.print_exc() traceback.print_exc()
print("Uncaught exception. Entering post mortem debugging") print('Uncaught exception. Entering post mortem debugging')
print("Running 'cont' or 'step' will restart the program") print('Running "cont" or "step" will restart the program')
t = sys.exc_info()[2] t = sys.exc_info()[2]
self.interaction(None, t) self.interaction(None, t)
print("Post mortem debugger finished. The " + mainpyfile + print('Post mortem debugger finished. The ' + mainpyfile +
" will be restarted") ' will be restarted')
def sigint_handler(self, signum, frame): def sigint_handler(self, signum, frame):
if self.allow_kbdint: if self.allow_kbdint:
@@ -839,7 +839,7 @@ class Dumper:
def interaction(self, frame, traceback): def interaction(self, frame, traceback):
if self.setup(frame, traceback): if self.setup(frame, traceback):
# no interaction desired at this time (happens if .pdbrc contains # no interaction desired at this time (happens if .pdbrc contains
# a command like "continue") # a command like 'continue')
self.forget() self.forget()
return return
@@ -926,7 +926,7 @@ class Dumper:
cond = None cond = None
comma = arg.find(',') comma = arg.find(',')
if comma > 0: if comma > 0:
# parse stuff after comma: "condition" # parse stuff after comma: 'condition'
cond = arg[comma+1:].lstrip() cond = arg[comma+1:].lstrip()
arg = arg[:comma].rstrip() arg = arg[:comma].rstrip()
# parse stuff before comma: [filename:]lineno | function # parse stuff before comma: [filename:]lineno | function
@@ -986,7 +986,7 @@ class Dumper:
self.error(err) self.error(err)
else: else:
bp = self.get_breaks(filename, line)[-1] bp = self.get_breaks(filename, line)[-1]
self.message("Breakpoint %d at %s:%d" % self.message('Breakpoint %d at %s:%d' %
(bp.number, bp.file, bp.line)) (bp.number, bp.file, bp.line))
# To be overridden in derived debuggers # To be overridden in derived debuggers
@@ -1169,14 +1169,14 @@ class Dumper:
self.message('Deleted %s' % bp) self.message('Deleted %s' % bp)
return return
if ':' in arg: if ':' in arg:
# Make sure it works for "clear C:\foo\bar.py:12" # Make sure it works for 'clear C:\foo\bar.py:12'
i = arg.rfind(':') i = arg.rfind(':')
filename = arg[:i] filename = arg[:i]
arg = arg[i+1:] arg = arg[i+1:]
try: try:
lineno = int(arg) lineno = int(arg)
except ValueError: except ValueError:
err = "Invalid line number (%s)" % arg err = 'Invalid line number (%s)' % arg
else: else:
bplist = self.get_breaks(filename, lineno) bplist = self.get_breaks(filename, lineno)
err = self.clear_break(filename, lineno) err = self.clear_break(filename, lineno)
@@ -1290,9 +1290,9 @@ class Dumper:
globals = self.curframe.f_globals globals = self.curframe.f_globals
locals = self.curframe_locals locals = self.curframe_locals
p = Dumper(self.stdin, self.stdout) p = Dumper(self.stdin, self.stdout)
self.message("ENTERING RECURSIVE DEBUGGER") self.message('ENTERING RECURSIVE DEBUGGER')
sys.call_tracing(p.run, (arg, globals, locals)) sys.call_tracing(p.run, (arg, globals, locals))
self.message("LEAVING RECURSIVE DEBUGGER") self.message('LEAVING RECURSIVE DEBUGGER')
sys.settrace(self.trace_dispatch) sys.settrace(self.trace_dispatch)
self.lastcmd = p.lastcmd self.lastcmd = p.lastcmd
@@ -1398,7 +1398,7 @@ class Dumper:
""" """
ns = self.curframe.f_globals.copy() ns = self.curframe.f_globals.copy()
ns.update(self.curframe_locals) ns.update(self.curframe_locals)
code.interact("*interactive*", local=ns) code.interact('*interactive*', local=ns)
def lookupmodule(self, filename): def lookupmodule(self, filename):
"""Helper function for break/clear parsing -- may be overridden. """Helper function for break/clear parsing -- may be overridden.
@@ -1428,12 +1428,12 @@ class Dumper:
self.updateData(args) self.updateData(args)
def updateData(self, args): def updateData(self, args):
self.expandedINames = set(args.get("expanded", [])) self.expandedINames = set(args.get('expanded', []))
self.typeformats = args.get("typeformats", {}) self.typeformats = args.get('typeformats', {})
self.formats = args.get("formats", {}) self.formats = args.get('formats', {})
self.output = "" self.output = ''
frameNr = args.get("frame", 0) frameNr = args.get('frame', 0)
if frameNr == -1: if frameNr == -1:
frameNr = 0 frameNr = 0
@@ -1441,33 +1441,33 @@ class Dumper:
frame, lineno = frame_lineno frame, lineno = frame_lineno
filename = self.canonic(frame.f_code.co_filename) filename = self.canonic(frame.f_code.co_filename)
self.output += "data={" self.output += 'data={'
for var in frame.f_locals.keys(): for var in frame.f_locals.keys():
if var in ("__file__", "__name__", "__package__", "__spec__", if var in ('__file__', '__name__', '__package__', '__spec__',
"__doc__", "__loader__", "__cached__", "__the_dumper__"): '__doc__', '__loader__', '__cached__', '__the_dumper__'):
continue continue
value = frame.f_locals[var] value = frame.f_locals[var]
# this applies only for anonymous arguments # this applies only for anonymous arguments
# e.g. def dummy(var, (width, height), var2) would create an anonymous local var # e.g. def dummy(var, (width, height), var2) would create an anonymous local var
# named '.1' for (width, height) as this is the second argument # named '.1' for (width, height) as this is the second argument
if var.startswith('.'): if var.startswith('.'):
var = "@arg" + var[1:] var = '@arg' + var[1:]
self.dumpValue(value, var, "local.%s" % var) self.dumpValue(value, var, 'local.%s' % var)
for watcher in args.get("watchers", []): for watcher in args.get('watchers', []):
iname = watcher['iname'] iname = watcher['iname']
exp = self.hexdecode(watcher['exp']) exp = self.hexdecode(watcher['exp'])
exp = str(exp).strip() exp = str(exp).strip()
escapedExp = self.hexencode(exp) escapedExp = self.hexencode(exp)
self.put("{") self.put('{')
self.putField("iname", iname) self.putField('iname', iname)
self.putField("wname", escapedExp) self.putField('wname', escapedExp)
try: try:
res = eval(exp, {}, frame.f_locals) res = eval(exp, {}, frame.f_locals)
self.putValue(res) self.putValue(res)
except: except:
self.putValue("<unavailable>") self.putValue('<unavailable>')
self.put("}") self.put('}')
#self.dumpValue(eval(value), escapedExp, iname) #self.dumpValue(eval(value), escapedExp, iname)
self.output += '}' self.output += '}'
@@ -1475,9 +1475,9 @@ class Dumper:
self.flushOutput() self.flushOutput()
def flushOutput(self): def flushOutput(self):
sys.stdout.write("@\n" + self.output + "@\n") sys.stdout.write('@\n' + self.output + '@\n')
sys.stdout.flush() sys.stdout.flush()
self.output = "" self.output = ''
def put(self, value): def put(self, value):
#sys.stdout.write(value) #sys.stdout.write(value)
@@ -1498,22 +1498,22 @@ class Dumper:
return t return t
def putType(self, type, priority = 0): def putType(self, type, priority = 0):
self.putField("type", self.cleanType(type)) self.putField('type', self.cleanType(type))
def putNumChild(self, numchild): def putNumChild(self, numchild):
self.put('numchild="%s",' % numchild) self.put('numchild="%s",' % numchild)
def putValue(self, value, encoding = None, priority = 0): def putValue(self, value, encoding = None, priority = 0):
self.putField("value", value) self.putField('value', value)
def putName(self, name): def putName(self, name):
self.put('name="%s",' % name) self.put('name="%s",' % name)
def isExpanded(self, iname): def isExpanded(self, iname):
#self.warn("IS EXPANDED: %s in %s" % (iname, self.expandedINames)) #self.warn('IS EXPANDED: %s in %s' % (iname, self.expandedINames))
if iname.startswith("None"): if iname.startswith('None'):
raise "Illegal iname '%s'" % iname raise "Illegal iname '%s'" % iname
#self.warn(" --> %s" % (iname in self.expandedINames)) #self.warn(' --> %s' % (iname in self.expandedINames))
return iname in self.expandedINames return iname in self.expandedINames
def isExpandedIName(self, iname): def isExpandedIName(self, iname):
@@ -1528,138 +1528,134 @@ class Dumper:
# Hex encoding operating on str or bytes, return str. # Hex encoding operating on str or bytes, return str.
def hexencode(self, s): def hexencode(self, s):
if sys.version_info[0] == 2: if sys.version_info[0] == 2:
return s.encode("hex") return s.encode('hex')
if isinstance(s, str): if isinstance(s, str):
s = s.encode("utf8") s = s.encode('utf8')
return base64.b16encode(s).decode("utf8") return base64.b16encode(s).decode('utf8')
def dumpValue(self, value, name, iname): def dumpValue(self, value, name, iname):
t = type(value) t = type(value)
tt = self.cleanType(t) tt = self.cleanType(t)
if tt == "module" or tt == "function": if tt == 'module' or tt == 'function':
return return
if str(value).startswith("<class '"): if str(value).startswith("<class '"):
return return
# FIXME: Should we? # FIXME: Should we?
if str(value).startswith("<enum-item "): if str(value).startswith('<enum-item '):
return return
self.put("{") self.put('{')
self.putField("iname", iname) self.putField('iname', iname)
self.putName(name) self.putName(name)
if tt == "NoneType": if tt == 'NoneType':
self.putType(tt) self.putType(tt)
self.putValue("None") self.putValue('None')
self.putNumChild(0) self.putNumChild(0)
elif tt == "list" or tt == "tuple": elif tt == 'list' or tt == 'tuple':
self.putType(tt) self.putType(tt)
self.putItemCount(len(value)) self.putItemCount(len(value))
#self.putValue(value) #self.putValue(value)
self.put("children=[") self.put('children=[')
for i in range(len(value)): for i in range(len(value)):
self.dumpValue(value[i], str(i), "%s.%d" % (iname, i)) self.dumpValue(value[i], str(i), '%s.%d' % (iname, i))
self.put("]") self.put(']')
elif tt == "str": elif tt == 'str':
v = value v = value
self.putType(tt) self.putType(tt)
self.putValue(self.hexencode(v)) self.putValue(self.hexencode(v))
self.putField("valueencoded", "utf8") self.putField('valueencoded', 'utf8')
self.putNumChild(0) self.putNumChild(0)
elif tt == "unicode": elif tt == 'unicode':
v = value v = value
self.putType(tt) self.putType(tt)
self.putValue(self.hexencode(v)) self.putValue(self.hexencode(v))
self.putField("valueencoded", "utf8") self.putField('valueencoded', 'utf8')
self.putNumChild(0) self.putNumChild(0)
elif tt == "buffer": elif tt == 'buffer':
v = str(value) v = str(value)
self.putType(tt) self.putType(tt)
self.putValue(self.hexencode(v)) self.putValue(self.hexencode(v))
self.putField("valueencoded", "latin1") self.putField('valueencoded', 'latin1')
self.putNumChild(0) self.putNumChild(0)
elif tt == "xrange": elif tt == 'xrange':
b = iter(value).next() b = iter(value).next()
e = b + len(value) e = b + len(value)
self.putType(tt) self.putType(tt)
self.putValue("(%d, %d)" % (b, e)) self.putValue('(%d, %d)' % (b, e))
self.putNumChild(0) self.putNumChild(0)
elif tt == "dict": elif tt == 'dict':
self.putType(tt) self.putType(tt)
self.putItemCount(len(value)) self.putItemCount(len(value))
self.putField("childnumchild", 2) self.putField('childnumchild', 2)
self.put("children=[") self.put('children=[')
i = 0 i = 0
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
vals = value.items() vals = value.items()
else: else:
vals = value.iteritems() vals = value.iteritems()
for (k, v) in vals: for (k, v) in vals:
self.put("{") self.put('{')
self.putType(" ") self.putType(' ')
self.putValue("%s: %s" % (k, v)) self.putValue('%s: %s' % (k, v))
if self.isExpanded(iname): if self.isExpanded(iname):
self.put("children=[") self.put('children=[')
self.dumpValue(k, "key", "%s.%d.k" % (iname, i)) self.dumpValue(k, 'key', '%s.%d.k' % (iname, i))
self.dumpValue(v, "value", "%s.%d.v" % (iname, i)) self.dumpValue(v, 'value', '%s.%d.v' % (iname, i))
self.put("]") self.put(']')
self.put("},") self.put('},')
i += 1 i += 1
self.put("]") self.put(']')
elif tt == "class": elif tt == 'class':
pass pass
elif tt == "module": elif tt == 'module':
pass pass
elif tt == "function": elif tt == 'function':
pass pass
elif str(value).startswith("<enum-item "): elif str(value).startswith('<enum-item '):
# FIXME: Having enums always shown like this is not nice. # FIXME: Having enums always shown like this is not nice.
self.putType(tt) self.putType(tt)
self.putValue(str(value)[11:-1]) self.putValue(str(value)[11:-1])
self.putNumChild(0) self.putNumChild(0)
else: else:
v = str(value) v = str(value)
p = v.find(" object at ") p = v.find(' object at ')
if p > 1: if p > 1:
self.putValue("@" + v[p + 11:-1]) self.putValue('@' + v[p + 11:-1])
self.putType(v[1:p]) self.putType(v[1:p])
else: else:
p = v.find(" instance at ") p = v.find(' instance at ')
if p > 1: if p > 1:
self.putValue("@" + v[p + 13:-1]) self.putValue('@' + v[p + 13:-1])
self.putType(v[1:p]) self.putType(v[1:p])
else: else:
self.putType(tt) self.putType(tt)
self.putValue(v) self.putValue(v)
if self.isExpanded(iname): if self.isExpanded(iname):
self.put("children=[") self.put('children=[')
for child in dir(value): for child in dir(value):
if child == "__dict__": if child in ('__dict__', '__doc__', '__module__'):
continue
if child == "__doc__":
continue
if child == "__module__":
continue continue
attr = getattr(value, child) attr = getattr(value, child)
if callable(attr): if callable(attr):
continue continue
try: try:
self.dumpValue(attr, child, "%s.%s" % (iname, child)) self.dumpValue(attr, child, '%s.%s' % (iname, child))
except: except:
pass pass
self.put("],") self.put('],')
self.put("},") self.put('},')
def warn(self, msg): def warn(self, msg):
self.putField("warning", msg) self.putField('warning', msg)
def listModules(self, args): def listModules(self, args):
self.put("modules=["); self.put('modules=[');
for name in sys.modules: for name in sys.modules:
self.put("{") self.put('{')
self.putName(name) self.putName(name)
self.putValue(sys.modules[name]) self.putValue(sys.modules[name])
self.put("},") self.put('},')
self.put("]") self.put(']')
self.flushOutput() self.flushOutput()
def listSymbols(self, args): def listSymbols(self, args):
@@ -1672,9 +1668,9 @@ class Dumper:
def assignValue(self, args): def assignValue(self, args):
exp = args['expression'] exp = args['expression']
value = args['value'] value = args['value']
cmd = "%s=%s" % (exp, exp, value) cmd = '%s=%s' % (exp, exp, value)
eval(cmd, {}) eval(cmd, {})
self.put("CMD: '%s'" % cmd) self.put('CMD: '%s'' % cmd)
self.flushOutput() self.flushOutput()
def stackListFrames(self, args): def stackListFrames(self, args):
@@ -1705,7 +1701,7 @@ class Dumper:
self.report(result) self.report(result)
def report(self, stuff): def report(self, stuff):
sys.stdout.write("@\n" + stuff + "@\n") sys.stdout.write('@\n' + stuff + '@\n')
sys.stdout.flush() sys.stdout.flush()