Patchwork make the libstdc++ pretty printers compatible with both Python 2 and Python3

login
register
mail settings
Submitter Matthias Klose
Date Oct. 31, 2013, 12:24 a.m.
Message ID <5271A321.2000002@ubuntu.com>
Download mbox | patch
Permalink /patch/287368/
State New
Headers show

Comments

Matthias Klose - Oct. 31, 2013, 12:24 a.m.
Starting with gdb 7.6, gdb can be linked with both Python 2.x and Python 3.x.
Therefore the pretty printers should be compatible with both Python versions.

This patch should be backported to 4.7 and 4.8 as well.

Ok for the trunk?

  Matthias


	* python/libstdcxx/v6/printers.py: Make pretty printers compatible with
	Both python 2.x and 3.x.
Tom Tromey - Oct. 31, 2013, 4:46 p.m.
>>>>> "Matthias" == Matthias Klose <doko@ubuntu.com> writes:

Matthias> Starting with gdb 7.6, gdb can be linked with both Python 2.x
Matthias> and Python 3.x.  Therefore the pretty printers should be
Matthias> compatible with both Python versions.

Thanks for doing this.

Matthias> -                n = self.rbiter.next()
Matthias> +                n = next(self.rbiter)

Matthias> -        def next(self):
Matthias> -            item = self.rbiter.next()
Matthias> +        def __next__(self):
Matthias> +            item = next(self.rbiter)

Matthias> +        return zip (counter, data)
 
I don't think these two hunks will work on Python 2.x.
But, I also don't think they are really needed, as I think it's just
fine to call the 'next' method on the iterator objects.

Matthias> +
Matthias>      def display_hint (self):
Matthias>          return 'map'

Spurious whitespace change?

You didn't say how you tested this.  Did you run the libstdc++
pretty-printer tests?

Tom
Jonathan Wakely - Jan. 11, 2014, 7:19 p.m.
On 31 October 2013 16:46, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Matthias" == Matthias Klose <doko@ubuntu.com> writes:
>
> Matthias> Starting with gdb 7.6, gdb can be linked with both Python 2.x
> Matthias> and Python 3.x.  Therefore the pretty printers should be
> Matthias> compatible with both Python versions.
>
> Thanks for doing this.
>
> Matthias> -                n = self.rbiter.next()
> Matthias> +                n = next(self.rbiter)
>
> Matthias> -        def next(self):
> Matthias> -            item = self.rbiter.next()
> Matthias> +        def __next__(self):
> Matthias> +            item = next(self.rbiter)
>
> Matthias> +        return zip (counter, data)
>
> I don't think these two hunks will work on Python 2.x.
> But, I also don't think they are really needed, as I think it's just
> fine to call the 'next' method on the iterator objects.
>
> Matthias> +
> Matthias>      def display_hint (self):
> Matthias>          return 'map'
>
> Spurious whitespace change?
>
> You didn't say how you tested this.  Did you run the libstdc++
> pretty-printer tests?


Matthias, did this patch get forgotten about?

I'd like to see it go in, if Tom's concerns can be addressed.

Patch

Index: python/libstdcxx/v6/printers.py
===================================================================
--- python/libstdcxx/v6/printers.py	(revision 204231)
+++ python/libstdcxx/v6/printers.py	(working copy)
@@ -15,8 +15,14 @@ 
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+# Keep this module compatible with both Python 2 and Python 3
+
 import gdb
-import itertools
+import sys
+if sys.version_info[0] < 3:
+    import itertools
+    map = itertools.imap
+    zip = itertools.izip
 import re
 
 # Try to use the new-style pretty-printing if available.
@@ -51,7 +57,7 @@ 
         # 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:
@@ -97,7 +103,7 @@ 
         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()
@@ -105,6 +111,7 @@ 
             count = self.count
             self.count = self.count + 1
             return ('[%d]' % count, elt['_M_data'])
+        next = __next__
 
     def __init__(self, typename, val):
         self.typename = typename
@@ -144,7 +151,7 @@ 
         def __iter__(self):
             return self
 
-        def next(self):
+        def __next__(self):
             if self.base == 0:
                 raise StopIteration
             elt = self.base.cast(self.nodetype).dereference()
@@ -152,6 +159,7 @@ 
             count = self.count
             self.count = self.count + 1
             return ('[%d]' % count, elt['_M_data'])
+        next = __next__
 
     def __init__(self, typename, val):
         self.val = val
@@ -198,7 +206,7 @@ 
         def __iter__(self):
             return self
 
-        def next(self):
+        def __next__(self):
             count = self.count
             self.count = self.count + 1
             if self.bitvec:
@@ -220,6 +228,7 @@ 
                 elt = self.item.dereference()
                 self.item = self.item + 1
                 return ('[%d]' % count, elt)
+        next = __next__
 
     def __init__(self, typename, val):
         self.typename = typename
@@ -276,20 +285,20 @@ 
                 # 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.
