[pypy-svn] r50450 - in pypy/dist/pypy/objspace: . test

arigo at codespeak.net arigo at codespeak.net
Tue Jan 8 22:31:26 CET 2008


Author: arigo
Date: Tue Jan  8 22:31:25 2008
New Revision: 50450

Modified:
   pypy/dist/pypy/objspace/descroperation.py
   pypy/dist/pypy/objspace/test/test_descroperation.py
Log:
Give up on this and add logic similar to CPython to
ensure a "consistent" ordering of instances of
unrelated types.


Modified: pypy/dist/pypy/objspace/descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/descroperation.py	(original)
+++ pypy/dist/pypy/objspace/descroperation.py	Tue Jan  8 22:31:25 2008
@@ -406,15 +406,37 @@
         #print "WARNING, comparison by address!"
         w_id1 = space.id(w_obj1)
         w_id2 = space.id(w_obj2)
+        lt = space.is_true(space.lt(w_id1, w_id2))
     else:
-        #print "WARNING, comparison by address!"
-        w_id1 = space.id(w_typ1)
-        w_id2 = space.id(w_typ2)
-    if space.is_true(space.lt(w_id1, w_id2)):
+        #print "WARNING, comparison by type name!"
+
+        # the CPython rule is to compare type names; numbers are
+        # smaller.  So we compare the types by the following key:
+        #   (not_a_number_flag, type_name, type_id)
+        num1 = number_check(space, w_obj1)
+        num2 = number_check(space, w_obj2)
+        if num1 != num2:
+            lt = num1      # if obj1 is a number, it is Lower Than obj2
+        else:
+            name1 = w_typ1.getname(space, "")
+            name2 = w_typ2.getname(space, "")
+            if name1 != name2:
+                lt = name1 < name2
+            else:
+                w_id1 = space.id(w_typ1)
+                w_id2 = space.id(w_typ2)
+                lt = space.is_true(space.lt(w_id1, w_id2))
+    if lt:
         return space.wrap(-1)
     else:
         return space.wrap(1)
 
+def number_check(space, w_obj):
+    # avoid this as much as possible.  It checks if w_obj "looks like"
+    # it might be a number-ish thing.
+    return (space.lookup(w_obj, '__int__') is not None or
+            space.lookup(w_obj, '__float__') is not None)
+
 # regular methods def helpers
 
 def _make_binop_impl(symbol, specialnames):

Modified: pypy/dist/pypy/objspace/test/test_descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_descroperation.py	(original)
+++ pypy/dist/pypy/objspace/test/test_descroperation.py	Tue Jan  8 22:31:25 2008
@@ -280,3 +280,35 @@
         x = X()
         x.__class__ = Y
         raises(AttributeError, getattr, x, 'a')
+
+    def test_silly_but_consistent_order(self):
+        # incomparable objects sort by type name :-/
+        class A(object): pass
+        class zz(object): pass
+        assert A() < zz()
+        assert zz() > A()
+        # if in doubt, CPython sorts numbers before non-numbers
+        assert 0 < ()
+        assert 0L < ()
+        assert 0.0 < ()
+        assert 0j < ()
+        assert 0 < []
+        assert 0L < []
+        assert 0.0 < []
+        assert 0j < []
+        assert 0 < A()
+        assert 0L < A()
+        assert 0.0 < A()
+        assert 0j < A()
+        assert 0 < zz()
+        assert 0L < zz()
+        assert 0.0 < zz()
+        assert 0j < zz()
+        # what if the type name is the same... whatever, but
+        # be consistent
+        a1 = A()
+        a2 = A()
+        class A(object): pass
+        a3 = A()
+        a4 = A()
+        assert (a1 < a3) == (a1 < a4) == (a2 < a3) == (a2 < a4)



More information about the Pypy-commit mailing list