ยปCore Development>Code coverage>Lib/test/test_richcmp.py

Python code coverage for Lib/test/test_richcmp.py

#countcontent
1n/a# Tests for rich comparisons
2n/a
3n/aimport unittest
4n/afrom test import support
5n/a
6n/aimport operator
7n/a
8n/aclass Number:
9n/a
10n/a def __init__(self, x):
11n/a self.x = x
12n/a
13n/a def __lt__(self, other):
14n/a return self.x < other
15n/a
16n/a def __le__(self, other):
17n/a return self.x <= other
18n/a
19n/a def __eq__(self, other):
20n/a return self.x == other
21n/a
22n/a def __ne__(self, other):
23n/a return self.x != other
24n/a
25n/a def __gt__(self, other):
26n/a return self.x > other
27n/a
28n/a def __ge__(self, other):
29n/a return self.x >= other
30n/a
31n/a def __cmp__(self, other):
32n/a raise support.TestFailed("Number.__cmp__() should not be called")
33n/a
34n/a def __repr__(self):
35n/a return "Number(%r)" % (self.x, )
36n/a
37n/aclass Vector:
38n/a
39n/a def __init__(self, data):
40n/a self.data = data
41n/a
42n/a def __len__(self):
43n/a return len(self.data)
44n/a
45n/a def __getitem__(self, i):
46n/a return self.data[i]
47n/a
48n/a def __setitem__(self, i, v):
49n/a self.data[i] = v
50n/a
51n/a __hash__ = None # Vectors cannot be hashed
52n/a
53n/a def __bool__(self):
54n/a raise TypeError("Vectors cannot be used in Boolean contexts")
55n/a
56n/a def __cmp__(self, other):
57n/a raise support.TestFailed("Vector.__cmp__() should not be called")
58n/a
59n/a def __repr__(self):
60n/a return "Vector(%r)" % (self.data, )
61n/a
62n/a def __lt__(self, other):
63n/a return Vector([a < b for a, b in zip(self.data, self.__cast(other))])
64n/a
65n/a def __le__(self, other):
66n/a return Vector([a <= b for a, b in zip(self.data, self.__cast(other))])
67n/a
68n/a def __eq__(self, other):
69n/a return Vector([a == b for a, b in zip(self.data, self.__cast(other))])
70n/a
71n/a def __ne__(self, other):
72n/a return Vector([a != b for a, b in zip(self.data, self.__cast(other))])
73n/a
74n/a def __gt__(self, other):
75n/a return Vector([a > b for a, b in zip(self.data, self.__cast(other))])
76n/a
77n/a def __ge__(self, other):
78n/a return Vector([a >= b for a, b in zip(self.data, self.__cast(other))])
79n/a
80n/a def __cast(self, other):
81n/a if isinstance(other, Vector):
82n/a other = other.data
83n/a if len(self.data) != len(other):
84n/a raise ValueError("Cannot compare vectors of different length")
85n/a return other
86n/a
87n/aopmap = {
88n/a "lt": (lambda a,b: a< b, operator.lt, operator.__lt__),
89n/a "le": (lambda a,b: a<=b, operator.le, operator.__le__),
90n/a "eq": (lambda a,b: a==b, operator.eq, operator.__eq__),
91n/a "ne": (lambda a,b: a!=b, operator.ne, operator.__ne__),
92n/a "gt": (lambda a,b: a> b, operator.gt, operator.__gt__),
93n/a "ge": (lambda a,b: a>=b, operator.ge, operator.__ge__)
94n/a}
95n/a
96n/aclass VectorTest(unittest.TestCase):
97n/a
98n/a def checkfail(self, error, opname, *args):
99n/a for op in opmap[opname]:
100n/a self.assertRaises(error, op, *args)
101n/a
102n/a def checkequal(self, opname, a, b, expres):
103n/a for op in opmap[opname]:
104n/a realres = op(a, b)
105n/a # can't use assertEqual(realres, expres) here
106n/a self.assertEqual(len(realres), len(expres))
107n/a for i in range(len(realres)):
108n/a # results are bool, so we can use "is" here
109n/a self.assertTrue(realres[i] is expres[i])
110n/a
111n/a def test_mixed(self):
112n/a # check that comparisons involving Vector objects
113n/a # which return rich results (i.e. Vectors with itemwise
114n/a # comparison results) work
115n/a a = Vector(range(2))
116n/a b = Vector(range(3))
117n/a # all comparisons should fail for different length
118n/a for opname in opmap:
119n/a self.checkfail(ValueError, opname, a, b)
120n/a
121n/a a = list(range(5))
122n/a b = 5 * [2]
123n/a # try mixed arguments (but not (a, b) as that won't return a bool vector)
124n/a args = [(a, Vector(b)), (Vector(a), b), (Vector(a), Vector(b))]
125n/a for (a, b) in args:
126n/a self.checkequal("lt", a, b, [True, True, False, False, False])
127n/a self.checkequal("le", a, b, [True, True, True, False, False])
128n/a self.checkequal("eq", a, b, [False, False, True, False, False])
129n/a self.checkequal("ne", a, b, [True, True, False, True, True ])
130n/a self.checkequal("gt", a, b, [False, False, False, True, True ])
131n/a self.checkequal("ge", a, b, [False, False, True, True, True ])
132n/a
133n/a for ops in opmap.values():
134n/a for op in ops:
135n/a # calls __bool__, which should fail
136n/a self.assertRaises(TypeError, bool, op(a, b))
137n/a
138n/aclass NumberTest(unittest.TestCase):
139n/a
140n/a def test_basic(self):
141n/a # Check that comparisons involving Number objects
142n/a # give the same results give as comparing the
143n/a # corresponding ints
144n/a for a in range(3):
145n/a for b in range(3):
146n/a for typea in (int, Number):
147n/a for typeb in (int, Number):
148n/a if typea==typeb==int:
149n/a continue # the combination int, int is useless
150n/a ta = typea(a)
151n/a tb = typeb(b)
152n/a for ops in opmap.values():
153n/a for op in ops:
154n/a realoutcome = op(a, b)
155n/a testoutcome = op(ta, tb)
156n/a self.assertEqual(realoutcome, testoutcome)
157n/a
158n/a def checkvalue(self, opname, a, b, expres):
159n/a for typea in (int, Number):
160n/a for typeb in (int, Number):
161n/a ta = typea(a)
162n/a tb = typeb(b)
163n/a for op in opmap[opname]:
164n/a realres = op(ta, tb)
165n/a realres = getattr(realres, "x", realres)
166n/a self.assertTrue(realres is expres)
167n/a
168n/a def test_values(self):
169n/a # check all operators and all comparison results
170n/a self.checkvalue("lt", 0, 0, False)
171n/a self.checkvalue("le", 0, 0, True )
172n/a self.checkvalue("eq", 0, 0, True )
173n/a self.checkvalue("ne", 0, 0, False)
174n/a self.checkvalue("gt", 0, 0, False)
175n/a self.checkvalue("ge", 0, 0, True )
176n/a
177n/a self.checkvalue("lt", 0, 1, True )
178n/a self.checkvalue("le", 0, 1, True )
179n/a self.checkvalue("eq", 0, 1, False)
180n/a self.checkvalue("ne", 0, 1, True )
181n/a self.checkvalue("gt", 0, 1, False)
182n/a self.checkvalue("ge", 0, 1, False)
183n/a
184n/a self.checkvalue("lt", 1, 0, False)
185n/a self.checkvalue("le", 1, 0, False)
186n/a self.checkvalue("eq", 1, 0, False)
187n/a self.checkvalue("ne", 1, 0, True )
188n/a self.checkvalue("gt", 1, 0, True )
189n/a self.checkvalue("ge", 1, 0, True )
190n/a
191n/aclass MiscTest(unittest.TestCase):
192n/a
193n/a def test_misbehavin(self):
194n/a class Misb:
195n/a def __lt__(self_, other): return 0
196n/a def __gt__(self_, other): return 0
197n/a def __eq__(self_, other): return 0
198n/a def __le__(self_, other): self.fail("This shouldn't happen")
199n/a def __ge__(self_, other): self.fail("This shouldn't happen")
200n/a def __ne__(self_, other): self.fail("This shouldn't happen")
201n/a a = Misb()
202n/a b = Misb()
203n/a self.assertEqual(a<b, 0)
204n/a self.assertEqual(a==b, 0)
205n/a self.assertEqual(a>b, 0)
206n/a
207n/a def test_not(self):
208n/a # Check that exceptions in __bool__ are properly
209n/a # propagated by the not operator
210n/a import operator
211n/a class Exc(Exception):
212n/a pass
213n/a class Bad:
214n/a def __bool__(self):
215n/a raise Exc
216n/a
217n/a def do(bad):
218n/a not bad
219n/a
220n/a for func in (do, operator.not_):
221n/a self.assertRaises(Exc, func, Bad())
222n/a
223n/a @support.no_tracing
224n/a def test_recursion(self):
225n/a # Check that comparison for recursive objects fails gracefully
226n/a from collections import UserList
227n/a a = UserList()
228n/a b = UserList()
229n/a a.append(b)
230n/a b.append(a)
231n/a self.assertRaises(RecursionError, operator.eq, a, b)
232n/a self.assertRaises(RecursionError, operator.ne, a, b)
233n/a self.assertRaises(RecursionError, operator.lt, a, b)
234n/a self.assertRaises(RecursionError, operator.le, a, b)
235n/a self.assertRaises(RecursionError, operator.gt, a, b)
236n/a self.assertRaises(RecursionError, operator.ge, a, b)
237n/a
238n/a b.append(17)
239n/a # Even recursive lists of different lengths are different,
240n/a # but they cannot be ordered
241n/a self.assertTrue(not (a == b))
242n/a self.assertTrue(a != b)
243n/a self.assertRaises(RecursionError, operator.lt, a, b)
244n/a self.assertRaises(RecursionError, operator.le, a, b)
245n/a self.assertRaises(RecursionError, operator.gt, a, b)
246n/a self.assertRaises(RecursionError, operator.ge, a, b)
247n/a a.append(17)
248n/a self.assertRaises(RecursionError, operator.eq, a, b)
249n/a self.assertRaises(RecursionError, operator.ne, a, b)
250n/a a.insert(0, 11)
251n/a b.insert(0, 12)
252n/a self.assertTrue(not (a == b))
253n/a self.assertTrue(a != b)
254n/a self.assertTrue(a < b)
255n/a
256n/a def test_exception_message(self):
257n/a class Spam:
258n/a pass
259n/a
260n/a tests = [
261n/a (lambda: 42 < None, r"'<' .* of 'int' and 'NoneType'"),
262n/a (lambda: None < 42, r"'<' .* of 'NoneType' and 'int'"),
263n/a (lambda: 42 > None, r"'>' .* of 'int' and 'NoneType'"),
264n/a (lambda: "foo" < None, r"'<' .* of 'str' and 'NoneType'"),
265n/a (lambda: "foo" >= 666, r"'>=' .* of 'str' and 'int'"),
266n/a (lambda: 42 <= None, r"'<=' .* of 'int' and 'NoneType'"),
267n/a (lambda: 42 >= None, r"'>=' .* of 'int' and 'NoneType'"),
268n/a (lambda: 42 < [], r"'<' .* of 'int' and 'list'"),
269n/a (lambda: () > [], r"'>' .* of 'tuple' and 'list'"),
270n/a (lambda: None >= None, r"'>=' .* of 'NoneType' and 'NoneType'"),
271n/a (lambda: Spam() < 42, r"'<' .* of 'Spam' and 'int'"),
272n/a (lambda: 42 < Spam(), r"'<' .* of 'int' and 'Spam'"),
273n/a (lambda: Spam() <= Spam(), r"'<=' .* of 'Spam' and 'Spam'"),
274n/a ]
275n/a for i, test in enumerate(tests):
276n/a with self.subTest(test=i):
277n/a with self.assertRaisesRegex(TypeError, test[1]):
278n/a test[0]()
279n/a
280n/a
281n/aclass DictTest(unittest.TestCase):
282n/a
283n/a def test_dicts(self):
284n/a # Verify that __eq__ and __ne__ work for dicts even if the keys and
285n/a # values don't support anything other than __eq__ and __ne__ (and
286n/a # __hash__). Complex numbers are a fine example of that.
287n/a import random
288n/a imag1a = {}
289n/a for i in range(50):
290n/a imag1a[random.randrange(100)*1j] = random.randrange(100)*1j
291n/a items = list(imag1a.items())
292n/a random.shuffle(items)
293n/a imag1b = {}
294n/a for k, v in items:
295n/a imag1b[k] = v
296n/a imag2 = imag1b.copy()
297n/a imag2[k] = v + 1.0
298n/a self.assertEqual(imag1a, imag1a)
299n/a self.assertEqual(imag1a, imag1b)
300n/a self.assertEqual(imag2, imag2)
301n/a self.assertTrue(imag1a != imag2)
302n/a for opname in ("lt", "le", "gt", "ge"):
303n/a for op in opmap[opname]:
304n/a self.assertRaises(TypeError, op, imag1a, imag2)
305n/a
306n/aclass ListTest(unittest.TestCase):
307n/a
308n/a def test_coverage(self):
309n/a # exercise all comparisons for lists
310n/a x = [42]
311n/a self.assertIs(x<x, False)
312n/a self.assertIs(x<=x, True)
313n/a self.assertIs(x==x, True)
314n/a self.assertIs(x!=x, False)
315n/a self.assertIs(x>x, False)
316n/a self.assertIs(x>=x, True)
317n/a y = [42, 42]
318n/a self.assertIs(x<y, True)
319n/a self.assertIs(x<=y, True)
320n/a self.assertIs(x==y, False)
321n/a self.assertIs(x!=y, True)
322n/a self.assertIs(x>y, False)
323n/a self.assertIs(x>=y, False)
324n/a
325n/a def test_badentry(self):
326n/a # make sure that exceptions for item comparison are properly
327n/a # propagated in list comparisons
328n/a class Exc(Exception):
329n/a pass
330n/a class Bad:
331n/a def __eq__(self, other):
332n/a raise Exc
333n/a
334n/a x = [Bad()]
335n/a y = [Bad()]
336n/a
337n/a for op in opmap["eq"]:
338n/a self.assertRaises(Exc, op, x, y)
339n/a
340n/a def test_goodentry(self):
341n/a # This test exercises the final call to PyObject_RichCompare()
342n/a # in Objects/listobject.c::list_richcompare()
343n/a class Good:
344n/a def __lt__(self, other):
345n/a return True
346n/a
347n/a x = [Good()]
348n/a y = [Good()]
349n/a
350n/a for op in opmap["lt"]:
351n/a self.assertIs(op(x, y), True)
352n/a
353n/a
354n/aif __name__ == "__main__":
355n/a unittest.main()