@@ -50,6 +50,25 @@ class Unorderable:
5050 def __repr__ (self ):
5151 return str (id (self ))
5252
53+ # Class Orderable is orderable with any type
54+ class Orderable :
55+ def __init__ (self , hash ):
56+ self ._hash = hash
57+ def __lt__ (self , other ):
58+ return False
59+ def __gt__ (self , other ):
60+ return self != other
61+ def __le__ (self , other ):
62+ return self == other
63+ def __ge__ (self , other ):
64+ return True
65+ def __eq__ (self , other ):
66+ return self is other
67+ def __ne__ (self , other ):
68+ return self is not other
69+ def __hash__ (self ):
70+ return self ._hash
71+
5372class QueryTestCase (unittest .TestCase ):
5473
5574 def setUp (self ):
@@ -620,6 +639,26 @@ def test_sort_unorderable_values(self):
620639 self .assertEqual (pprint .pformat (dict .fromkeys (keys , 0 )),
621640 '{%r: 0, %r: 0}' % tuple (sorted (keys , key = id )))
622641
642+ def test_sort_orderable_and_unorderable_values (self ):
643+ # Issue 22721: sorted pprints is not stable
644+ a = Unorderable ()
645+ b = Orderable (hash (a )) # should have the same hash value
646+ # self-test
647+ self .assertLess (a , b )
648+ self .assertLess (str (type (b )), str (type (a )))
649+ self .assertEqual (sorted ([b , a ]), [a , b ])
650+ self .assertEqual (sorted ([a , b ]), [a , b ])
651+ # set
652+ self .assertEqual (pprint .pformat (set ([b , a ]), width = 1 ),
653+ '{%r,\n %r}' % (a , b ))
654+ self .assertEqual (pprint .pformat (set ([a , b ]), width = 1 ),
655+ '{%r,\n %r}' % (a , b ))
656+ # dict
657+ self .assertEqual (pprint .pformat (dict .fromkeys ([b , a ]), width = 1 ),
658+ '{%r: None,\n %r: None}' % (a , b ))
659+ self .assertEqual (pprint .pformat (dict .fromkeys ([a , b ]), width = 1 ),
660+ '{%r: None,\n %r: None}' % (a , b ))
661+
623662 def test_str_wrap (self ):
624663 # pprint tries to wrap strings intelligently
625664 fox = 'the quick brown fox jumped over a lazy dog'
0 commit comments