[Jython-checkins] jython: list.sort now uses __lt__, per PEP 207 ("rich comparisons"). Fixes #1767
jim.baker
jython-checkins at python.org
Tue Feb 16 23:47:15 EST 2016
https://hg.python.org/jython/rev/ab3bea089f77
changeset: 7901:ab3bea089f77
user: Jeff Allen <ja.py at farowl.co.uk>
date: Tue Feb 16 21:47:09 2016 -0700
summary:
list.sort now uses __lt__, per PEP 207 ("rich comparisons"). Fixes #1767
files:
Lib/test/test_sort_jy.py | 61 +++++++++++++++++++++
src/org/python/core/PyList.java | 19 +++++-
2 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/Lib/test/test_sort_jy.py b/Lib/test/test_sort_jy.py
--- a/Lib/test/test_sort_jy.py
+++ b/Lib/test/test_sort_jy.py
@@ -16,6 +16,67 @@
assert len(a_set - a_sorted_set) == len(a_sorted_set - a_set) == 0
+
+ def test_bug1767(self):
+ 'Test bug 1767 sorting when __cmp__ inconsistent with __eq__'
+
+ class Tricky:
+
+ def __init__(self, pair):
+ self.key0, self.key1 = pair
+
+ def __cmp__(self, other):
+ # Duplicates standard sort for pairs
+ if self.key0 != other.key0:
+ return cmp(self.key0, other.key0)
+ return cmp(self.key1, other.key1)
+
+ def __eq__(self,other):
+ # Compare only on second key: inconsistent with __cmp__()==0
+ return self.key1 == other.key1
+
+ def __repr__(self):
+ return "(%d, %d)" %(self.key0, self.key1)
+
+ def slowSorted(qq) :
+ 'Reference sort peformed by insertion using only <'
+ rr = list()
+ for q in qq :
+ i = 0
+ for i in range(len(rr)) :
+ if q < rr[i] :
+ rr.insert(i,q)
+ break
+ else :
+ rr.append(q)
+ return rr
+
+ def check(trick, answer):
+ 'Check list of Tricky matches list of pairs in order'
+ assert len(trick)==len(answer)
+ for t, a in zip(trick,answer) :
+ # print q, a
+ assert t.key0==a[0] and t.key1==a[1]
+
+ # Test material
+ question = [(2, 5), (1, 3), (3, 0), (2, 3), (1, 1), (2, 3),
+ (3, 5), (1, 0), (2, 0), (2, 1), (1, 4), (2, 5),
+ (1, 1), (3, 5), (2, 5), (1, 0), (3, 2), (1, 1),
+ (2, 2), (2, 2), (1, 0), (2, 3), (2, 1), (3, 2)]
+ answer = slowSorted(question)
+
+ # Test library function
+ que = [Tricky(p) for p in question]
+ que.sort()
+ check(que, answer)
+
+ # Test library function in reverse
+ que = [Tricky(p) for p in question]
+ que.sort(reverse=True)
+ check(que, list(reversed(answer)))
+
+
+
def test_main():
test_support.run_unittest(SortTest)
diff --git a/src/org/python/core/PyList.java b/src/org/python/core/PyList.java
--- a/src/org/python/core/PyList.java
+++ b/src/org/python/core/PyList.java
@@ -814,7 +814,15 @@
}
public int compare(PyObject o1, PyObject o2) {
- int result = o1._cmp(o2);
+ // PEP 207 specifies that sort should only depend on "less-than" (Issue #1767)
+ int result;
+ if (o1._lt(o2).__nonzero__()) {
+ result = -1;
+ } else if (o2._lt(o1).__nonzero__()) {
+ result = 1;
+ } else {
+ result = 0;
+ }
if (this.list.gListAllocatedStatus >= 0) {
throw Py.ValueError("list modified during sort");
}
@@ -905,7 +913,14 @@
if (cmp != null && cmp != Py.None) {
result = cmp.__call__(o1.key, o2.key).asInt();
} else {
- result = o1.key._cmp(o2.key);
+ // PEP 207 specifies that sort should only depend on "less-than" (Issue #1767)
+ if (o1.key._lt(o2.key).__nonzero__()) {
+ result = -1;
+ } else if (o2.key._lt(o1.key).__nonzero__()) {
+ result = 1;
+ } else {
+ result = 0;
+ }
}
if (this.list.gListAllocatedStatus >= 0) {
throw Py.ValueError("list modified during sort");
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list