This was a bit trickier than the backport to 4.9: but the tests pass, except this one:
UNSUPPORTED: libstdc++-prettyprinters/shared_ptr.cc This is a bit puzzling, but seems unrelated to my change. 2014-08-13 Samuel Bronson <naes...@gmail.com> Backport r212453 from trunk 2014-07-11 Samuel Bronson <naes...@gmail.com> Matthias Klose <d...@ubuntu.com> PR libstdc++/58962 * python/libstdcxx/v6/printers.py: Port to Python 2+3 (imap): New compat function. (izip): Likewise. (Iterator): New mixin to allow writing iterators in Python 3 style regardless of which version we're running on. [Python3] (long) New compat alias for "int". * testsuite/lib/gdb-test.exp: Port to Python 2+3 (print syntax) Backport r210625 from trunk 2014-05-19 Jonathan Wakely <jwak...@redhat.com> * python/libstdcxx/v6/printers.py: Use Python3 raise syntax. --- libstdc++-v3/ChangeLog | 20 +++++ libstdc++-v3/python/libstdcxx/v6/printers.py | 108 +++++++++++++++++++-------- libstdc++-v3/testsuite/lib/gdb-test.exp | 4 +- 3 files changed, 98 insertions(+), 34 deletions(-)
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9c8408d..4134f13 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,23 @@ +2014-08-13 Samuel Bronson <naes...@gmail.com> + + Backport r212453 from trunk + 2014-07-11 Samuel Bronson <naes...@gmail.com> + Matthias Klose <d...@ubuntu.com> + + PR libstdc++/58962 + * python/libstdcxx/v6/printers.py: Port to Python 2+3 + (imap): New compat function. + (izip): Likewise. + (Iterator): New mixin to allow writing iterators in Python 3 style + regardless of which version we're running on. + [Python3] (long) New compat alias for "int". + * testsuite/lib/gdb-test.exp: Port to Python 2+3 (print syntax) + + Backport r210625 from trunk + 2014-05-19 Jonathan Wakely <jwak...@redhat.com> + + * python/libstdcxx/v6/printers.py: Use Python3 raise syntax. + 2014-08-04 Jonathan Wakely <jwak...@redhat.com> Backported from mainline diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index e6f2007..1a1f02d 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -1,4 +1,4 @@ -# Pretty-printers for libstc++. +# Pretty-printers for libstdc++. # Copyright (C) 2008-2013 Free Software Foundation, Inc. @@ -18,6 +18,50 @@ import gdb import itertools import re +import sys + +### Python 2 + Python 3 compatibility code + +# Resources about compatibility: +# +# * <http://pythonhosted.org/six/>: Documentation of the "six" module + +# FIXME: The handling of e.g. std::basic_string (at least on char) +# probably needs updating to work with Python 3's new string rules. +# +# In particular, Python 3 has a separate type (called byte) for +# bytestrings, and a special b"" syntax for the byte literals; the old +# str() type has been redefined to always store Unicode text. +# +# We probably can't do much about this until this GDB PR is addressed: +# <https://sourceware.org/bugzilla/show_bug.cgi?id=17138> + +if sys.version_info[0] > 2: + ### Python 3 stuff + Iterator = object + # Python 3 folds these into the normal functions. + imap = map + izip = zip + # Also, int subsumes long + long = int +else: + ### Python 2 stuff + class Iterator: + """Compatibility mixin for iterators + + Instead of writing next() methods for iterators, write + __next__() methods and use this mixin to make them work in + Python 2 as well as Python 3. + + Idea stolen from the "six" documentation: + <http://pythonhosted.org/six/#six.Iterator> + """ + + def next(self): + return self.__next__() + + # In Python 2, we still need these from itertools + from itertools import imap, izip # Try to use the new-style pretty-printing if available. _use_gdb_pp = True @@ -51,7 +95,7 @@ def find_type(orig, name): # anything fancier here. field = typ.fields()[0] if not field.is_base_class: - raise ValueError, "Cannot find type %s::%s" % (str(orig), name) + raise ValueError("Cannot find type %s::%s" % (str(orig), name)) typ = field.type class SharedPointerPrinter: @@ -87,7 +131,7 @@ class UniquePointerPrinter: class StdListPrinter: "Print a std::list" - class _iterator: + class _iterator(Iterator): def __init__(self, nodetype, head): self.nodetype = nodetype self.base = head['_M_next'] @@ -97,7 +141,7 @@ class StdListPrinter: def __iter__(self): return self - def next(self): + def __next__(self): if self.base == self.head: raise StopIteration elt = self.base.cast(self.nodetype).dereference() @@ -135,7 +179,7 @@ class StdListIteratorPrinter: class StdSlistPrinter: "Print a __gnu_cxx::slist" - class _iterator: + class _iterator(Iterator): def __init__(self, nodetype, head): self.nodetype = nodetype self.base = head['_M_head']['_M_next'] @@ -144,7 +188,7 @@ class StdSlistPrinter: def __iter__(self): return self - def next(self): + def __next__(self): if self.base == 0: raise StopIteration elt = self.base.cast(self.nodetype).dereference() @@ -180,7 +224,7 @@ class StdSlistIteratorPrinter: class StdVectorPrinter: "Print a std::vector" - class _iterator: + class _iterator(Iterator): def __init__ (self, start, finish, bitvec): self.bitvec = bitvec if bitvec: @@ -198,7 +242,7 @@ class StdVectorPrinter: def __iter__(self): return self - def next(self): + def __next__(self): count = self.count self.count = self.count + 1 if self.bitvec: @@ -265,7 +309,7 @@ class StdVectorIteratorPrinter: class StdTuplePrinter: "Print a std::tuple" - class _iterator: + class _iterator(Iterator): def __init__ (self, head): self.head = head @@ -276,20 +320,20 @@ class StdTuplePrinter: # Set the actual head to the first pair. self.head = self.head.cast (nodes[0].type) elif len (nodes) != 0: - raise ValueError, "Top of tuple tree does not consist of a single node." + raise ValueError("Top of tuple tree does not consist of a single node.") self.count = 0 def __iter__ (self): return self - def next (self): + def __next__ (self): nodes = self.head.type.fields () # Check for further recursions in the inheritance tree. if len (nodes) == 0: raise StopIteration # Check that this iteration has an expected structure. if len (nodes) != 2: - raise ValueError, "Cannot parse more than 2 nodes in a tuple tree." + raise ValueError("Cannot parse more than 2 nodes in a tuple tree.") # - Left node is the next recursion parent. # - Right node is the actual class contained in the tuple. @@ -341,7 +385,7 @@ class StdStackOrQueuePrinter: return self.visualizer.display_hint () return None -class RbtreeIterator: +class RbtreeIterator(Iterator): def __init__(self, rbtree): self.size = rbtree['_M_t']['_M_impl']['_M_node_count'] self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left'] @@ -353,7 +397,7 @@ class RbtreeIterator: def __len__(self): return int (self.size) - def next(self): + def __next__(self): if self.count == self.size: raise StopIteration result = self.node @@ -405,7 +449,7 @@ class StdMapPrinter: "Print a std::map or std::multimap" # Turn an RbtreeIterator into a pretty-print iterator. - class _iter: + class _iter(Iterator): def __init__(self, rbiter, type): self.rbiter = rbiter self.count = 0 @@ -414,9 +458,9 @@ class StdMapPrinter: def __iter__(self): return self - def next(self): + def __next__(self): if self.count % 2 == 0: - n = self.rbiter.next() + n = next(self.rbiter) n = n.cast(self.type).dereference()['_M_value_field'] self.pair = n item = n['first'] @@ -447,7 +491,7 @@ class StdSetPrinter: "Print a std::set or std::multiset" # Turn an RbtreeIterator into a pretty-print iterator. - class _iter: + class _iter(Iterator): def __init__(self, rbiter, type): self.rbiter = rbiter self.count = 0 @@ -456,8 +500,8 @@ class StdSetPrinter: def __iter__(self): return self - def next(self): - item = self.rbiter.next() + def __next__(self): + item = next(self.rbiter) item = item.cast(self.type).dereference()['_M_value_field'] # FIXME: this is weird ... what to do? # Maybe a 'set' display hint? @@ -522,7 +566,7 @@ class StdBitsetPrinter: class StdDequePrinter: "Print a std::deque" - class _iter: + class _iter(Iterator): def __init__(self, node, start, end, last, buffer_size): self.node = node self.p = start @@ -534,7 +578,7 @@ class StdDequePrinter: def __iter__(self): return self - def next(self): + def __next__(self): if self.p == self.last: raise StopIteration @@ -619,7 +663,7 @@ class StdStringPrinter: def display_hint (self): return 'string' -class Tr1HashtableIterator: +class Tr1HashtableIterator(Iterator): def __init__ (self, hash): self.node = hash['_M_bbegin']['_M_node']['_M_nxt'] self.node_type = find_type(hash.type, '__node_type').pointer() @@ -627,7 +671,7 @@ class Tr1HashtableIterator: def __iter__ (self): return self - def next (self): + def __next__ (self): if self.node == 0: raise StopIteration node = self.node.cast(self.node_type) @@ -655,8 +699,8 @@ class Tr1UnorderedSetPrinter: return '[%d]' % i def children (self): - counter = itertools.imap (self.format_count, itertools.count()) - return itertools.izip (counter, Tr1HashtableIterator (self.hashtable())) + counter = imap (self.format_count, itertools.count()) + return izip (counter, Tr1HashtableIterator (self.hashtable())) class Tr1UnorderedMapPrinter: "Print a tr1::unordered_map" @@ -688,11 +732,11 @@ class Tr1UnorderedMapPrinter: return '[%d]' % i def children (self): - counter = itertools.imap (self.format_count, itertools.count()) + counter = imap (self.format_count, itertools.count()) # Map over the hash table and flatten the result. - data = self.flatten (itertools.imap (self.format_one, Tr1HashtableIterator (self.hashtable()))) + data = self.flatten (imap (self.format_one, Tr1HashtableIterator (self.hashtable()))) # Zip the two iterators together. - return itertools.izip (counter, data) + return izip (counter, data) def display_hint (self): return 'map' @@ -700,7 +744,7 @@ class Tr1UnorderedMapPrinter: class StdForwardListPrinter: "Print a std::forward_list" - class _iterator: + class _iterator(Iterator): def __init__(self, nodetype, head): self.nodetype = nodetype self.base = head['_M_next'] @@ -709,7 +753,7 @@ class StdForwardListPrinter: def __iter__(self): return self - def next(self): + def __next__(self): if self.base == 0: raise StopIteration elt = self.base.cast(self.nodetype).dereference() @@ -764,7 +808,7 @@ class Printer(object): # A small sanity check. # FIXME if not self.compiled_rx.match(name + '<>'): - raise ValueError, 'libstdc++ programming error: "%s" does not match' % name + raise ValueError('libstdc++ programming error: "%s" does not match' % name) printer = RxPrinter(name, function) self.subprinters.append(printer) self.lookup[name] = printer diff --git a/libstdc++-v3/testsuite/lib/gdb-test.exp b/libstdc++-v3/testsuite/lib/gdb-test.exp index 66dcc66..5062828 100644 --- a/libstdc++-v3/testsuite/lib/gdb-test.exp +++ b/libstdc++-v3/testsuite/lib/gdb-test.exp @@ -91,7 +91,7 @@ proc gdb-test { marker {selector {}} } { } } - set do_whatis_tests [gdb_batch_check "python print gdb.type_printers" \ + set do_whatis_tests [gdb_batch_check "python print(gdb.type_printers)" \ "\\\[\\\]"] if {!$do_whatis_tests} { send_log "skipping 'whatis' tests - gdb too old" @@ -252,6 +252,6 @@ proc gdb_batch_check {command pattern} { # but not earlier versions. # Return 1 if the version is ok, 0 otherwise. proc gdb_version_check {} { - return [gdb_batch_check "python print gdb.lookup_global_symbol" \ + return [gdb_batch_check "python print(gdb.lookup_global_symbol)" \ "<built-in function lookup_global_symbol>"] }