[pypy-commit] pypy default: a bit of refactoring: do pretty print of *pointers* to strings and lists, so we can still inspect the underyling struct when we do p *val
antocuni
noreply at buildbot.pypy.org
Mon Aug 8 17:39:15 CEST 2011
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r46375:02272b150b8d
Date: 2011-08-08 17:26 +0200
http://bitbucket.org/pypy/pypy/changeset/02272b150b8d/
Log: a bit of refactoring: do pretty print of *pointers* to strings and
lists, so we can still inspect the underyling struct when we do p
*val
diff --git a/pypy/tool/gdb_pypy.py b/pypy/tool/gdb_pypy.py
--- a/pypy/tool/gdb_pypy.py
+++ b/pypy/tool/gdb_pypy.py
@@ -122,12 +122,31 @@
return typeids
+def is_ptr(type, gdb):
+ if gdb is None:
+ import gdb # so we can pass a fake one from the tests
+ return type.code == gdb.TYPE_CODE_PTR
-class RpyStringPrinter(object):
+
+class RPyStringPrinter(object):
+ """
+ Pretty printer for rpython strings.
+
+ Note that this pretty prints *pointers* to strings: this way you can do "p
+ val" and see the nice string, and "p *val" to see the underyling struct
+ fields
+ """
def __init__(self, val):
self.val = val
-
+
+ @classmethod
+ def lookup(cls, val, gdb=None):
+ t = val.type
+ if is_ptr(t, gdb) and t.target().tag == 'pypy_rpy_string0':
+ return cls(val)
+ return None
+
def to_string(self):
chars = self.val['rs_chars']
length = int(chars['length'])
@@ -137,15 +156,44 @@
return repr(string) + " (rpy)"
-def rpy_string_lookup(val):
- if val.type.tag == 'pypy_rpy_string0':
- return RpyStringPrinter(val)
- return None
+class RPyListPrinter(object):
+ """
+ Pretty printer for rpython lists
+
+ Note that this pretty prints *pointers* to lists: this way you can do "p
+ val" and see the nice repr, and "p *val" to see the underyling struct
+ fields
+ """
+
+ def __init__(self, val):
+ self.val = val
+
+ @classmethod
+ def lookup(cls, val, gdb=None):
+ t = val.type
+ if is_ptr(t, gdb) and t.target().tag == 'pypy_list0':
+ return cls(val)
+ return None
+
+ def to_string(self):
+ length = int(self.val['l_length'])
+ array = self.val['l_items']
+ allocated = int(array['length'])
+ items = array['items']
+ itemlist = []
+ for i in range(length):
+ item = items[i]
+ itemlist.append(str(item))
+ str_items = ', '.join(itemlist)
+ return '[%s] (length=%d, allocated=%d, rpy)' % (str_items, length, allocated)
try:
import gdb
RPyType() # side effects
- gdb.pretty_printers.append(rpy_string_lookup)
+ gdb.pretty_printers += [
+ RPyStringPrinter.lookup,
+ RPyListPrinter.lookup
+ ]
except ImportError:
pass
diff --git a/pypy/tool/test/test_gdb_pypy.py b/pypy/tool/test/test_gdb_pypy.py
--- a/pypy/tool/test/test_gdb_pypy.py
+++ b/pypy/tool/test/test_gdb_pypy.py
@@ -4,6 +4,10 @@
class FakeGdb(object):
COMMAND_NONE = -1
+ #
+ TYPE_CODE_PTR = 1
+ TYPE_CODE_ARRAY = 2
+ TYPE_CODE_STRUCT = 3
def __init__(self, exprs, progspace=None):
self.exprs = exprs
@@ -24,20 +28,40 @@
pass
class Struct(object):
- def __init__(self, fieldnames):
+ code = FakeGdb.TYPE_CODE_STRUCT
+
+ def __init__(self, fieldnames, tag):
self._fields = [Field(name=name) for name in fieldnames]
+ self.tag = tag
def fields(self):
return self._fields[:]
+class Pointer(object):
+ code = FakeGdb.TYPE_CODE_PTR
+
+ def __init__(self, target):
+ self._target = target
+
+ def target(self):
+ return self._target
+
class Value(dict):
def __init__(self, *args, **kwds):
+ type_tag = kwds.pop('type_tag', None)
dict.__init__(self, *args, **kwds)
- self.type = Struct(self.keys())
+ self.type = Struct(self.keys(), type_tag)
for key, val in self.iteritems():
if isinstance(val, dict):
self[key] = Value(val)
+class PtrValue(Value):
+ def __init__(self, *args, **kwds):
+ # in python gdb, we can use [] to access fields either if we have an
+ # actual struct or a pointer to it, so we just reuse Value here
+ Value.__init__(self, *args, **kwds)
+ self.type = Pointer(self.type)
+
def test_mock_objects():
d = {'a': 1,
'b': 2,
@@ -129,7 +153,24 @@
'items': map(ord, 'foobar'),
}
}
- string = Value(d)
- string.type.tag = 'pypy_rpy_string0'
- printer = gdb_pypy.rpy_string_lookup(string)
+ p_string = PtrValue(d, type_tag='pypy_rpy_string0')
+ printer = gdb_pypy.RPyStringPrinter.lookup(p_string, FakeGdb)
assert printer.to_string() == "'foobar' (rpy)"
+
+def test_pprint_list():
+ d = {'_gcheader': {
+ 'h_tid': 123
+ },
+ 'l_length': 3, # the lenght of the rpython list
+ 'l_items':
+ # this is the array which contains the items
+ {'_gcheader': {
+ 'h_tid': 456
+ },
+ 'length': 5, # the lenght of the underlying array
+ 'items': [40, 41, 42, -1, -2],
+ }
+ }
+ mylist = PtrValue(d, type_tag='pypy_list0')
+ printer = gdb_pypy.RPyListPrinter.lookup(mylist, FakeGdb)
+ assert printer.to_string() == '[40, 41, 42] (length=3, allocated=5, rpy)'
More information about the pypy-commit
mailing list