From 175a4c4305dc15e0031711b5f6c9d2cb3cc597d7 Mon Sep 17 00:00:00 2001
From: David Gobbi <david.gobbi@gmail.com>
Date: Sat, 22 Aug 2015 23:37:39 -0600
Subject: [PATCH] Make vtkVariantStrictWeakOrder(a,b) work with Py3k.

For Python 2, this method operated like the cmp(a,b) method.  In
Python 3, there is no cmp(a,b) method, so instead this method now
returns (a < b) like the original C++ method.
---
 Common/Core/Testing/Python/TestVariant.py | 21 +++++--
 Wrapping/Python/vtk/util/vtkVariant.py    | 68 ++++++++++++++++++-----
 2 files changed, 69 insertions(+), 20 deletions(-)

diff --git a/Common/Core/Testing/Python/TestVariant.py b/Common/Core/Testing/Python/TestVariant.py
index 5bce363292b..260ccccee08 100644
--- a/Common/Core/Testing/Python/TestVariant.py
+++ b/Common/Core/Testing/Python/TestVariant.py
@@ -18,7 +18,7 @@ import sys
 import vtk
 from vtk.test import Testing
 
-if sys.hexversion > 0x03000000:
+if sys.hexversion >= 0x03000000:
     cedilla = 'Fran\xe7ois'
 else:
     cedilla = unicode('Fran\xe7ois', 'latin1')
@@ -126,16 +126,27 @@ class TestVariant(Testing.vtkTest):
         l.sort()
         self.assertEqual(l, s)
 
+    def testComparisonMethods(self):
+        v1 = vtk.vtkVariant(10)
+        v2 = vtk.vtkVariant("10")
+        # compare without regards to type
+        self.assertEqual(vtk.vtkVariantEqual(v1, v2), True)
+        self.assertEqual(vtk.vtkVariantLessThan(v1, v2), False)
+        # compare with different types being non-equivalent
+        self.assertEqual(vtk.vtkVariantStrictEquality(v1, v2), False)
+        if sys.hexversion >= 0x03000000:
+            self.assertEqual(vtk.vtkVariantStrictWeakOrder(v1, v2), True)
+        else:
+            # for Python 2, it worked like the cmp() function
+            self.assertEqual(vtk.vtkVariantStrictWeakOrder(v1, v2), -1)
+
     def testStrictWeakOrder(self):
         """Use vtkVariantStrictWeakOrder to sort a list of vtkVariants"""
-        if sys.hexversion > 0x03000000:
-            """sort() doesn't take comparator in py3k"""
-            return
         original = [1, 2.5, vtk.vtkVariant(), "0", cedilla]
         ordered = [vtk.vtkVariant(), 1, 2.5, "0", cedilla]
         l = [vtk.vtkVariant(x) for x in original]
         s = [vtk.vtkVariant(x) for x in ordered]
-        l.sort(vtk.vtkVariantStrictWeakOrder)
+        l.sort(key=vtk.vtkVariantStrictWeakOrderKey)
         self.assertEqual(l, s)
 
     def testVariantExtract(self):
diff --git a/Wrapping/Python/vtk/util/vtkVariant.py b/Wrapping/Python/vtk/util/vtkVariant.py
index fbf54a1b787..bad0a645878 100644
--- a/Wrapping/Python/vtk/util/vtkVariant.py
+++ b/Wrapping/Python/vtk/util/vtkVariant.py
@@ -3,6 +3,7 @@ Utility functions to mimic the template support functions for vtkVariant
 """
 
 import vtk
+import sys
 
 _variant_type_map = {
     'void' : vtk.VTK_VOID,
@@ -126,10 +127,11 @@ def vtkVariantCast(v, t):
 
 def vtkVariantStrictWeakOrder(s1, s2):
     """
-    Compare variants by type first, and then by value.  The return values
-    are -1, 0, 1 like the python cmp() method, for compatibility with the
-    python list sort() method.  This is in contrast with the C++ version,
-    which returns true or false.
+    Compare variants by type first, and then by value.  When called from
+    within a Python 2 interpreter, the return values are -1, 0, 1 like the
+    cmp() method, for compatibility with the Python 2 list sort() method.
+    This is in contrast with the Python 3 version of this method (and the
+    VTK C++ version), which return true or false.
     """
     s1 = vtk.vtkVariant(s1)
     s2 = vtk.vtkVariant(s2)
@@ -137,28 +139,64 @@ def vtkVariantStrictWeakOrder(s1, s2):
     t1 = s1.GetType()
     t2 = s2.GetType()
 
+    # define a cmp(x, y) for Python 3 that returns (x < y)
+    def vcmp(x, y):
+        if sys.hexversion >= 0x03000000:
+            return (x < y)
+        else:
+            return cmp(x,y)
+
     # check based on type
     if t1 != t2:
-        return cmp(t1,t2)
+        return vcmp(t1,t2)
 
     v1 = s1.IsValid()
     v2 = s2.IsValid()
 
     # check based on validity
-    if (not v1) and (not v2):
-        return 0
-    elif v1 != v2:
-        return cmp(v1,v2)
+    if (not v1) or (not v2):
+        return vcmp(v1,v2)
 
     # extract and compare the values
     r1 = getattr(s1, _variant_method_map[t1])()
     r2 = getattr(s2, _variant_method_map[t2])()
 
-    # compare vtk objects by classname
+    # compare vtk objects by classname, then address
     if t1 == vtk.VTK_OBJECT:
-        return cmp(r1.GetClassName(), r2.GetClassName())
-
-    return cmp(r1, r2)
+        c1 = r1.GetClassName()
+        c2 = r2.GetClassName()
+        if c1 != c2:
+            return vcmp(c1,c2)
+        else:
+            return vcmp(r1.__this__,r2.__this__)
+
+    return vcmp(r1, r2)
+
+
+if sys.hexversion >= 0x03000000:
+    class vtkVariantStrictWeakOrderKey:
+        """A key method (class, actually) for use with sort()"""
+        def __init__(self, obj, *args):
+            self.obj = obj
+        def __lt__(self, other):
+            return vtkVariantStrictWeakOrder(self.obj, other)
+else:
+    class vtkVariantStrictWeakOrderKey:
+        """A key method (class, actually) for use with sort()"""
+        def __init__(self, obj, *args):
+            self.obj = obj
+        def __lt__(self, other):
+            return vtkVariantStrictWeakOrder(self.obj, other) < 0
+        def __gt__(self, other):
+            return vtkVariantStrictWeakOrder(self.obj, other) > 0
+        def __eq__(self, other):
+            return vtkVariantStrictWeakOrder(self.obj, other) == 0
+        def __le__(self, other):
+            return vtkVariantStrictWeakOrder(self.obj, other) <= 0
+        def __ge__(self, other):
+            return vtkVariantStrictWeakOrder(self.obj, other) >= 0
+        def __ne__(self, other):
+            return vtkVariantStrictWeakOrder(self.obj, other) != 0
 
 
 def vtkVariantStrictEquality(s1, s2):
@@ -193,14 +231,14 @@ def vtkVariantStrictEquality(s1, s2):
 
 def vtkVariantLessThan(s1, s2):
     """
-    Return true if s1 < s2.  This isn't very useful in Python.
+    Return true if s1 < s2.
     """
     return (vtk.vtkVariant(s1) < vtk.vtkVariant(s2))
 
 
 def vtkVariantEqual(s1, s2):
     """
-    Return true if s1 == s2.  This isn't very useful in Python.
+    Return true if s1 == s2.
     """
     return (vtk.vtkVariant(s1) == vtk.vtkVariant(s2))
 
-- 
GitLab