blob: f9e8a97fc8268f60a2ac62b9d44408a7bfbf6fe9 [file] [log] [blame]
Thomas Wouters4d70c3d2006-06-08 14:42:34 +00001import functools
R. David Murray378c0cf2010-02-24 01:46:21 +00002import sys
Raymond Hettinger9c323f82005-02-28 19:39:44 +00003import unittest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004from test import support
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +00005from weakref import proxy
Jack Diederiche0cbd692009-04-01 04:27:09 +00006import pickle
Georg Brandl2e7346a2010-07-31 18:09:23 +00007from random import choice
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 Diederiche0cbd692009-04-01 04:27:09 +000025def signature(part):
26 """ return the signature of a partial object """
27 return (part.func, part.args, part.keywords, part.__dict__)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000028
Raymond Hettinger9c323f82005-02-28 19:39:44 +000029class TestPartial(unittest.TestCase):
30
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000031 thetype = functools.partial
Raymond Hettinger9c323f82005-02-28 19:39:44 +000032
33 def test_basic_examples(self):
34 p = self.thetype(capture, 1, 2, a=10, b=20)
35 self.assertEqual(p(3, 4, b=30, c=40),
36 ((1, 2, 3, 4), dict(a=10, b=30, c=40)))
37 p = self.thetype(map, lambda x: x*10)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000038 self.assertEqual(list(p([1,2,3,4])), [10, 20, 30, 40])
Raymond Hettinger9c323f82005-02-28 19:39:44 +000039
40 def test_attributes(self):
41 p = self.thetype(capture, 1, 2, a=10, b=20)
42 # attributes should be readable
43 self.assertEqual(p.func, capture)
44 self.assertEqual(p.args, (1, 2))
45 self.assertEqual(p.keywords, dict(a=10, b=20))
46 # attributes should not be writable
47 if not isinstance(self.thetype, type):
48 return
Georg Brandl89fad142010-03-14 10:23:39 +000049 self.assertRaises(AttributeError, setattr, p, 'func', map)
50 self.assertRaises(AttributeError, setattr, p, 'args', (1, 2))
51 self.assertRaises(AttributeError, setattr, p, 'keywords', dict(a=1, b=2))
52
53 p = self.thetype(hex)
54 try:
55 del p.__dict__
56 except TypeError:
57 pass
58 else:
59 self.fail('partial object allowed __dict__ to be deleted')
Raymond Hettinger9c323f82005-02-28 19:39:44 +000060
61 def test_argument_checking(self):
62 self.assertRaises(TypeError, self.thetype) # need at least a func arg
63 try:
64 self.thetype(2)()
65 except TypeError:
66 pass
67 else:
68 self.fail('First arg not checked for callability')
69
70 def test_protection_of_callers_dict_argument(self):
71 # a caller's dictionary should not be altered by partial
72 def func(a=10, b=20):
73 return a
74 d = {'a':3}
75 p = self.thetype(func, a=5)
76 self.assertEqual(p(**d), 3)
77 self.assertEqual(d, {'a':3})
78 p(b=7)
79 self.assertEqual(d, {'a':3})
80
81 def test_arg_combinations(self):
82 # exercise special code paths for zero args in either partial
83 # object or the caller
84 p = self.thetype(capture)
85 self.assertEqual(p(), ((), {}))
86 self.assertEqual(p(1,2), ((1,2), {}))
87 p = self.thetype(capture, 1, 2)
88 self.assertEqual(p(), ((1,2), {}))
89 self.assertEqual(p(3,4), ((1,2,3,4), {}))
90
91 def test_kw_combinations(self):
92 # exercise special code paths for no keyword args in
93 # either the partial object or the caller
94 p = self.thetype(capture)
95 self.assertEqual(p(), ((), {}))
96 self.assertEqual(p(a=1), ((), {'a':1}))
97 p = self.thetype(capture, a=1)
98 self.assertEqual(p(), ((), {'a':1}))
99 self.assertEqual(p(b=2), ((), {'a':1, 'b':2}))
100 # keyword args in the call override those in the partial object
101 self.assertEqual(p(a=3, b=2), ((), {'a':3, 'b':2}))
102
103 def test_positional(self):
104 # make sure positional arguments are captured correctly
105 for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]:
106 p = self.thetype(capture, *args)
107 expected = args + ('x',)
108 got, empty = p('x')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000109 self.assertTrue(expected == got and empty == {})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000110
111 def test_keyword(self):
112 # make sure keyword arguments are captured correctly
113 for a in ['a', 0, None, 3.5]:
114 p = self.thetype(capture, a=a)
115 expected = {'a':a,'x':None}
116 empty, got = p(x=None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000117 self.assertTrue(expected == got and empty == ())
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000118
119 def test_no_side_effects(self):
120 # make sure there are no side effects that affect subsequent calls
121 p = self.thetype(capture, 0, a=1)
122 args1, kw1 = p(1, b=2)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000123 self.assertTrue(args1 == (0,1) and kw1 == {'a':1,'b':2})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000124 args2, kw2 = p()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000125 self.assertTrue(args2 == (0,) and kw2 == {'a':1})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000126
127 def test_error_propagation(self):
128 def f(x, y):
129 x / y
130 self.assertRaises(ZeroDivisionError, self.thetype(f, 1, 0))
131 self.assertRaises(ZeroDivisionError, self.thetype(f, 1), 0)
132 self.assertRaises(ZeroDivisionError, self.thetype(f), 1, 0)
133 self.assertRaises(ZeroDivisionError, self.thetype(f, y=0), 1)
134
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000135 def test_weakref(self):
136 f = self.thetype(int, base=16)
137 p = proxy(f)
138 self.assertEqual(f.func, p.func)
139 f = None
140 self.assertRaises(ReferenceError, getattr, p, 'func')
141
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000142 def test_with_bound_and_unbound_methods(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000143 data = list(map(str, range(10)))
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000144 join = self.thetype(str.join, '')
145 self.assertEqual(join(data), '0123456789')
146 join = self.thetype(''.join)
147 self.assertEqual(join(data), '0123456789')
Tim Peterseba28be2005-03-28 01:08:02 +0000148
Jack Diederiche0cbd692009-04-01 04:27:09 +0000149 def test_pickle(self):
150 f = self.thetype(signature, 'asdf', bar=True)
151 f.add_something_to__dict__ = True
152 f_copy = pickle.loads(pickle.dumps(f))
153 self.assertEqual(signature(f), signature(f_copy))
154
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000155class PartialSubclass(functools.partial):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000156 pass
157
158class TestPartialSubclass(TestPartial):
159
160 thetype = PartialSubclass
161
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000162class TestPythonPartial(TestPartial):
163
164 thetype = PythonPartial
165
Jack Diederiche0cbd692009-04-01 04:27:09 +0000166 # the python version isn't picklable
167 def test_pickle(self): pass
168
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000169class TestUpdateWrapper(unittest.TestCase):
170
171 def check_wrapper(self, wrapper, wrapped,
172 assigned=functools.WRAPPER_ASSIGNMENTS,
173 updated=functools.WRAPPER_UPDATES):
174 # Check attributes were assigned
175 for name in assigned:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000176 self.assertTrue(getattr(wrapper, name) is getattr(wrapped, name))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000177 # Check attributes were updated
178 for name in updated:
179 wrapper_attr = getattr(wrapper, name)
180 wrapped_attr = getattr(wrapped, name)
181 for key in wrapped_attr:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000182 self.assertTrue(wrapped_attr[key] is wrapper_attr[key])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000183
R. David Murray378c0cf2010-02-24 01:46:21 +0000184 def _default_update(self):
Antoine Pitrou560f7642010-08-04 18:28:02 +0000185 def f(a:'This is a new annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000186 """This is a test"""
187 pass
188 f.attr = 'This is also a test'
Antoine Pitrou560f7642010-08-04 18:28:02 +0000189 def wrapper(b:'This is the prior annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000190 pass
191 functools.update_wrapper(wrapper, f)
R. David Murray378c0cf2010-02-24 01:46:21 +0000192 return wrapper, f
193
194 def test_default_update(self):
195 wrapper, f = self._default_update()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000196 self.check_wrapper(wrapper, f)
197 self.assertEqual(wrapper.__name__, 'f')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000198 self.assertEqual(wrapper.attr, 'This is also a test')
Antoine Pitrou560f7642010-08-04 18:28:02 +0000199 self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation')
200 self.assertNotIn('b', wrapper.__annotations__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000201
R. David Murray378c0cf2010-02-24 01:46:21 +0000202 @unittest.skipIf(sys.flags.optimize >= 2,
203 "Docstrings are omitted with -O2 and above")
204 def test_default_update_doc(self):
205 wrapper, f = self._default_update()
206 self.assertEqual(wrapper.__doc__, 'This is a test')
207
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000208 def test_no_update(self):
209 def f():
210 """This is a test"""
211 pass
212 f.attr = 'This is also a test'
213 def wrapper():
214 pass
215 functools.update_wrapper(wrapper, f, (), ())
216 self.check_wrapper(wrapper, f, (), ())
217 self.assertEqual(wrapper.__name__, 'wrapper')
218 self.assertEqual(wrapper.__doc__, None)
Antoine Pitrou560f7642010-08-04 18:28:02 +0000219 self.assertEqual(wrapper.__annotations__, {})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000220 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000221
222 def test_selective_update(self):
223 def f():
224 pass
225 f.attr = 'This is a different test'
226 f.dict_attr = dict(a=1, b=2, c=3)
227 def wrapper():
228 pass
229 wrapper.dict_attr = {}
230 assign = ('attr',)
231 update = ('dict_attr',)
232 functools.update_wrapper(wrapper, f, assign, update)
233 self.check_wrapper(wrapper, f, assign, update)
234 self.assertEqual(wrapper.__name__, 'wrapper')
235 self.assertEqual(wrapper.__doc__, None)
236 self.assertEqual(wrapper.attr, 'This is a different test')
237 self.assertEqual(wrapper.dict_attr, f.dict_attr)
238
Thomas Wouters89f507f2006-12-13 04:49:30 +0000239 def test_builtin_update(self):
240 # Test for bug #1576241
241 def wrapper():
242 pass
243 functools.update_wrapper(wrapper, max)
244 self.assertEqual(wrapper.__name__, 'max')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000245 self.assertTrue(wrapper.__doc__.startswith('max('))
Antoine Pitrou560f7642010-08-04 18:28:02 +0000246 self.assertEqual(wrapper.__annotations__, {})
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000247
248class TestWraps(TestUpdateWrapper):
249
R. David Murray378c0cf2010-02-24 01:46:21 +0000250 def _default_update(self):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000251 def f():
252 """This is a test"""
253 pass
254 f.attr = 'This is also a test'
255 @functools.wraps(f)
256 def wrapper():
257 pass
258 self.check_wrapper(wrapper, f)
R. David Murray378c0cf2010-02-24 01:46:21 +0000259 return wrapper
260
261 def test_default_update(self):
262 wrapper = self._default_update()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000263 self.assertEqual(wrapper.__name__, 'f')
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000264 self.assertEqual(wrapper.attr, 'This is also a test')
265
R. David Murray378c0cf2010-02-24 01:46:21 +0000266 @unittest.skipIf(not sys.flags.optimize <= 1,
267 "Docstrings are omitted with -O2 and above")
268 def test_default_update_doc(self):
269 wrapper = self._default_update()
270 self.assertEqual(wrapper.__doc__, 'This is a test')
271
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000272 def test_no_update(self):
273 def f():
274 """This is a test"""
275 pass
276 f.attr = 'This is also a test'
277 @functools.wraps(f, (), ())
278 def wrapper():
279 pass
280 self.check_wrapper(wrapper, f, (), ())
281 self.assertEqual(wrapper.__name__, 'wrapper')
282 self.assertEqual(wrapper.__doc__, None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000283 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000284
285 def test_selective_update(self):
286 def f():
287 pass
288 f.attr = 'This is a different test'
289 f.dict_attr = dict(a=1, b=2, c=3)
290 def add_dict_attr(f):
291 f.dict_attr = {}
292 return f
293 assign = ('attr',)
294 update = ('dict_attr',)
295 @functools.wraps(f, assign, update)
296 @add_dict_attr
297 def wrapper():
298 pass
299 self.check_wrapper(wrapper, f, assign, update)
300 self.assertEqual(wrapper.__name__, 'wrapper')
301 self.assertEqual(wrapper.__doc__, None)
302 self.assertEqual(wrapper.attr, 'This is a different test')
303 self.assertEqual(wrapper.dict_attr, f.dict_attr)
304
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000305class TestReduce(unittest.TestCase):
306 func = functools.reduce
307
308 def test_reduce(self):
309 class Squares:
310 def __init__(self, max):
311 self.max = max
312 self.sofar = []
313
314 def __len__(self):
315 return len(self.sofar)
316
317 def __getitem__(self, i):
318 if not 0 <= i < self.max: raise IndexError
319 n = len(self.sofar)
320 while n <= i:
321 self.sofar.append(n*n)
322 n += 1
323 return self.sofar[i]
Guido van Rossumd8faa362007-04-27 19:54:29 +0000324
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000325 self.assertEqual(self.func(lambda x, y: x+y, ['a', 'b', 'c'], ''), 'abc')
326 self.assertEqual(
327 self.func(lambda x, y: x+y, [['a', 'c'], [], ['d', 'w']], []),
328 ['a','c','d','w']
329 )
330 self.assertEqual(self.func(lambda x, y: x*y, range(2,8), 1), 5040)
331 self.assertEqual(
Guido van Rossume2a383d2007-01-15 16:59:06 +0000332 self.func(lambda x, y: x*y, range(2,21), 1),
333 2432902008176640000
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000334 )
335 self.assertEqual(self.func(lambda x, y: x+y, Squares(10)), 285)
336 self.assertEqual(self.func(lambda x, y: x+y, Squares(10), 0), 285)
337 self.assertEqual(self.func(lambda x, y: x+y, Squares(0), 0), 0)
338 self.assertRaises(TypeError, self.func)
339 self.assertRaises(TypeError, self.func, 42, 42)
340 self.assertRaises(TypeError, self.func, 42, 42, 42)
341 self.assertEqual(self.func(42, "1"), "1") # func is never called with one item
342 self.assertEqual(self.func(42, "", "1"), "1") # func is never called with one item
343 self.assertRaises(TypeError, self.func, 42, (42, 42))
344
345 class BadSeq:
346 def __getitem__(self, index):
347 raise ValueError
348 self.assertRaises(ValueError, self.func, 42, BadSeq())
349
350 # Test reduce()'s use of iterators.
351 def test_iterator_usage(self):
352 class SequenceClass:
353 def __init__(self, n):
354 self.n = n
355 def __getitem__(self, i):
356 if 0 <= i < self.n:
357 return i
358 else:
359 raise IndexError
Guido van Rossumd8faa362007-04-27 19:54:29 +0000360
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000361 from operator import add
362 self.assertEqual(self.func(add, SequenceClass(5)), 10)
363 self.assertEqual(self.func(add, SequenceClass(5), 42), 52)
364 self.assertRaises(TypeError, self.func, add, SequenceClass(0))
365 self.assertEqual(self.func(add, SequenceClass(0), 42), 42)
366 self.assertEqual(self.func(add, SequenceClass(1)), 0)
367 self.assertEqual(self.func(add, SequenceClass(1), 42), 42)
368
369 d = {"one": 1, "two": 2, "three": 3}
370 self.assertEqual(self.func(add, d), "".join(d.keys()))
371
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000372class TestCmpToKey(unittest.TestCase):
373 def test_cmp_to_key(self):
374 def mycmp(x, y):
375 return y - x
376 self.assertEqual(sorted(range(5), key=functools.cmp_to_key(mycmp)),
377 [4, 3, 2, 1, 0])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000378
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000379 def test_hash(self):
380 def mycmp(x, y):
381 return y - x
382 key = functools.cmp_to_key(mycmp)
383 k = key(10)
384 self.assertRaises(TypeError, hash(k))
385
386class TestTotalOrdering(unittest.TestCase):
387
388 def test_total_ordering_lt(self):
389 @functools.total_ordering
390 class A:
391 def __init__(self, value):
392 self.value = value
393 def __lt__(self, other):
394 return self.value < other.value
395 self.assert_(A(1) < A(2))
396 self.assert_(A(2) > A(1))
397 self.assert_(A(1) <= A(2))
398 self.assert_(A(2) >= A(1))
399 self.assert_(A(2) <= A(2))
400 self.assert_(A(2) >= A(2))
401
402 def test_total_ordering_le(self):
403 @functools.total_ordering
404 class A:
405 def __init__(self, value):
406 self.value = value
407 def __le__(self, other):
408 return self.value <= other.value
409 self.assert_(A(1) < A(2))
410 self.assert_(A(2) > A(1))
411 self.assert_(A(1) <= A(2))
412 self.assert_(A(2) >= A(1))
413 self.assert_(A(2) <= A(2))
414 self.assert_(A(2) >= A(2))
415
416 def test_total_ordering_gt(self):
417 @functools.total_ordering
418 class A:
419 def __init__(self, value):
420 self.value = value
421 def __gt__(self, other):
422 return self.value > other.value
423 self.assert_(A(1) < A(2))
424 self.assert_(A(2) > A(1))
425 self.assert_(A(1) <= A(2))
426 self.assert_(A(2) >= A(1))
427 self.assert_(A(2) <= A(2))
428 self.assert_(A(2) >= A(2))
429
430 def test_total_ordering_ge(self):
431 @functools.total_ordering
432 class A:
433 def __init__(self, value):
434 self.value = value
435 def __ge__(self, other):
436 return self.value >= other.value
437 self.assert_(A(1) < A(2))
438 self.assert_(A(2) > A(1))
439 self.assert_(A(1) <= A(2))
440 self.assert_(A(2) >= A(1))
441 self.assert_(A(2) <= A(2))
442 self.assert_(A(2) >= A(2))
443
444 def test_total_ordering_no_overwrite(self):
445 # new methods should not overwrite existing
446 @functools.total_ordering
447 class A(int):
448 raise Exception()
449 self.assert_(A(1) < A(2))
450 self.assert_(A(2) > A(1))
451 self.assert_(A(1) <= A(2))
452 self.assert_(A(2) >= A(1))
453 self.assert_(A(2) <= A(2))
454 self.assert_(A(2) >= A(2))
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000455
Benjamin Peterson42ebee32010-04-11 01:43:16 +0000456 def test_no_operations_defined(self):
457 with self.assertRaises(ValueError):
458 @functools.total_ordering
459 class A:
460 pass
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000461
Georg Brandl2e7346a2010-07-31 18:09:23 +0000462class TestLRU(unittest.TestCase):
463
464 def test_lru(self):
465 def orig(x, y):
466 return 3*x+y
467 f = functools.lru_cache(maxsize=20)(orig)
468
469 domain = range(5)
470 for i in range(1000):
471 x, y = choice(domain), choice(domain)
472 actual = f(x, y)
473 expected = orig(x, y)
474 self.assertEquals(actual, expected)
475 self.assert_(f.hits > f.misses)
476 self.assertEquals(f.hits + f.misses, 1000)
477
478 f.clear() # test clearing
479 self.assertEqual(f.hits, 0)
480 self.assertEqual(f.misses, 0)
481 f(x, y)
482 self.assertEqual(f.hits, 0)
483 self.assertEqual(f.misses, 1)
484
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000485 # test size zero (which means "never-cache")
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000486 @functools.lru_cache(0)
487 def f():
488 nonlocal f_cnt
489 f_cnt += 1
490 return 20
Raymond Hettingerf3098282010-08-15 03:30:45 +0000491 f_cnt = 0
492 for i in range(5):
493 self.assertEqual(f(), 20)
494 self.assertEqual(f_cnt, 5)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000495
496 # test size one
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000497 @functools.lru_cache(1)
498 def f():
499 nonlocal f_cnt
500 f_cnt += 1
501 return 20
Raymond Hettingerf3098282010-08-15 03:30:45 +0000502 f_cnt = 0
503 for i in range(5):
504 self.assertEqual(f(), 20)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000505 self.assertEqual(f_cnt, 1)
506
Raymond Hettingerf3098282010-08-15 03:30:45 +0000507 # test size two
508 @functools.lru_cache(2)
509 def f(x):
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000510 nonlocal f_cnt
511 f_cnt += 1
Raymond Hettingerf3098282010-08-15 03:30:45 +0000512 return x*10
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000513 f_cnt = 0
Raymond Hettingerf3098282010-08-15 03:30:45 +0000514 for x in 7, 9, 7, 9, 7, 9, 8, 8, 8, 9, 9, 9, 8, 8, 8, 7:
515 # * * * *
516 self.assertEqual(f(x), x*10)
517 self.assertEqual(f_cnt, 4)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000518
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000519def test_main(verbose=None):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000520 test_classes = (
521 TestPartial,
522 TestPartialSubclass,
523 TestPythonPartial,
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000524 TestUpdateWrapper,
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000525 TestWraps,
Georg Brandl2e7346a2010-07-31 18:09:23 +0000526 TestReduce,
527 TestLRU,
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000528 )
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000529 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000530
531 # verify reference counting
532 if verbose and hasattr(sys, "gettotalrefcount"):
533 import gc
534 counts = [None] * 5
Guido van Rossum805365e2007-05-07 22:24:25 +0000535 for i in range(len(counts)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000536 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000537 gc.collect()
538 counts[i] = sys.gettotalrefcount()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000539 print(counts)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000540
541if __name__ == '__main__':
542 test_main(verbose=True)