PyXR

c:\python24\lib \ test \ test_richcmp.py



0001 # Tests for rich comparisons
0002 
0003 import unittest
0004 from test import test_support
0005 
0006 import operator
0007 
0008 class Number:
0009 
0010     def __init__(self, x):
0011         self.x = x
0012 
0013     def __lt__(self, other):
0014         return self.x < other
0015 
0016     def __le__(self, other):
0017         return self.x <= other
0018 
0019     def __eq__(self, other):
0020         return self.x == other
0021 
0022     def __ne__(self, other):
0023         return self.x != other
0024 
0025     def __gt__(self, other):
0026         return self.x > other
0027 
0028     def __ge__(self, other):
0029         return self.x >= other
0030 
0031     def __cmp__(self, other):
0032         raise test_support.TestFailed, "Number.__cmp__() should not be called"
0033 
0034     def __repr__(self):
0035         return "Number(%r)" % (self.x, )
0036 
0037 class Vector:
0038 
0039     def __init__(self, data):
0040         self.data = data
0041 
0042     def __len__(self):
0043         return len(self.data)
0044 
0045     def __getitem__(self, i):
0046         return self.data[i]
0047 
0048     def __setitem__(self, i, v):
0049         self.data[i] = v
0050 
0051     def __hash__(self):
0052         raise TypeError, "Vectors cannot be hashed"
0053 
0054     def __nonzero__(self):
0055         raise TypeError, "Vectors cannot be used in Boolean contexts"
0056 
0057     def __cmp__(self, other):
0058         raise test_support.TestFailed, "Vector.__cmp__() should not be called"
0059 
0060     def __repr__(self):
0061         return "Vector(%r)" % (self.data, )
0062 
0063     def __lt__(self, other):
0064         return Vector([a < b for a, b in zip(self.data, self.__cast(other))])
0065 
0066     def __le__(self, other):
0067         return Vector([a <= b for a, b in zip(self.data, self.__cast(other))])
0068 
0069     def __eq__(self, other):
0070         return Vector([a == b for a, b in zip(self.data, self.__cast(other))])
0071 
0072     def __ne__(self, other):
0073         return Vector([a != b for a, b in zip(self.data, self.__cast(other))])
0074 
0075     def __gt__(self, other):
0076         return Vector([a > b for a, b in zip(self.data, self.__cast(other))])
0077 
0078     def __ge__(self, other):
0079         return Vector([a >= b for a, b in zip(self.data, self.__cast(other))])
0080 
0081     def __cast(self, other):
0082         if isinstance(other, Vector):
0083             other = other.data
0084         if len(self.data) != len(other):
0085             raise ValueError, "Cannot compare vectors of different length"
0086         return other
0087 
0088 opmap = {
0089     "lt": (lambda a,b: a< b, operator.lt, operator.__lt__),
0090     "le": (lambda a,b: a<=b, operator.le, operator.__le__),
0091     "eq": (lambda a,b: a==b, operator.eq, operator.__eq__),
0092     "ne": (lambda a,b: a!=b, operator.ne, operator.__ne__),
0093     "gt": (lambda a,b: a> b, operator.gt, operator.__gt__),
0094     "ge": (lambda a,b: a>=b, operator.ge, operator.__ge__)
0095 }
0096 
0097 class VectorTest(unittest.TestCase):
0098 
0099     def checkfail(self, error, opname, *args):
0100         for op in opmap[opname]:
0101             self.assertRaises(error, op, *args)
0102 
0103     def checkequal(self, opname, a, b, expres):
0104         for op in opmap[opname]:
0105             realres = op(a, b)
0106             # can't use assertEqual(realres, expres) here
0107             self.assertEqual(len(realres), len(expres))
0108             for i in xrange(len(realres)):
0109                 # results are bool, so we can use "is" here
0110                 self.assert_(realres[i] is expres[i])
0111 
0112     def test_mixed(self):
0113         # check that comparisons involving Vector objects
0114         # which return rich results (i.e. Vectors with itemwise
0115         # comparison results) work
0116         a = Vector(range(2))
0117         b = Vector(range(3))
0118         # all comparisons should fail for different length
0119         for opname in opmap:
0120             self.checkfail(ValueError, opname, a, b)
0121 
0122         a = range(5)
0123         b = 5 * [2]
0124         # try mixed arguments (but not (a, b) as that won't return a bool vector)
0125         args = [(a, Vector(b)), (Vector(a), b), (Vector(a), Vector(b))]
0126         for (a, b) in args:
0127             self.checkequal("lt", a, b, [True,  True,  False, False, False])
0128             self.checkequal("le", a, b, [True,  True,  True,  False, False])
0129             self.checkequal("eq", a, b, [False, False, True,  False, False])
0130             self.checkequal("ne", a, b, [True,  True,  False, True,  True ])
0131             self.checkequal("gt", a, b, [False, False, False, True,  True ])
0132             self.checkequal("ge", a, b, [False, False, True,  True,  True ])
0133 
0134             for ops in opmap.itervalues():
0135                 for op in ops:
0136                     # calls __nonzero__, which should fail
0137                     self.assertRaises(TypeError, bool, op(a, b))
0138 
0139 class NumberTest(unittest.TestCase):
0140 
0141     def test_basic(self):
0142         # Check that comparisons involving Number objects
0143         # give the same results give as comparing the
0144         # corresponding ints
0145         for a in xrange(3):
0146             for b in xrange(3):
0147                 for typea in (int, Number):
0148                     for typeb in (int, Number):
0149                         if typea==typeb==int:
0150                             continue # the combination int, int is useless
0151                         ta = typea(a)
0152                         tb = typeb(b)
0153                         for ops in opmap.itervalues():
0154                             for op in ops:
0155                                 realoutcome = op(a, b)
0156                                 testoutcome = op(ta, tb)
0157                                 self.assertEqual(realoutcome, testoutcome)
0158 
0159     def checkvalue(self, opname, a, b, expres):
0160         for typea in (int, Number):
0161             for typeb in (int, Number):
0162                 ta = typea(a)
0163                 tb = typeb(b)
0164                 for op in opmap[opname]:
0165                     realres = op(ta, tb)
0166                     realres = getattr(realres, "x", realres)
0167                     self.assert_(realres is expres)
0168 
0169     def test_values(self):
0170         # check all operators and all comparison results
0171         self.checkvalue("lt", 0, 0, False)
0172         self.checkvalue("le", 0, 0, True )
0173         self.checkvalue("eq", 0, 0, True )
0174         self.checkvalue("ne", 0, 0, False)
0175         self.checkvalue("gt", 0, 0, False)
0176         self.checkvalue("ge", 0, 0, True )
0177 
0178         self.checkvalue("lt", 0, 1, True )
0179         self.checkvalue("le", 0, 1, True )
0180         self.checkvalue("eq", 0, 1, False)
0181         self.checkvalue("ne", 0, 1, True )
0182         self.checkvalue("gt", 0, 1, False)
0183         self.checkvalue("ge", 0, 1, False)
0184 
0185         self.checkvalue("lt", 1, 0, False)
0186         self.checkvalue("le", 1, 0, False)
0187         self.checkvalue("eq", 1, 0, False)
0188         self.checkvalue("ne", 1, 0, True )
0189         self.checkvalue("gt", 1, 0, True )
0190         self.checkvalue("ge", 1, 0, True )
0191 
0192 class MiscTest(unittest.TestCase):
0193 
0194     def test_misbehavin(self):
0195         class Misb:
0196             def __lt__(self, other): return 0
0197             def __gt__(self, other): return 0
0198             def __eq__(self, other): return 0
0199             def __le__(self, other): raise TestFailed, "This shouldn't happen"
0200             def __ge__(self, other): raise TestFailed, "This shouldn't happen"
0201             def __ne__(self, other): raise TestFailed, "This shouldn't happen"
0202             def __cmp__(self, other): raise RuntimeError, "expected"
0203         a = Misb()
0204         b = Misb()
0205         self.assertEqual(a<b, 0)
0206         self.assertEqual(a==b, 0)
0207         self.assertEqual(a>b, 0)
0208         self.assertRaises(RuntimeError, cmp, a, b)
0209 
0210     def test_not(self):
0211         # Check that exceptions in __nonzero__ are properly
0212         # propagated by the not operator
0213         import operator
0214         class Exc:
0215             pass
0216         class Bad:
0217             def __nonzero__(self):
0218                 raise Exc
0219 
0220         def do(bad):
0221             not bad
0222 
0223         for func in (do, operator.not_):
0224             self.assertRaises(Exc, func, Bad())
0225 
0226     def test_recursion(self):
0227         # Check that comparison for recursive objects fails gracefully
0228         from UserList import UserList
0229         a = UserList()
0230         b = UserList()
0231         a.append(b)
0232         b.append(a)
0233         self.assertRaises(RuntimeError, operator.eq, a, b)
0234         self.assertRaises(RuntimeError, operator.ne, a, b)
0235         self.assertRaises(RuntimeError, operator.lt, a, b)
0236         self.assertRaises(RuntimeError, operator.le, a, b)
0237         self.assertRaises(RuntimeError, operator.gt, a, b)
0238         self.assertRaises(RuntimeError, operator.ge, a, b)
0239 
0240         b.append(17)
0241         # Even recursive lists of different lengths are different,
0242         # but they cannot be ordered
0243         self.assert_(not (a == b))
0244         self.assert_(a != b)
0245         self.assertRaises(RuntimeError, operator.lt, a, b)
0246         self.assertRaises(RuntimeError, operator.le, a, b)
0247         self.assertRaises(RuntimeError, operator.gt, a, b)
0248         self.assertRaises(RuntimeError, operator.ge, a, b)
0249         a.append(17)
0250         self.assertRaises(RuntimeError, operator.eq, a, b)
0251         self.assertRaises(RuntimeError, operator.ne, a, b)
0252         a.insert(0, 11)
0253         b.insert(0, 12)
0254         self.assert_(not (a == b))
0255         self.assert_(a != b)
0256         self.assert_(a < b)
0257 
0258 class DictTest(unittest.TestCase):
0259 
0260     def test_dicts(self):
0261         # Verify that __eq__ and __ne__ work for dicts even if the keys and
0262         # values don't support anything other than __eq__ and __ne__.  Complex
0263         # numbers are a fine example of that.
0264         import random
0265         imag1a = {}
0266         for i in range(50):
0267             imag1a[random.randrange(100)*1j] = random.randrange(100)*1j
0268         items = imag1a.items()
0269         random.shuffle(items)
0270         imag1b = {}
0271         for k, v in items:
0272             imag1b[k] = v
0273         imag2 = imag1b.copy()
0274         imag2[k] = v + 1.0
0275         self.assert_(imag1a == imag1a)
0276         self.assert_(imag1a == imag1b)
0277         self.assert_(imag2 == imag2)
0278         self.assert_(imag1a != imag2)
0279         for opname in ("lt", "le", "gt", "ge"):
0280             for op in opmap[opname]:
0281                 self.assertRaises(TypeError, op, imag1a, imag2)
0282 
0283 class ListTest(unittest.TestCase):
0284 
0285     def assertIs(self, a, b):
0286         self.assert_(a is b)
0287 
0288     def test_coverage(self):
0289         # exercise all comparisons for lists
0290         x = [42]
0291         self.assertIs(x<x, False)
0292         self.assertIs(x<=x, True)
0293         self.assertIs(x==x, True)
0294         self.assertIs(x!=x, False)
0295         self.assertIs(x>x, False)
0296         self.assertIs(x>=x, True)
0297         y = [42, 42]
0298         self.assertIs(x<y, True)
0299         self.assertIs(x<=y, True)
0300         self.assertIs(x==y, False)
0301         self.assertIs(x!=y, True)
0302         self.assertIs(x>y, False)
0303         self.assertIs(x>=y, False)
0304 
0305     def test_badentry(self):
0306         # make sure that exceptions for item comparison are properly
0307         # propagated in list comparisons
0308         class Exc:
0309             pass
0310         class Bad:
0311             def __eq__(self, other):
0312                 raise Exc
0313 
0314         x = [Bad()]
0315         y = [Bad()]
0316 
0317         for op in opmap["eq"]:
0318             self.assertRaises(Exc, op, x, y)
0319 
0320     def test_goodentry(self):
0321         # This test exercises the final call to PyObject_RichCompare()
0322         # in Objects/listobject.c::list_richcompare()
0323         class Good:
0324             def __lt__(self, other):
0325                 return True
0326 
0327         x = [Good()]
0328         y = [Good()]
0329 
0330         for op in opmap["lt"]:
0331             self.assertIs(op(x, y), True)
0332 
0333 def test_main():
0334     test_support.run_unittest(VectorTest, NumberTest, MiscTest, DictTest, ListTest)
0335 
0336 if __name__ == "__main__":
0337     test_main()
0338 

Generated by PyXR 0.9.4
SourceForge.net Logo