@@ -309,6 +318,7 @@ 
                 return ('[%d]' % self.count, impl)
             else:
                 return ('[%d]' % self.count, impl['_M_head_impl'])
+        next = __next__
 
     def __init__ (self, typename, val):
         self.typename = typename
@@ -353,7 +363,7 @@ 
     def __len__(self):
         return int (self.size)
 
-    def next(self):
+    def __next__(self):
         if self.count == self.size:
             raise StopIteration
         result = self.node
@@ -374,6 +384,7 @@ 
                     node = parent
             self.node = node
         return result
+    next = __next__
 
 # This is a pretty printer for std::_Rb_tree_iterator (which is
 # std::map::iterator), and has nothing to do with the RbtreeIterator
@@ -414,9 +425,9 @@ 
         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']
@@ -425,6 +436,7 @@ 
             result = ('[%d]' % self.count, item)
             self.count = self.count + 1
             return result
+        next = __next__
 
     def __init__ (self, typename, val):
         self.typename = typename
@@ -456,14 +468,15 @@ 
         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?
             result = ('[%d]' % self.count, item)
             self.count = self.count + 1
             return result
+        next = __next__
 
     def __init__ (self, typename, val):
         self.typename = typename
@@ -534,7 +547,7 @@ 
         def __iter__(self):
             return self
 
-        def next(self):
+        def __next__(self):
             if self.p == self.last:
                 raise StopIteration
 
@@ -551,6 +564,7 @@ 
                 self.end = self.p + self.buffer_size
 
             return result
+        next = __next__
 
     def __init__(self, typename, val):
         self.typename = typename
@@ -572,7 +586,7 @@ 
 
         size = self.buffer_size * delta_n + delta_s + delta_e
 
-        return '%s with %d elements' % (self.typename, long (size))
+        return '%s with %d elements' % (self.typename, int (size))
 
     def children(self):
         start = self.val['_M_impl']['_M_start']
@@ -635,7 +649,7 @@ 
     def __iter__ (self):
         return self
 
-    def next (self):
+    def __next__ (self):
         if self.node == 0:
             raise StopIteration
         node = self.node.cast(self.node_type)
@@ -649,6 +663,7 @@ 
                     break
                 self.bucket = self.bucket + 1
         return result
+    next = __next__
 
 class StdHashtableIterator:
     def __init__(self, hash):
@@ -658,7 +673,7 @@ 
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         if self.node == 0:
             raise StopIteration
         elt = self.node.cast(self.node_type).dereference()
@@ -666,6 +681,7 @@ 
         valptr = elt['_M_storage'].address
         valptr = valptr.cast(elt.type.template_argument(0).pointer())
         return valptr.dereference()
+    next = __next__
 
 class Tr1UnorderedSetPrinter:
     "Print a tr1::unordered_set"
@@ -687,10 +703,10 @@ 
         return '[%d]' % i
 
     def children (self):
-        counter = itertools.imap (self.format_count, itertools.count())
+        counter = map (self.format_count, itertools.count())
         if self.typename.startswith('std::tr1'):
-            return itertools.izip (counter, Tr1HashtableIterator (self.hashtable()))
-        return itertools.izip (counter, StdHashtableIterator (self.hashtable()))
+            return zip (counter, Tr1HashtableIterator (self.hashtable()))
+        return zip (counter, StdHashtableIterator (self.hashtable()))
 
 class Tr1UnorderedMapPrinter:
     "Print a tr1::unordered_map"
@@ -722,17 +738,17 @@ 
         return '[%d]' % i
 
     def children (self):
-        counter = itertools.imap (self.format_count, itertools.count())
+        counter = map (self.format_count, itertools.count())
         # Map over the hash table and flatten the result.
         if self.typename.startswith('std::tr1'):
-            data = self.flatten (itertools.imap (self.format_one, Tr1HashtableIterator (self.hashtable())))
+            data = self.flatten (map (self.format_one, Tr1HashtableIterator (self.hashtable())))
             # Zip the two iterators together.
-            return itertools.izip (counter, data)
-        data = self.flatten (itertools.imap (self.format_one, StdHashtableIterator (self.hashtable())))
+            return zip (counter, data)
+        data = self.flatten (map (self.format_one, StdHashtableIterator (self.hashtable())))
         # Zip the two iterators together.
-        return itertools.izip (counter, data)
-        
+        return zip (counter, data)
 
+
     def display_hint (self):
         return 'map'
 
@@ -748,7 +764,7 @@ 
         def __iter__(self):
             return self
 
-        def next(self):
+        def __next__(self):
             if self.base == 0:
                 raise StopIteration
             elt = self.base.cast(self.nodetype).dereference()
@@ -758,6 +774,7 @@ 
             valptr = elt['_M_storage'].address
             valptr = valptr.cast(elt.type.template_argument(0).pointer())
             return ('[%d]' % count, valptr.dereference())
+        next = __next__
 
     def __init__(self, typename, val):
         self.val = val
@@ -808,7 +825,7 @@ 
         # 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