[gobject-introspection] giscanner: Use rich comparison methods for Python 3 compatibility



commit 10175a1b54fff30291bbb5ff849dc3a048a4b8dc
Author: Simon Feltman <sfeltman src gnome org>
Date:   Wed Apr 30 17:08:29 2014 -0700

    giscanner: Use rich comparison methods for Python 3 compatibility
    
    Add lt, le, gt, ge, eq, ne, and hash dunder methods to all classes that
    implement custom comparisons with __cmp__. This is needed to support Python 3
    compatible sorting of instances of these classes.
    Avoid using @functools.total_ordering which does not work for some of these
    classes and also is not available in Python 2.6.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=679438

 giscanner/annotationparser.py |   26 +++++++-
 giscanner/ast.py              |  136 +++++++++++++++++++++++++++++++++++------
 giscanner/girwriter.py        |   15 ++---
 giscanner/message.py          |   31 ++++++++-
 4 files changed, 173 insertions(+), 35 deletions(-)
---
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index cd6fa4f..d48ed61 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -114,6 +114,7 @@ from __future__ import unicode_literals
 
 import os
 import re
+import operator
 
 from collections import namedtuple
 from operator import ne, gt, lt
@@ -1054,11 +1055,32 @@ class GtkDocCommentBlock(GtkDocAnnotatable):
         #: applied to this :class:`GtkDocCommentBlock`.
         self.tags = OrderedDict()
 
-    def __cmp__(self, other):
+    def _compare(self, other, op):
         # Note: This is used by g-ir-annotation-tool, which does a ``sorted(blocks.values())``,
         #       meaning that keeping this around makes update-glib-annotations.py patches
         #       easier to review.
-        return cmp(self.name, other.name)
+        return op(self.name, other.name)
+
+    def __lt__(self, other):
+        return self._compare(other, operator.lt)
+
+    def __gt__(self, other):
+        return self._compare(other, operator.gt)
+
+    def __ge__(self, other):
+        return self._compare(other, operator.ge)
+
+    def __le__(self, other):
+        return self._compare(other, operator.le)
+
+    def __eq__(self, other):
+        return self._compare(other, operator.eq)
+
+    def __ne__(self, other):
+        return self._compare(other, operator.ne)
+
+    def __hash__(self):
+        return hash(self.name)
 
     def __repr__(self):
         return "<GtkDocCommentBlock '%s' %r>" % (self.name, self.annotations)
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 74a7081..f0fb7df 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -25,6 +25,7 @@ from __future__ import print_function
 from __future__ import unicode_literals
 
 import copy
+import operator
 from itertools import chain
 
 from . import message
@@ -123,15 +124,37 @@ in contrast to the other create_type() functions."""
         assert self.target_giname is not None
         return self.target_giname.split('.')[1]
 
-    def __cmp__(self, other):
+    def _compare(self, other, op):
         if self.target_fundamental:
-            return cmp(self.target_fundamental, other.target_fundamental)
+            return op(self.target_fundamental, other.target_fundamental)
         elif self.target_giname:
-            return cmp(self.target_giname, other.target_giname)
+            return op(self.target_giname, other.target_giname)
         elif self.target_foreign:
-            return cmp(self.target_foreign, other.target_foreign)
+            return op(self.target_foreign, other.target_foreign)
         else:
-            return cmp(self.ctype, other.ctype)
+            return op(self.ctype, other.ctype)
+
+    def __lt__(self, other):
+        return self._compare(other, operator.lt)
+
+    def __gt__(self, other):
+        return self._compare(other, operator.gt)
+
+    def __ge__(self, other):
+        return self._compare(other, operator.ge)
+
+    def __le__(self, other):
+        return self._compare(other, operator.le)
+
+    def __eq__(self, other):
+        return self._compare(other, operator.eq)
+
+    def __ne__(self, other):
+        return self._compare(other, operator.ne)
+
+    def __hash__(self):
+        return hash((self.target_fundamental, self.target_giname,
+                     self.target_foreign, self.ctype))
 
     def is_equiv(self, typeval):
         """Return True if the specified types are compatible at
@@ -498,11 +521,26 @@ class Include(object):
     def from_string(cls, string):
         return cls(*string.split('-', 1))
 
-    def __cmp__(self, other):
-        namecmp = cmp(self.name, other.name)
-        if namecmp != 0:
-            return namecmp
-        return cmp(self.version, other.version)
+    def _compare(self, other, op):
+        return op((self.name, self.version), (other.name, other.version))
+
+    def __lt__(self, other):
+        return self._compare(other, operator.lt)
+
+    def __gt__(self, other):
+        return self._compare(other, operator.gt)
+
+    def __ge__(self, other):
+        return self._compare(other, operator.ge)
+
+    def __le__(self, other):
+        return self._compare(other, operator.le)
+
+    def __eq__(self, other):
+        return self._compare(other, operator.eq)
+
+    def __ne__(self, other):
+        return self._compare(other, operator.ne)
 
     def __hash__(self):
         return hash(str(self))
@@ -558,11 +596,29 @@ GIName.  It's possible for nodes to contain or point to other nodes."""
         assert self.namespace is not None
         return Type(target_giname=('%s.%s' % (self.namespace.name, self.name)))
 
