blob: 69176f434ea070758d3042ef31ff8418fb5e810e [file] [log] [blame]
Serhiy Storchaka71b71762016-02-02 18:45:59 +02001import copy
Nick Coghlanc649ec52006-05-29 12:43:05 +00002import functools
R. David Murrayf28fd242010-02-23 00:24:49 +00003import sys
Raymond Hettinger9c323f82005-02-28 19:39:44 +00004import unittest
5from test import test_support
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +00006from weakref import proxy
Jack Diederichd60c29e2009-03-31 23:46:48 +00007import pickle
Raymond Hettinger9c323f82005-02-28 19:39:44 +00008
9@staticmethod
10def PythonPartial(func, *args, **keywords):
11 'Pure Python approximation of partial()'
12 def newfunc(*fargs, **fkeywords):
13 newkeywords = keywords.copy()
14 newkeywords.update(fkeywords)
15 return func(*(args + fargs), **newkeywords)
16 newfunc.func = func
17 newfunc.args = args
18 newfunc.keywords = keywords
19 return newfunc
20
21def capture(*args, **kw):
22 """capture all positional and keyword arguments"""
23 return args, kw
24
Jack Diederichd60c29e2009-03-31 23:46:48 +000025def signature(part):
26 """ return the signature of a partial object """
27 return (part.func, part.args, part.keywords, part.__dict__)
28
Serhiy Storchaka71b71762016-02-02 18:45:59 +020029class MyTuple(tuple):
30 pass
31
32class BadTuple(tuple):
33 def __add__(self, other):
34 return list(self) + list(other)
35
36class MyDict(dict):
37 pass
38
Raymond Hettinger9c323f82005-02-28 19:39:44 +000039class TestPartial(unittest.TestCase):
40
Nick Coghlanc649ec52006-05-29 12:43:05 +000041 thetype = functools.partial
Raymond Hettinger9c323f82005-02-28 19:39:44 +000042
43 def test_basic_examples(self):
44 p = self.thetype(capture, 1, 2, a=10, b=20)
45 self.assertEqual(p(3, 4, b=30, c=40),
46 ((1, 2, 3, 4), dict(a=10, b=30, c=40)))
47 p = self.thetype(map, lambda x: x*10)
48 self.assertEqual(p([1,2,3,4]), [10, 20, 30, 40])
49
50 def test_attributes(self):
51 p = self.thetype(capture, 1, 2, a=10, b=20)
52 # attributes should be readable
53 self.assertEqual(p.func, capture)
54 self.assertEqual(p.args, (1, 2))
55 self.assertEqual(p.keywords, dict(a=10, b=20))
56 # attributes should not be writable
Raymond Hettinger9c323f82005-02-28 19:39:44 +000057 self.assertRaises(TypeError, setattr, p, 'func', map)
58 self.assertRaises(TypeError, setattr, p, 'args', (1, 2))
59 self.assertRaises(TypeError, setattr, p, 'keywords', dict(a=1, b=2))
60
Georg Brandla34f87f2010-02-07 12:27:06 +000061 p = self.thetype(hex)
62 try:
63 del p.__dict__
64 except TypeError:
65 pass
66 else:
67 self.fail('partial object allowed __dict__ to be deleted')
68
Raymond Hettinger9c323f82005-02-28 19:39:44 +000069 def test_argument_checking(self):
70 self.assertRaises(TypeError, self.thetype) # need at least a func arg
71 try:
72 self.thetype(2)()
73 except TypeError:
74 pass
75 else:
76 self.fail('First arg not checked for callability')
77
78 def test_protection_of_callers_dict_argument(self):
79 # a caller's dictionary should not be altered by partial
80 def func(a=10, b=20):
81 return a
82 d = {'a':3}
83 p = self.thetype(func, a=5)
84 self.assertEqual(p(**d), 3)
85 self.assertEqual(d, {'a':3})
86 p(b=7)
87 self.assertEqual(d, {'a':3})
88
89 def test_arg_combinations(self):
90 # exercise special code paths for zero args in either partial
91 # object or the caller
92 p = self.thetype(capture)
93 self.assertEqual(p(), ((), {}))
94 self.assertEqual(p(1,2), ((1,2), {}))
95 p = self.thetype(capture, 1, 2)
96 self.assertEqual(p(), ((1,2), {}))
97 self.assertEqual(p(3,4), ((1,2,3,4), {}))
98
99 def test_kw_combinations(self):
100 # exercise special code paths for no keyword args in
101 # either the partial object or the caller
102 p = self.thetype(capture)
Benjamin Peterson72c01412015-05-09 00:23:41 -0400103 self.assertEqual(p.keywords, {})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000104 self.assertEqual(p(), ((), {}))
105 self.assertEqual(p(a=1), ((), {'a':1}))
106 p = self.thetype(capture, a=1)
Benjamin Peterson72c01412015-05-09 00:23:41 -0400107 self.assertEqual(p.keywords, {'a':1})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000108 self.assertEqual(p(), ((), {'a':1}))
109 self.assertEqual(p(b=2), ((), {'a':1, 'b':2}))
110 # keyword args in the call override those in the partial object
111 self.assertEqual(p(a=3, b=2), ((), {'a':3, 'b':2}))
112
113 def test_positional(self):
114 # make sure positional arguments are captured correctly
115 for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]:
116 p = self.thetype(capture, *args)
117 expected = args + ('x',)
118 got, empty = p('x')
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000119 self.assertTrue(expected == got and empty == {})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000120
121 def test_keyword(self):
122 # make sure keyword arguments are captured correctly
123 for a in ['a', 0, None, 3.5]:
124 p = self.thetype(capture, a=a)
125 expected = {'a':a,'x':None}
126 empty, got = p(x=None)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000127 self.assertTrue(expected == got and empty == ())
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000128
129 def test_no_side_effects(self):
130 # make sure there are no side effects that affect subsequent calls
131 p = self.thetype(capture, 0, a=1)
132 args1, kw1 = p(1, b=2)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000133 self.assertTrue(args1 == (0,1) and kw1 == {'a':1,'b':2})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000134 args2, kw2 = p()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000135 self.assertTrue(args2 == (0,) and kw2 == {'a':1})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000136
137 def test_error_propagation(self):
138 def f(x, y):
Ezio Melottidde5b942010-02-03 05:37:26 +0000139 x // y
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000140 self.assertRaises(ZeroDivisionError, self.thetype(f, 1, 0))
141 self.assertRaises(ZeroDivisionError, self.thetype(f, 1), 0)
142 self.assertRaises(ZeroDivisionError, self.thetype(f), 1, 0)
143 self.assertRaises(ZeroDivisionError, self.thetype(f, y=0), 1)
144
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000145 def test_weakref(self):
146 f = self.thetype(int, base=16)
147 p = proxy(f)
148 self.assertEqual(f.func, p.func)
149 f = None
150 self.assertRaises(ReferenceError, getattr, p, 'func')
151
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000152 def test_with_bound_and_unbound_methods(self):
153 data = map(str, range(10))
154 join = self.thetype(str.join, '')
155 self.assertEqual(join(data), '0123456789')
156 join = self.thetype(''.join)
157 self.assertEqual(join(data), '0123456789')
Tim Peterseba28be2005-03-28 01:08:02 +0000158
Jack Diederichd60c29e2009-03-31 23:46:48 +0000159 def test_pickle(self):
Serhiy Storchaka71b71762016-02-02 18:45:59 +0200160 f = self.thetype(signature, ['asdf'], bar=[True])
161 f.attr = []
Serhiy Storchaka655720e2014-12-15 14:02:43 +0200162 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
163 f_copy = pickle.loads(pickle.dumps(f, proto))
Serhiy Storchaka71b71762016-02-02 18:45:59 +0200164 self.assertEqual(signature(f_copy), signature(f))
165
166 def test_copy(self):
167 f = self.thetype(signature, ['asdf'], bar=[True])
168 f.attr = []
169 f_copy = copy.copy(f)
170 self.assertEqual(signature(f_copy), signature(f))
171 self.assertIs(f_copy.attr, f.attr)
172 self.assertIs(f_copy.args, f.args)
173 self.assertIs(f_copy.keywords, f.keywords)
174
175 def test_deepcopy(self):
176 f = self.thetype(signature, ['asdf'], bar=[True])
177 f.attr = []
178 f_copy = copy.deepcopy(f)
179 self.assertEqual(signature(f_copy), signature(f))
180 self.assertIsNot(f_copy.attr, f.attr)
181 self.assertIsNot(f_copy.args, f.args)
182 self.assertIsNot(f_copy.args[0], f.args[0])
183 self.assertIsNot(f_copy.keywords, f.keywords)
184 self.assertIsNot(f_copy.keywords['bar'], f.keywords['bar'])
185
186 def test_setstate(self):
187 f = self.thetype(signature)
188 f.__setstate__((capture, (1,), dict(a=10), dict(attr=[])))
189 self.assertEqual(signature(f),
190 (capture, (1,), dict(a=10), dict(attr=[])))
191 self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20}))
192
193 f.__setstate__((capture, (1,), dict(a=10), None))
194 self.assertEqual(signature(f), (capture, (1,), dict(a=10), {}))
195 self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20}))
196
197 f.__setstate__((capture, (1,), None, None))
198 #self.assertEqual(signature(f), (capture, (1,), {}, {}))
199 self.assertEqual(f(2, b=20), ((1, 2), {'b': 20}))
200 self.assertEqual(f(2), ((1, 2), {}))
201 self.assertEqual(f(), ((1,), {}))
202
203 f.__setstate__((capture, (), {}, None))
204 self.assertEqual(signature(f), (capture, (), {}, {}))
205 self.assertEqual(f(2, b=20), ((2,), {'b': 20}))
206 self.assertEqual(f(2), ((2,), {}))
207 self.assertEqual(f(), ((), {}))
208
209 def test_setstate_errors(self):
210 f = self.thetype(signature)
211 self.assertRaises(TypeError, f.__setstate__, (capture, (), {}))
212 self.assertRaises(TypeError, f.__setstate__, (capture, (), {}, {}, None))
213 self.assertRaises(TypeError, f.__setstate__, [capture, (), {}, None])
214 self.assertRaises(TypeError, f.__setstate__, (None, (), {}, None))
215 self.assertRaises(TypeError, f.__setstate__, (capture, None, {}, None))
216 self.assertRaises(TypeError, f.__setstate__, (capture, [], {}, None))
217 self.assertRaises(TypeError, f.__setstate__, (capture, (), [], None))
218
219 def test_setstate_subclasses(self):
220 f = self.thetype(signature)
221 f.__setstate__((capture, MyTuple((1,)), MyDict(a=10), None))
222 s = signature(f)
223 self.assertEqual(s, (capture, (1,), dict(a=10), {}))
224 self.assertIs(type(s[1]), tuple)
225 self.assertIs(type(s[2]), dict)
226 r = f()
227 self.assertEqual(r, ((1,), {'a': 10}))
228 self.assertIs(type(r[0]), tuple)
229 self.assertIs(type(r[1]), dict)
230
231 f.__setstate__((capture, BadTuple((1,)), {}, None))
232 s = signature(f)
233 self.assertEqual(s, (capture, (1,), {}, {}))
234 self.assertIs(type(s[1]), tuple)
235 r = f(2)
236 self.assertEqual(r, ((1, 2), {}))
237 self.assertIs(type(r[0]), tuple)
Jack Diederichd60c29e2009-03-31 23:46:48 +0000238
Serhiy Storchakaa07a8b42013-02-04 12:45:46 +0200239 # Issue 6083: Reference counting bug
240 def test_setstate_refcount(self):
241 class BadSequence:
242 def __len__(self):
243 return 4
244 def __getitem__(self, key):
245 if key == 0:
246 return max
247 elif key == 1:
248 return tuple(range(1000000))
249 elif key in (2, 3):
250 return {}
251 raise IndexError
252
253 f = self.thetype(object)
Serhiy Storchaka71b71762016-02-02 18:45:59 +0200254 self.assertRaises(TypeError, f.__setstate__, BadSequence())
Serhiy Storchakaa07a8b42013-02-04 12:45:46 +0200255
Nick Coghlanc649ec52006-05-29 12:43:05 +0000256class PartialSubclass(functools.partial):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000257 pass
258
259class TestPartialSubclass(TestPartial):
260
261 thetype = PartialSubclass
262
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000263class TestPythonPartial(TestPartial):
264
265 thetype = PythonPartial
266
Jack Diederichd60c29e2009-03-31 23:46:48 +0000267 # the python version isn't picklable
Serhiy Storchaka71b71762016-02-02 18:45:59 +0200268 test_pickle = None
269 test_setstate = None
270 test_setstate_errors = None
271 test_setstate_subclasses = None
272 test_setstate_refcount = None
273
274 # the python version isn't deepcopyable
275 test_deepcopy = None
Zachary Ware1f702212013-12-10 14:09:20 -0600276
277 # the python version isn't a type
278 test_attributes = None
Jack Diederichd60c29e2009-03-31 23:46:48 +0000279
Nick Coghlan676725d2006-06-08 13:54:49 +0000280class TestUpdateWrapper(unittest.TestCase):
281
282 def check_wrapper(self, wrapper, wrapped,
283 assigned=functools.WRAPPER_ASSIGNMENTS,
284 updated=functools.WRAPPER_UPDATES):
285 # Check attributes were assigned
286 for name in assigned:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000287 self.assertTrue(getattr(wrapper, name) is getattr(wrapped, name))
Nick Coghlan676725d2006-06-08 13:54:49 +0000288 # Check attributes were updated
289 for name in updated:
290 wrapper_attr = getattr(wrapper, name)
291 wrapped_attr = getattr(wrapped, name)
292 for key in wrapped_attr:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000293 self.assertTrue(wrapped_attr[key] is wrapper_attr[key])
Nick Coghlan676725d2006-06-08 13:54:49 +0000294
R. David Murrayf28fd242010-02-23 00:24:49 +0000295 def _default_update(self):
Nick Coghlan676725d2006-06-08 13:54:49 +0000296 def f():
297 """This is a test"""
298 pass
299 f.attr = 'This is also a test'
300 def wrapper():
301 pass
302 functools.update_wrapper(wrapper, f)
R. David Murrayf28fd242010-02-23 00:24:49 +0000303 return wrapper, f
304
305 def test_default_update(self):
306 wrapper, f = self._default_update()
Nick Coghlan676725d2006-06-08 13:54:49 +0000307 self.check_wrapper(wrapper, f)
308 self.assertEqual(wrapper.__name__, 'f')
Nick Coghlan676725d2006-06-08 13:54:49 +0000309 self.assertEqual(wrapper.attr, 'This is also a test')
310
R. David Murrayf28fd242010-02-23 00:24:49 +0000311 @unittest.skipIf(sys.flags.optimize >= 2,
312 "Docstrings are omitted with -O2 and above")
313 def test_default_update_doc(self):
314 wrapper, f = self._default_update()
315 self.assertEqual(wrapper.__doc__, 'This is a test')
316
Nick Coghlan676725d2006-06-08 13:54:49 +0000317 def test_no_update(self):
318 def f():
319 """This is a test"""
320 pass
321 f.attr = 'This is also a test'
322 def wrapper():
323 pass
324 functools.update_wrapper(wrapper, f, (), ())
325 self.check_wrapper(wrapper, f, (), ())
326 self.assertEqual(wrapper.__name__, 'wrapper')
327 self.assertEqual(wrapper.__doc__, None)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000328 self.assertFalse(hasattr(wrapper, 'attr'))
Nick Coghlan676725d2006-06-08 13:54:49 +0000329
330 def test_selective_update(self):
331 def f():
332 pass
333 f.attr = 'This is a different test'
334 f.dict_attr = dict(a=1, b=2, c=3)
335 def wrapper():
336 pass
337 wrapper.dict_attr = {}
338 assign = ('attr',)
339 update = ('dict_attr',)
340 functools.update_wrapper(wrapper, f, assign, update)
341 self.check_wrapper(wrapper, f, assign, update)
342 self.assertEqual(wrapper.__name__, 'wrapper')
343 self.assertEqual(wrapper.__doc__, None)
344 self.assertEqual(wrapper.attr, 'This is a different test')
345 self.assertEqual(wrapper.dict_attr, f.dict_attr)
346
Serhiy Storchaka72121c62013-01-27 19:45:49 +0200347 @test_support.requires_docstrings
Andrew M. Kuchling41eb7162006-10-27 16:39:10 +0000348 def test_builtin_update(self):
349 # Test for bug #1576241
350 def wrapper():
351 pass
352 functools.update_wrapper(wrapper, max)
353 self.assertEqual(wrapper.__name__, 'max')
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000354 self.assertTrue(wrapper.__doc__.startswith('max('))
Nick Coghlan676725d2006-06-08 13:54:49 +0000355
356class TestWraps(TestUpdateWrapper):
357
R. David Murrayf28fd242010-02-23 00:24:49 +0000358 def _default_update(self):
Nick Coghlan676725d2006-06-08 13:54:49 +0000359 def f():
360 """This is a test"""
361 pass
362 f.attr = 'This is also a test'
363 @functools.wraps(f)
364 def wrapper():
365 pass
366 self.check_wrapper(wrapper, f)
R. David Murrayf28fd242010-02-23 00:24:49 +0000367 return wrapper
368
369 def test_default_update(self):
370 wrapper = self._default_update()
Nick Coghlan676725d2006-06-08 13:54:49 +0000371 self.assertEqual(wrapper.__name__, 'f')
Nick Coghlan676725d2006-06-08 13:54:49 +0000372 self.assertEqual(wrapper.attr, 'This is also a test')
373
Serhiy Storchaka80a0a1e2013-01-28 13:24:01 +0200374 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murrayf28fd242010-02-23 00:24:49 +0000375 "Docstrings are omitted with -O2 and above")
376 def test_default_update_doc(self):
377 wrapper = self._default_update()
378 self.assertEqual(wrapper.__doc__, 'This is a test')
379
Nick Coghlan676725d2006-06-08 13:54:49 +0000380 def test_no_update(self):
381 def f():
382 """This is a test"""
383 pass
384 f.attr = 'This is also a test'
385 @functools.wraps(f, (), ())
386 def wrapper():
387 pass
388 self.check_wrapper(wrapper, f, (), ())
389 self.assertEqual(wrapper.__name__, 'wrapper')
390 self.assertEqual(wrapper.__doc__, None)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000391 self.assertFalse(hasattr(wrapper, 'attr'))
Nick Coghlan676725d2006-06-08 13:54:49 +0000392
393 def test_selective_update(self):
394 def f():
395 pass
396 f.attr = 'This is a different test'
397 f.dict_attr = dict(a=1, b=2, c=3)
398 def add_dict_attr(f):
399 f.dict_attr = {}
400 return f
401 assign = ('attr',)
402 update = ('dict_attr',)
403 @functools.wraps(f, assign, update)
404 @add_dict_attr
405 def wrapper():
406 pass
407 self.check_wrapper(wrapper, f, assign, update)
408 self.assertEqual(wrapper.__name__, 'wrapper')
409 self.assertEqual(wrapper.__doc__, None)
410 self.assertEqual(wrapper.attr, 'This is a different test')
411 self.assertEqual(wrapper.dict_attr, f.dict_attr)
412
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000413
Brett Cannon83e81842008-08-09 23:30:55 +0000414class TestReduce(unittest.TestCase):
415
416 def test_reduce(self):
417 class Squares:
418
419 def __init__(self, max):
420 self.max = max
421 self.sofar = []
422
423 def __len__(self): return len(self.sofar)
424
425 def __getitem__(self, i):
426 if not 0 <= i < self.max: raise IndexError
427 n = len(self.sofar)
428 while n <= i:
429 self.sofar.append(n*n)
430 n += 1
431 return self.sofar[i]
432
433 reduce = functools.reduce
434 self.assertEqual(reduce(lambda x, y: x+y, ['a', 'b', 'c'], ''), 'abc')
435 self.assertEqual(
436 reduce(lambda x, y: x+y, [['a', 'c'], [], ['d', 'w']], []),
437 ['a','c','d','w']
438 )
439 self.assertEqual(reduce(lambda x, y: x*y, range(2,8), 1), 5040)
440 self.assertEqual(
441 reduce(lambda x, y: x*y, range(2,21), 1L),
442 2432902008176640000L
443 )
444 self.assertEqual(reduce(lambda x, y: x+y, Squares(10)), 285)
445 self.assertEqual(reduce(lambda x, y: x+y, Squares(10), 0), 285)
446 self.assertEqual(reduce(lambda x, y: x+y, Squares(0), 0), 0)
447 self.assertRaises(TypeError, reduce)
448 self.assertRaises(TypeError, reduce, 42, 42)
449 self.assertRaises(TypeError, reduce, 42, 42, 42)
450 self.assertEqual(reduce(42, "1"), "1") # func is never called with one item
451 self.assertEqual(reduce(42, "", "1"), "1") # func is never called with one item
452 self.assertRaises(TypeError, reduce, 42, (42, 42))
453
Raymond Hettingerbb006cf2010-04-04 21:45:01 +0000454class TestCmpToKey(unittest.TestCase):
455 def test_cmp_to_key(self):
456 def mycmp(x, y):
457 return y - x
458 self.assertEqual(sorted(range(5), key=functools.cmp_to_key(mycmp)),
459 [4, 3, 2, 1, 0])
Brett Cannon83e81842008-08-09 23:30:55 +0000460
Raymond Hettingere1d665a2010-04-05 18:53:43 +0000461 def test_hash(self):
462 def mycmp(x, y):
463 return y - x
464 key = functools.cmp_to_key(mycmp)
465 k = key(10)
466 self.assertRaises(TypeError, hash(k))
467
Raymond Hettinger06bc0b62010-04-04 22:24:03 +0000468class TestTotalOrdering(unittest.TestCase):
469
470 def test_total_ordering_lt(self):
471 @functools.total_ordering
472 class A:
473 def __init__(self, value):
474 self.value = value
475 def __lt__(self, other):
476 return self.value < other.value
Éric Araujo374274d2011-03-19 04:29:36 +0100477 def __eq__(self, other):
478 return self.value == other.value
Ezio Melotti2623a372010-11-21 13:34:58 +0000479 self.assertTrue(A(1) < A(2))
480 self.assertTrue(A(2) > A(1))
481 self.assertTrue(A(1) <= A(2))
482 self.assertTrue(A(2) >= A(1))
483 self.assertTrue(A(2) <= A(2))
484 self.assertTrue(A(2) >= A(2))
Raymond Hettinger06bc0b62010-04-04 22:24:03 +0000485
486 def test_total_ordering_le(self):
487 @functools.total_ordering
488 class A:
489 def __init__(self, value):
490 self.value = value
491 def __le__(self, other):
492 return self.value <= other.value
Éric Araujo374274d2011-03-19 04:29:36 +0100493 def __eq__(self, other):
494 return self.value == other.value
Ezio Melotti2623a372010-11-21 13:34:58 +0000495 self.assertTrue(A(1) < A(2))
496 self.assertTrue(A(2) > A(1))
497 self.assertTrue(A(1) <= A(2))
498 self.assertTrue(A(2) >= A(1))
499 self.assertTrue(A(2) <= A(2))
500 self.assertTrue(A(2) >= A(2))
Raymond Hettinger06bc0b62010-04-04 22:24:03 +0000501
502 def test_total_ordering_gt(self):
503 @functools.total_ordering
504 class A:
505 def __init__(self, value):
506 self.value = value
507 def __gt__(self, other):
508 return self.value > other.value
Éric Araujo374274d2011-03-19 04:29:36 +0100509 def __eq__(self, other):
510 return self.value == other.value
Ezio Melotti2623a372010-11-21 13:34:58 +0000511 self.assertTrue(A(1) < A(2))
512 self.assertTrue(A(2) > A(1))
513 self.assertTrue(A(1) <= A(2))
514 self.assertTrue(A(2) >= A(1))
515 self.assertTrue(A(2) <= A(2))
516 self.assertTrue(A(2) >= A(2))
Raymond Hettinger06bc0b62010-04-04 22:24:03 +0000517
518 def test_total_ordering_ge(self):
519 @functools.total_ordering
520 class A:
521 def __init__(self, value):
522 self.value = value
523 def __ge__(self, other):
524 return self.value >= other.value
Éric Araujo374274d2011-03-19 04:29:36 +0100525 def __eq__(self, other):
526 return self.value == other.value
Ezio Melotti2623a372010-11-21 13:34:58 +0000527 self.assertTrue(A(1) < A(2))
528 self.assertTrue(A(2) > A(1))
529 self.assertTrue(A(1) <= A(2))
530 self.assertTrue(A(2) >= A(1))
531 self.assertTrue(A(2) <= A(2))
532 self.assertTrue(A(2) >= A(2))
Raymond Hettinger06bc0b62010-04-04 22:24:03 +0000533
534 def test_total_ordering_no_overwrite(self):
535 # new methods should not overwrite existing
536 @functools.total_ordering
Benjamin Peterson9d0eaac2010-08-23 17:45:31 +0000537 class A(str):
Raymond Hettinger06bc0b62010-04-04 22:24:03 +0000538 pass
Ezio Melotti2623a372010-11-21 13:34:58 +0000539 self.assertTrue(A("a") < A("b"))
540 self.assertTrue(A("b") > A("a"))
541 self.assertTrue(A("a") <= A("b"))
542 self.assertTrue(A("b") >= A("a"))
543 self.assertTrue(A("b") <= A("b"))
544 self.assertTrue(A("b") >= A("b"))
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000545
Benjamin Petersona11da592010-04-11 01:40:32 +0000546 def test_no_operations_defined(self):
547 with self.assertRaises(ValueError):
548 @functools.total_ordering
549 class A:
550 pass
551
Éric Araujo374274d2011-03-19 04:29:36 +0100552 def test_bug_10042(self):
553 @functools.total_ordering
554 class TestTO:
555 def __init__(self, value):
556 self.value = value
557 def __eq__(self, other):
558 if isinstance(other, TestTO):
559 return self.value == other.value
560 return False
561 def __lt__(self, other):
562 if isinstance(other, TestTO):
563 return self.value < other.value
564 raise TypeError
565 with self.assertRaises(TypeError):
566 TestTO(8) <= ()
567
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000568def test_main(verbose=None):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000569 test_classes = (
570 TestPartial,
571 TestPartialSubclass,
572 TestPythonPartial,
Nick Coghlan676725d2006-06-08 13:54:49 +0000573 TestUpdateWrapper,
Benjamin Peterson9d0eaac2010-08-23 17:45:31 +0000574 TestTotalOrdering,
Brett Cannon83e81842008-08-09 23:30:55 +0000575 TestWraps,
576 TestReduce,
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000577 )
578 test_support.run_unittest(*test_classes)
579
580 # verify reference counting
581 if verbose and hasattr(sys, "gettotalrefcount"):
582 import gc
583 counts = [None] * 5
584 for i in xrange(len(counts)):
585 test_support.run_unittest(*test_classes)
586 gc.collect()
587 counts[i] = sys.gettotalrefcount()
588 print counts
589
590if __name__ == '__main__':
591 test_main(verbose=True)