-    def __cmp__(self, other):
-        nscmp = cmp(self.namespace, other.namespace)
-        if nscmp != 0:
-            return nscmp
-        return cmp(self.name, other.name)
+    def _compare(self, other, op):
+        return op((self.namespace, self.name), (other.namespace, other.name))
+
+    def __lt__(self, other):
+        return self._compare(other, operator.lt)
+
+    def __gt__(self, other):
+        return self._compare(other, operator.gt)
+
+    def __ge__(self, other):
+        return self._compare(other, operator.ge)
+
+    def __le__(self, other):
+        return self._compare(other, operator.le)
+
+    def __eq__(self, other):
+        return self._compare(other, operator.eq)
+
+    def __ne__(self, other):
+        return self._compare(other, operator.ne)
+
+    def __hash__(self):
+        return hash((self.namespace, self.name))
 
     def __repr__(self):
         return "%s('%s')" % (self.__class__.__name__, self.name)
@@ -858,8 +914,29 @@ class Member(Annotated):
         self.nick = nick
         self.parent = None
 
-    def __cmp__(self, other):
-        return cmp(self.name, other.name)
+    def _compare(self, other, op):
+        return op(self.name, other.name)
+
+    def __lt__(self, other):
+        return self._compare(other, operator.lt)
+
+    def __gt__(self, other):
+        return self._compare(other, operator.gt)
+
+    def __ge__(self, other):
+        return self._compare(other, operator.ge)
+
+    def __le__(self, other):
+        return self._compare(other, operator.le)
+
+    def __eq__(self, other):
+        return self._compare(other, operator.eq)
+
+    def __ne__(self, other):
+        return self._compare(other, operator.ne)
+
+    def __hash__(self):
+        return hash(self.name)
 
     def __repr__(self):
         return "%s('%s')" % (self.__class__.__name__, self.name)
@@ -931,8 +1008,29 @@ class Field(Annotated):
         self.namespace = None
         self.parent = None  # a compound
 
-    def __cmp__(self, other):
-        return cmp(self.name, other.name)
+    def _compare(self, other, op):
+        return op(self.name, other.name)
+
+    def __lt__(self, other):
+        return self._compare(other, operator.lt)
+
+    def __gt__(self, other):
+        return self._compare(other, operator.gt)
+
+    def __ge__(self, other):
+        return self._compare(other, operator.ge)
+
+    def __le__(self, other):
+        return self._compare(other, operator.le)
+
+    def __eq__(self, other):
+        return self._compare(other, operator.eq)
+
+    def __ne__(self, other):
+        return self._compare(other, operator.ne)
+
+    def __hash__(self):
+        return hash(self.name)
 
     def __repr__(self):
         return "%s('%s')" % (self.__class__.__name__, self.name)
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 0df87ed..e73dcac 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -82,17 +82,12 @@ class GIRWriter(XMLWriter):
             # We define a custom sorting function here because
             # we want aliases to be first.  They're a bit
             # special because the typelib compiler expands them.
-            def nscmp(a, b):
-                if isinstance(a, ast.Alias):
-                    if isinstance(b, ast.Alias):
-                        return cmp(a.name, b.name)
-                    else:
-                        return -1
-                elif isinstance(b, ast.Alias):
-                    return 1
+            def nscmp(val):
+                if isinstance(val, ast.Alias):
+                    return 0, val
                 else:
-                    return cmp(a, b)
-            for node in sorted(namespace.values(), cmp=nscmp):
+                    return 1, val
+            for node in sorted(namespace.values(), key=nscmp):
                 self._write_node(node)
 
     def _write_node(self, node):
diff --git a/giscanner/message.py b/giscanner/message.py
index d474ae9..f36bcbc 100644
--- a/giscanner/message.py
+++ b/giscanner/message.py
@@ -27,6 +27,7 @@ from __future__ import unicode_literals
 
 import os
 import sys
+import operator
 
 from . import utils
 
@@ -48,12 +49,34 @@ class Position(object):
         self.line = line
         self.column = column
 
-    def __cmp__(self, other):
-        return cmp((self.filename, self.line, self.column),
-                   (other.filename, other.line, other.column))
+    def _compare(self, other, op):
+        return op((self.filename, self.line, self.column),
+                  (other.filename, other.line, other.column))
+
+    def __lt__(self, other):
+        return self._compare(other, operator.lt)
+
+    def __gt__(self, other):
+        return self._compare(other, operator.gt)
+
+    def __ge__(self, other):
+        return self._compare(other, operator.ge)
+
+    def __le__(self, other):
+        return self._compare(other, operator.le)
+
+    def __eq__(self, other):
+        return self._compare(other, operator.eq)
+
+    def __ne__(self, other):
+        return self._compare(other, operator.ne)
+
+    def __hash__(self):
+        return hash((self.filename, self.line, self.column))
 
     def __repr__(self):
-        return '<Position %s:%d:%d>' % (os.path.basename(self.filename), self.line or -1,
+        return '<Position %s:%d:%d>' % (os.path.basename(self.filename),
+                                        self.line or -1,
                                         self.column or -1)
 
     def format(self, cwd):


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]