blob: ee1f5dbd7c387477a6774183d451868ce10d2e7f [file] [log] [blame]
Raymond Hettinger003be522011-05-03 11:01:32 -07001import collections
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
Antoine Pitroub5b37142012-11-13 21:35:40 +01009import functools
10
11original_functools = functools
12py_functools = support.import_fresh_module('functools', blocked=['_functools'])
13c_functools = support.import_fresh_module('functools', fresh=['_functools'])
14
15class BaseTest(unittest.TestCase):
16
17 """Base class required for testing C and Py implementations."""
18
19 def setUp(self):
20
21 # The module must be explicitly set so that the proper
22 # interaction between the c module and the python module
23 # can be controlled.
24 self.partial = self.module.partial
25 super(BaseTest, self).setUp()
26
27class BaseTestC(BaseTest):
28 module = c_functools
29
30class BaseTestPy(BaseTest):
31 module = py_functools
32
33PythonPartial = py_functools.partial
Raymond Hettinger9c323f82005-02-28 19:39:44 +000034
35def capture(*args, **kw):
36 """capture all positional and keyword arguments"""
37 return args, kw
38
Jack Diederiche0cbd692009-04-01 04:27:09 +000039def signature(part):
40 """ return the signature of a partial object """
41 return (part.func, part.args, part.keywords, part.__dict__)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000042
Antoine Pitroub5b37142012-11-13 21:35:40 +010043class TestPartial(object):
Raymond Hettinger9c323f82005-02-28 19:39:44 +000044
Antoine Pitroub5b37142012-11-13 21:35:40 +010045 partial = functools.partial
Raymond Hettinger9c323f82005-02-28 19:39:44 +000046
47 def test_basic_examples(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010048 p = self.partial(capture, 1, 2, a=10, b=20)
49 self.assertTrue(callable(p))
Raymond Hettinger9c323f82005-02-28 19:39:44 +000050 self.assertEqual(p(3, 4, b=30, c=40),
51 ((1, 2, 3, 4), dict(a=10, b=30, c=40)))
Antoine Pitroub5b37142012-11-13 21:35:40 +010052 p = self.partial(map, lambda x: x*10)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000053 self.assertEqual(list(p([1,2,3,4])), [10, 20, 30, 40])
Raymond Hettinger9c323f82005-02-28 19:39:44 +000054
55 def test_attributes(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010056 p = self.partial(capture, 1, 2, a=10, b=20)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000057 # attributes should be readable
58 self.assertEqual(p.func, capture)
59 self.assertEqual(p.args, (1, 2))
60 self.assertEqual(p.keywords, dict(a=10, b=20))
61 # attributes should not be writable
Antoine Pitroub5b37142012-11-13 21:35:40 +010062 if not isinstance(self.partial, type):
Raymond Hettinger9c323f82005-02-28 19:39:44 +000063 return
Georg Brandl89fad142010-03-14 10:23:39 +000064 self.assertRaises(AttributeError, setattr, p, 'func', map)
65 self.assertRaises(AttributeError, setattr, p, 'args', (1, 2))
66 self.assertRaises(AttributeError, setattr, p, 'keywords', dict(a=1, b=2))
67
Antoine Pitroub5b37142012-11-13 21:35:40 +010068 p = self.partial(hex)
Georg Brandl89fad142010-03-14 10:23:39 +000069 try:
70 del p.__dict__
71 except TypeError:
72 pass
73 else:
74 self.fail('partial object allowed __dict__ to be deleted')
Raymond Hettinger9c323f82005-02-28 19:39:44 +000075
76 def test_argument_checking(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010077 self.assertRaises(TypeError, self.partial) # need at least a func arg
Raymond Hettinger9c323f82005-02-28 19:39:44 +000078 try:
Antoine Pitroub5b37142012-11-13 21:35:40 +010079 self.partial(2)()
Raymond Hettinger9c323f82005-02-28 19:39:44 +000080 except TypeError:
81 pass
82 else:
83 self.fail('First arg not checked for callability')
84
85 def test_protection_of_callers_dict_argument(self):
86 # a caller's dictionary should not be altered by partial
87 def func(a=10, b=20):
88 return a
89 d = {'a':3}
Antoine Pitroub5b37142012-11-13 21:35:40 +010090 p = self.partial(func, a=5)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000091 self.assertEqual(p(**d), 3)
92 self.assertEqual(d, {'a':3})
93 p(b=7)
94 self.assertEqual(d, {'a':3})
95
96 def test_arg_combinations(self):
97 # exercise special code paths for zero args in either partial
98 # object or the caller
Antoine Pitroub5b37142012-11-13 21:35:40 +010099 p = self.partial(capture)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000100 self.assertEqual(p(), ((), {}))
101 self.assertEqual(p(1,2), ((1,2), {}))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100102 p = self.partial(capture, 1, 2)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000103 self.assertEqual(p(), ((1,2), {}))
104 self.assertEqual(p(3,4), ((1,2,3,4), {}))
105
106 def test_kw_combinations(self):
107 # exercise special code paths for no keyword args in
108 # either the partial object or the caller
Antoine Pitroub5b37142012-11-13 21:35:40 +0100109 p = self.partial(capture)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000110 self.assertEqual(p(), ((), {}))
111 self.assertEqual(p(a=1), ((), {'a':1}))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100112 p = self.partial(capture, a=1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000113 self.assertEqual(p(), ((), {'a':1}))
114 self.assertEqual(p(b=2), ((), {'a':1, 'b':2}))
115 # keyword args in the call override those in the partial object
116 self.assertEqual(p(a=3, b=2), ((), {'a':3, 'b':2}))
117
118 def test_positional(self):
119 # make sure positional arguments are captured correctly
120 for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100121 p = self.partial(capture, *args)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000122 expected = args + ('x',)
123 got, empty = p('x')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000124 self.assertTrue(expected == got and empty == {})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000125
126 def test_keyword(self):
127 # make sure keyword arguments are captured correctly
128 for a in ['a', 0, None, 3.5]:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100129 p = self.partial(capture, a=a)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000130 expected = {'a':a,'x':None}
131 empty, got = p(x=None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000132 self.assertTrue(expected == got and empty == ())
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000133
134 def test_no_side_effects(self):
135 # make sure there are no side effects that affect subsequent calls
Antoine Pitroub5b37142012-11-13 21:35:40 +0100136 p = self.partial(capture, 0, a=1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000137 args1, kw1 = p(1, b=2)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000138 self.assertTrue(args1 == (0,1) and kw1 == {'a':1,'b':2})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000139 args2, kw2 = p()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000140 self.assertTrue(args2 == (0,) and kw2 == {'a':1})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000141
142 def test_error_propagation(self):
143 def f(x, y):
144 x / y
Antoine Pitroub5b37142012-11-13 21:35:40 +0100145 self.assertRaises(ZeroDivisionError, self.partial(f, 1, 0))
146 self.assertRaises(ZeroDivisionError, self.partial(f, 1), 0)
147 self.assertRaises(ZeroDivisionError, self.partial(f), 1, 0)
148 self.assertRaises(ZeroDivisionError, self.partial(f, y=0), 1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000149
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000150 def test_weakref(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100151 f = self.partial(int, base=16)
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000152 p = proxy(f)
153 self.assertEqual(f.func, p.func)
154 f = None
155 self.assertRaises(ReferenceError, getattr, p, 'func')
156
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000157 def test_with_bound_and_unbound_methods(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000158 data = list(map(str, range(10)))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100159 join = self.partial(str.join, '')
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000160 self.assertEqual(join(data), '0123456789')
Antoine Pitroub5b37142012-11-13 21:35:40 +0100161 join = self.partial(''.join)
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000162 self.assertEqual(join(data), '0123456789')
Tim Peterseba28be2005-03-28 01:08:02 +0000163
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000164 def test_repr(self):
165 args = (object(), object())
166 args_repr = ', '.join(repr(a) for a in args)
167 kwargs = {'a': object(), 'b': object()}
168 kwargs_repr = ', '.join("%s=%r" % (k, v) for k, v in kwargs.items())
Antoine Pitroub5b37142012-11-13 21:35:40 +0100169 if self.partial is functools.partial:
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000170 name = 'functools.partial'
171 else:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100172 name = self.partial.__name__
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000173
Antoine Pitroub5b37142012-11-13 21:35:40 +0100174 f = self.partial(capture)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000175 self.assertEqual('{}({!r})'.format(name, capture),
176 repr(f))
177
Antoine Pitroub5b37142012-11-13 21:35:40 +0100178 f = self.partial(capture, *args)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000179 self.assertEqual('{}({!r}, {})'.format(name, capture, args_repr),
180 repr(f))
181
Antoine Pitroub5b37142012-11-13 21:35:40 +0100182 f = self.partial(capture, **kwargs)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000183 self.assertEqual('{}({!r}, {})'.format(name, capture, kwargs_repr),
184 repr(f))
185
Antoine Pitroub5b37142012-11-13 21:35:40 +0100186 f = self.partial(capture, *args, **kwargs)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000187 self.assertEqual('{}({!r}, {}, {})'.format(name, capture, args_repr, kwargs_repr),
188 repr(f))
189
Jack Diederiche0cbd692009-04-01 04:27:09 +0000190 def test_pickle(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100191 f = self.partial(signature, 'asdf', bar=True)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000192 f.add_something_to__dict__ = True
193 f_copy = pickle.loads(pickle.dumps(f))
194 self.assertEqual(signature(f), signature(f_copy))
195
Antoine Pitroub5b37142012-11-13 21:35:40 +0100196class TestPartialC(BaseTestC, TestPartial):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000197 pass
198
Antoine Pitroub5b37142012-11-13 21:35:40 +0100199class TestPartialPy(BaseTestPy, TestPartial):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000200
Antoine Pitroub5b37142012-11-13 21:35:40 +0100201 def test_pickle(self):
202 raise unittest.SkipTest("Python implementation of partial isn't picklable")
Antoine Pitrou33543272012-11-13 21:36:21 +0100203
Antoine Pitroub5b37142012-11-13 21:35:40 +0100204 def test_repr(self):
205 raise unittest.SkipTest("Python implementation of partial uses own repr")
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000206
Antoine Pitroub5b37142012-11-13 21:35:40 +0100207class TestPartialCSubclass(BaseTestC, TestPartial):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000208
Antoine Pitroub5b37142012-11-13 21:35:40 +0100209 class PartialSubclass(c_functools.partial):
210 pass
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000211
Antoine Pitroub5b37142012-11-13 21:35:40 +0100212 partial = staticmethod(PartialSubclass)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000213
Antoine Pitroub5b37142012-11-13 21:35:40 +0100214class TestPartialPySubclass(TestPartialPy):
215
216 class PartialSubclass(c_functools.partial):
217 pass
218
219 partial = staticmethod(PartialSubclass)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000220
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000221class TestUpdateWrapper(unittest.TestCase):
222
223 def check_wrapper(self, wrapper, wrapped,
224 assigned=functools.WRAPPER_ASSIGNMENTS,
225 updated=functools.WRAPPER_UPDATES):
226 # Check attributes were assigned
227 for name in assigned:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000228 self.assertTrue(getattr(wrapper, name) is getattr(wrapped, name))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000229 # Check attributes were updated
230 for name in updated:
231 wrapper_attr = getattr(wrapper, name)
232 wrapped_attr = getattr(wrapped, name)
233 for key in wrapped_attr:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000234 self.assertTrue(wrapped_attr[key] is wrapper_attr[key])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000235
R. David Murray378c0cf2010-02-24 01:46:21 +0000236 def _default_update(self):
Antoine Pitrou560f7642010-08-04 18:28:02 +0000237 def f(a:'This is a new annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000238 """This is a test"""
239 pass
240 f.attr = 'This is also a test'
Antoine Pitrou560f7642010-08-04 18:28:02 +0000241 def wrapper(b:'This is the prior annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000242 pass
243 functools.update_wrapper(wrapper, f)
R. David Murray378c0cf2010-02-24 01:46:21 +0000244 return wrapper, f
245
246 def test_default_update(self):
247 wrapper, f = self._default_update()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000248 self.check_wrapper(wrapper, f)
Nick Coghlan98876832010-08-17 06:17:18 +0000249 self.assertIs(wrapper.__wrapped__, f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000250 self.assertEqual(wrapper.__name__, 'f')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600251 self.assertEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000252 self.assertEqual(wrapper.attr, 'This is also a test')
Antoine Pitrou560f7642010-08-04 18:28:02 +0000253 self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation')
254 self.assertNotIn('b', wrapper.__annotations__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000255
R. David Murray378c0cf2010-02-24 01:46:21 +0000256 @unittest.skipIf(sys.flags.optimize >= 2,
257 "Docstrings are omitted with -O2 and above")
258 def test_default_update_doc(self):
259 wrapper, f = self._default_update()
260 self.assertEqual(wrapper.__doc__, 'This is a test')
261
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000262 def test_no_update(self):
263 def f():
264 """This is a test"""
265 pass
266 f.attr = 'This is also a test'
267 def wrapper():
268 pass
269 functools.update_wrapper(wrapper, f, (), ())
270 self.check_wrapper(wrapper, f, (), ())
271 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600272 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000273 self.assertEqual(wrapper.__doc__, None)
Antoine Pitrou560f7642010-08-04 18:28:02 +0000274 self.assertEqual(wrapper.__annotations__, {})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000275 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000276
277 def test_selective_update(self):
278 def f():
279 pass
280 f.attr = 'This is a different test'
281 f.dict_attr = dict(a=1, b=2, c=3)
282 def wrapper():
283 pass
284 wrapper.dict_attr = {}
285 assign = ('attr',)
286 update = ('dict_attr',)
287 functools.update_wrapper(wrapper, f, assign, update)
288 self.check_wrapper(wrapper, f, assign, update)
289 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600290 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000291 self.assertEqual(wrapper.__doc__, None)
292 self.assertEqual(wrapper.attr, 'This is a different test')
293 self.assertEqual(wrapper.dict_attr, f.dict_attr)
294
Nick Coghlan98876832010-08-17 06:17:18 +0000295 def test_missing_attributes(self):
296 def f():
297 pass
298 def wrapper():
299 pass
300 wrapper.dict_attr = {}
301 assign = ('attr',)
302 update = ('dict_attr',)
303 # Missing attributes on wrapped object are ignored
304 functools.update_wrapper(wrapper, f, assign, update)
305 self.assertNotIn('attr', wrapper.__dict__)
306 self.assertEqual(wrapper.dict_attr, {})
307 # Wrapper must have expected attributes for updating
308 del wrapper.dict_attr
309 with self.assertRaises(AttributeError):
310 functools.update_wrapper(wrapper, f, assign, update)
311 wrapper.dict_attr = 1
312 with self.assertRaises(AttributeError):
313 functools.update_wrapper(wrapper, f, assign, update)
314
315 @unittest.skipIf(sys.flags.optimize >= 2,
316 "Docstrings are omitted with -O2 and above")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000317 def test_builtin_update(self):
318 # Test for bug #1576241
319 def wrapper():
320 pass
321 functools.update_wrapper(wrapper, max)
322 self.assertEqual(wrapper.__name__, 'max')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000323 self.assertTrue(wrapper.__doc__.startswith('max('))
Antoine Pitrou560f7642010-08-04 18:28:02 +0000324 self.assertEqual(wrapper.__annotations__, {})
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000325
326class TestWraps(TestUpdateWrapper):
327
R. David Murray378c0cf2010-02-24 01:46:21 +0000328 def _default_update(self):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000329 def f():
330 """This is a test"""
331 pass
332 f.attr = 'This is also a test'
333 @functools.wraps(f)
334 def wrapper():
335 pass
336 self.check_wrapper(wrapper, f)
Meador Ingeff7f64c2011-12-11 22:37:31 -0600337 return wrapper, f
R. David Murray378c0cf2010-02-24 01:46:21 +0000338
339 def test_default_update(self):
Meador Ingeff7f64c2011-12-11 22:37:31 -0600340 wrapper, f = self._default_update()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000341 self.assertEqual(wrapper.__name__, 'f')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600342 self.assertEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000343 self.assertEqual(wrapper.attr, 'This is also a test')
344
Antoine Pitroub5b37142012-11-13 21:35:40 +0100345 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000346 "Docstrings are omitted with -O2 and above")
347 def test_default_update_doc(self):
Meador Ingeff7f64c2011-12-11 22:37:31 -0600348 wrapper, _ = self._default_update()
R. David Murray378c0cf2010-02-24 01:46:21 +0000349 self.assertEqual(wrapper.__doc__, 'This is a test')
350
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000351 def test_no_update(self):
352 def f():
353 """This is a test"""
354 pass
355 f.attr = 'This is also a test'
356 @functools.wraps(f, (), ())
357 def wrapper():
358 pass
359 self.check_wrapper(wrapper, f, (), ())
360 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600361 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000362 self.assertEqual(wrapper.__doc__, None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000363 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000364
365 def test_selective_update(self):
366 def f():
367 pass
368 f.attr = 'This is a different test'
369 f.dict_attr = dict(a=1, b=2, c=3)
370 def add_dict_attr(f):
371 f.dict_attr = {}
372 return f
373 assign = ('attr',)
374 update = ('dict_attr',)
375 @functools.wraps(f, assign, update)
376 @add_dict_attr
377 def wrapper():
378 pass
379 self.check_wrapper(wrapper, f, assign, update)
380 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600381 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000382 self.assertEqual(wrapper.__doc__, None)
383 self.assertEqual(wrapper.attr, 'This is a different test')
384 self.assertEqual(wrapper.dict_attr, f.dict_attr)
385
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000386class TestReduce(unittest.TestCase):
387 func = functools.reduce
388
389 def test_reduce(self):
390 class Squares:
391 def __init__(self, max):
392 self.max = max
393 self.sofar = []
394
395 def __len__(self):
396 return len(self.sofar)
397
398 def __getitem__(self, i):
399 if not 0 <= i < self.max: raise IndexError
400 n = len(self.sofar)
401 while n <= i:
402 self.sofar.append(n*n)
403 n += 1
404 return self.sofar[i]
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000405 def add(x, y):
406 return x + y
407 self.assertEqual(self.func(add, ['a', 'b', 'c'], ''), 'abc')
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000408 self.assertEqual(
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000409 self.func(add, [['a', 'c'], [], ['d', 'w']], []),
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000410 ['a','c','d','w']
411 )
412 self.assertEqual(self.func(lambda x, y: x*y, range(2,8), 1), 5040)
413 self.assertEqual(
Guido van Rossume2a383d2007-01-15 16:59:06 +0000414 self.func(lambda x, y: x*y, range(2,21), 1),
415 2432902008176640000
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000416 )
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000417 self.assertEqual(self.func(add, Squares(10)), 285)
418 self.assertEqual(self.func(add, Squares(10), 0), 285)
419 self.assertEqual(self.func(add, Squares(0), 0), 0)
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000420 self.assertRaises(TypeError, self.func)
421 self.assertRaises(TypeError, self.func, 42, 42)
422 self.assertRaises(TypeError, self.func, 42, 42, 42)
423 self.assertEqual(self.func(42, "1"), "1") # func is never called with one item
424 self.assertEqual(self.func(42, "", "1"), "1") # func is never called with one item
425 self.assertRaises(TypeError, self.func, 42, (42, 42))
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000426 self.assertRaises(TypeError, self.func, add, []) # arg 2 must not be empty sequence with no initial value
427 self.assertRaises(TypeError, self.func, add, "")
428 self.assertRaises(TypeError, self.func, add, ())
429 self.assertRaises(TypeError, self.func, add, object())
430
431 class TestFailingIter:
432 def __iter__(self):
433 raise RuntimeError
434 self.assertRaises(RuntimeError, self.func, add, TestFailingIter())
435
436 self.assertEqual(self.func(add, [], None), None)
437 self.assertEqual(self.func(add, [], 42), 42)
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000438
439 class BadSeq:
440 def __getitem__(self, index):
441 raise ValueError
442 self.assertRaises(ValueError, self.func, 42, BadSeq())
443
444 # Test reduce()'s use of iterators.
445 def test_iterator_usage(self):
446 class SequenceClass:
447 def __init__(self, n):
448 self.n = n
449 def __getitem__(self, i):
450 if 0 <= i < self.n:
451 return i
452 else:
453 raise IndexError
Guido van Rossumd8faa362007-04-27 19:54:29 +0000454
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000455 from operator import add
456 self.assertEqual(self.func(add, SequenceClass(5)), 10)
457 self.assertEqual(self.func(add, SequenceClass(5), 42), 52)
458 self.assertRaises(TypeError, self.func, add, SequenceClass(0))
459 self.assertEqual(self.func(add, SequenceClass(0), 42), 42)
460 self.assertEqual(self.func(add, SequenceClass(1)), 0)
461 self.assertEqual(self.func(add, SequenceClass(1), 42), 42)
462
463 d = {"one": 1, "two": 2, "three": 3}
464 self.assertEqual(self.func(add, d), "".join(d.keys()))
465
Antoine Pitroub5b37142012-11-13 21:35:40 +0100466class TestCmpToKey(object):
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700467
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000468 def test_cmp_to_key(self):
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700469 def cmp1(x, y):
470 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100471 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700472 self.assertEqual(key(3), key(3))
473 self.assertGreater(key(3), key(1))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100474 self.assertGreaterEqual(key(3), key(3))
475
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700476 def cmp2(x, y):
477 return int(x) - int(y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100478 key = self.cmp_to_key(cmp2)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700479 self.assertEqual(key(4.0), key('4'))
480 self.assertLess(key(2), key('35'))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100481 self.assertLessEqual(key(2), key('35'))
482 self.assertNotEqual(key(2), key('35'))
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700483
484 def test_cmp_to_key_arguments(self):
485 def cmp1(x, y):
486 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100487 key = self.cmp_to_key(mycmp=cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700488 self.assertEqual(key(obj=3), key(obj=3))
489 self.assertGreater(key(obj=3), key(obj=1))
490 with self.assertRaises((TypeError, AttributeError)):
491 key(3) > 1 # rhs is not a K object
492 with self.assertRaises((TypeError, AttributeError)):
493 1 < key(3) # lhs is not a K object
494 with self.assertRaises(TypeError):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100495 key = self.cmp_to_key() # too few args
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700496 with self.assertRaises(TypeError):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100497 key = self.module.cmp_to_key(cmp1, None) # too many args
498 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700499 with self.assertRaises(TypeError):
500 key() # too few args
501 with self.assertRaises(TypeError):
502 key(None, None) # too many args
503
504 def test_bad_cmp(self):
505 def cmp1(x, y):
506 raise ZeroDivisionError
Antoine Pitroub5b37142012-11-13 21:35:40 +0100507 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700508 with self.assertRaises(ZeroDivisionError):
509 key(3) > key(1)
510
511 class BadCmp:
512 def __lt__(self, other):
513 raise ZeroDivisionError
514 def cmp1(x, y):
515 return BadCmp()
516 with self.assertRaises(ZeroDivisionError):
517 key(3) > key(1)
518
519 def test_obj_field(self):
520 def cmp1(x, y):
521 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100522 key = self.cmp_to_key(mycmp=cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700523 self.assertEqual(key(50).obj, 50)
524
525 def test_sort_int(self):
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000526 def mycmp(x, y):
527 return y - x
Antoine Pitroub5b37142012-11-13 21:35:40 +0100528 self.assertEqual(sorted(range(5), key=self.cmp_to_key(mycmp)),
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000529 [4, 3, 2, 1, 0])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000530
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700531 def test_sort_int_str(self):
532 def mycmp(x, y):
533 x, y = int(x), int(y)
534 return (x > y) - (x < y)
535 values = [5, '3', 7, 2, '0', '1', 4, '10', 1]
Antoine Pitroub5b37142012-11-13 21:35:40 +0100536 values = sorted(values, key=self.cmp_to_key(mycmp))
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700537 self.assertEqual([int(value) for value in values],
538 [0, 1, 1, 2, 3, 4, 5, 7, 10])
539
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000540 def test_hash(self):
541 def mycmp(x, y):
542 return y - x
Antoine Pitroub5b37142012-11-13 21:35:40 +0100543 key = self.cmp_to_key(mycmp)
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000544 k = key(10)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700545 self.assertRaises(TypeError, hash, k)
Raymond Hettingere7a24302011-05-03 11:16:36 -0700546 self.assertNotIsInstance(k, collections.Hashable)
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000547
Antoine Pitroub5b37142012-11-13 21:35:40 +0100548class TestCmpToKeyC(BaseTestC, TestCmpToKey):
549 cmp_to_key = c_functools.cmp_to_key
550
551class TestCmpToKeyPy(BaseTestPy, TestCmpToKey):
552 cmp_to_key = staticmethod(py_functools.cmp_to_key)
553
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000554class TestTotalOrdering(unittest.TestCase):
555
556 def test_total_ordering_lt(self):
557 @functools.total_ordering
558 class A:
559 def __init__(self, value):
560 self.value = value
561 def __lt__(self, other):
562 return self.value < other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000563 def __eq__(self, other):
564 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000565 self.assertTrue(A(1) < A(2))
566 self.assertTrue(A(2) > A(1))
567 self.assertTrue(A(1) <= A(2))
568 self.assertTrue(A(2) >= A(1))
569 self.assertTrue(A(2) <= A(2))
570 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000571
572 def test_total_ordering_le(self):
573 @functools.total_ordering
574 class A:
575 def __init__(self, value):
576 self.value = value
577 def __le__(self, other):
578 return self.value <= other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000579 def __eq__(self, other):
580 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000581 self.assertTrue(A(1) < A(2))
582 self.assertTrue(A(2) > A(1))
583 self.assertTrue(A(1) <= A(2))
584 self.assertTrue(A(2) >= A(1))
585 self.assertTrue(A(2) <= A(2))
586 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000587
588 def test_total_ordering_gt(self):
589 @functools.total_ordering
590 class A:
591 def __init__(self, value):
592 self.value = value
593 def __gt__(self, other):
594 return self.value > other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000595 def __eq__(self, other):
596 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000597 self.assertTrue(A(1) < A(2))
598 self.assertTrue(A(2) > A(1))
599 self.assertTrue(A(1) <= A(2))
600 self.assertTrue(A(2) >= A(1))
601 self.assertTrue(A(2) <= A(2))
602 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000603
604 def test_total_ordering_ge(self):
605 @functools.total_ordering
606 class A:
607 def __init__(self, value):
608 self.value = value
609 def __ge__(self, other):
610 return self.value >= other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000611 def __eq__(self, other):
612 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000613 self.assertTrue(A(1) < A(2))
614 self.assertTrue(A(2) > A(1))
615 self.assertTrue(A(1) <= A(2))
616 self.assertTrue(A(2) >= A(1))
617 self.assertTrue(A(2) <= A(2))
618 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000619
620 def test_total_ordering_no_overwrite(self):
621 # new methods should not overwrite existing
622 @functools.total_ordering
623 class A(int):
Benjamin Peterson9c2930e2010-08-23 17:40:33 +0000624 pass
Ezio Melottib3aedd42010-11-20 19:04:17 +0000625 self.assertTrue(A(1) < A(2))
626 self.assertTrue(A(2) > A(1))
627 self.assertTrue(A(1) <= A(2))
628 self.assertTrue(A(2) >= A(1))
629 self.assertTrue(A(2) <= A(2))
630 self.assertTrue(A(2) >= A(2))
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000631
Benjamin Peterson42ebee32010-04-11 01:43:16 +0000632 def test_no_operations_defined(self):
633 with self.assertRaises(ValueError):
634 @functools.total_ordering
635 class A:
636 pass
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000637
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000638 def test_bug_10042(self):
639 @functools.total_ordering
640 class TestTO:
641 def __init__(self, value):
642 self.value = value
643 def __eq__(self, other):
644 if isinstance(other, TestTO):
645 return self.value == other.value
646 return False
647 def __lt__(self, other):
648 if isinstance(other, TestTO):
649 return self.value < other.value
650 raise TypeError
651 with self.assertRaises(TypeError):
652 TestTO(8) <= ()
653
Georg Brandl2e7346a2010-07-31 18:09:23 +0000654class TestLRU(unittest.TestCase):
655
656 def test_lru(self):
657 def orig(x, y):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100658 return 3 * x + y
Georg Brandl2e7346a2010-07-31 18:09:23 +0000659 f = functools.lru_cache(maxsize=20)(orig)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000660 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000661 self.assertEqual(maxsize, 20)
662 self.assertEqual(currsize, 0)
663 self.assertEqual(hits, 0)
664 self.assertEqual(misses, 0)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000665
666 domain = range(5)
667 for i in range(1000):
668 x, y = choice(domain), choice(domain)
669 actual = f(x, y)
670 expected = orig(x, y)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000671 self.assertEqual(actual, expected)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000672 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000673 self.assertTrue(hits > misses)
674 self.assertEqual(hits + misses, 1000)
675 self.assertEqual(currsize, 20)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000676
Raymond Hettinger02566ec2010-09-04 22:46:06 +0000677 f.cache_clear() # test clearing
Raymond Hettinger7496b412010-11-30 19:15:45 +0000678 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000679 self.assertEqual(hits, 0)
680 self.assertEqual(misses, 0)
681 self.assertEqual(currsize, 0)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000682 f(x, y)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000683 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000684 self.assertEqual(hits, 0)
685 self.assertEqual(misses, 1)
686 self.assertEqual(currsize, 1)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000687
Nick Coghlan98876832010-08-17 06:17:18 +0000688 # Test bypassing the cache
689 self.assertIs(f.__wrapped__, orig)
690 f.__wrapped__(x, y)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000691 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000692 self.assertEqual(hits, 0)
693 self.assertEqual(misses, 1)
694 self.assertEqual(currsize, 1)
Nick Coghlan98876832010-08-17 06:17:18 +0000695
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000696 # test size zero (which means "never-cache")
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000697 @functools.lru_cache(0)
698 def f():
699 nonlocal f_cnt
700 f_cnt += 1
701 return 20
Nick Coghlan234515a2010-11-30 06:19:46 +0000702 self.assertEqual(f.cache_info().maxsize, 0)
Raymond Hettingerf3098282010-08-15 03:30:45 +0000703 f_cnt = 0
704 for i in range(5):
705 self.assertEqual(f(), 20)
706 self.assertEqual(f_cnt, 5)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000707 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000708 self.assertEqual(hits, 0)
709 self.assertEqual(misses, 5)
710 self.assertEqual(currsize, 0)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000711
712 # test size one
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000713 @functools.lru_cache(1)
714 def f():
715 nonlocal f_cnt
716 f_cnt += 1
717 return 20
Nick Coghlan234515a2010-11-30 06:19:46 +0000718 self.assertEqual(f.cache_info().maxsize, 1)
Raymond Hettingerf3098282010-08-15 03:30:45 +0000719 f_cnt = 0
720 for i in range(5):
721 self.assertEqual(f(), 20)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000722 self.assertEqual(f_cnt, 1)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000723 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000724 self.assertEqual(hits, 4)
725 self.assertEqual(misses, 1)
726 self.assertEqual(currsize, 1)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000727
Raymond Hettingerf3098282010-08-15 03:30:45 +0000728 # test size two
729 @functools.lru_cache(2)
730 def f(x):
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000731 nonlocal f_cnt
732 f_cnt += 1
Raymond Hettingerf3098282010-08-15 03:30:45 +0000733 return x*10
Nick Coghlan234515a2010-11-30 06:19:46 +0000734 self.assertEqual(f.cache_info().maxsize, 2)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000735 f_cnt = 0
Raymond Hettingerf3098282010-08-15 03:30:45 +0000736 for x in 7, 9, 7, 9, 7, 9, 8, 8, 8, 9, 9, 9, 8, 8, 8, 7:
737 # * * * *
738 self.assertEqual(f(x), x*10)
739 self.assertEqual(f_cnt, 4)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000740 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000741 self.assertEqual(hits, 12)
742 self.assertEqual(misses, 4)
743 self.assertEqual(currsize, 2)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000744
Raymond Hettingerc79fb0e2010-12-01 03:45:41 +0000745 def test_lru_with_maxsize_none(self):
746 @functools.lru_cache(maxsize=None)
747 def fib(n):
748 if n < 2:
749 return n
750 return fib(n-1) + fib(n-2)
751 self.assertEqual([fib(n) for n in range(16)],
752 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
753 self.assertEqual(fib.cache_info(),
754 functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
755 fib.cache_clear()
756 self.assertEqual(fib.cache_info(),
757 functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
758
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700759 def test_lru_with_exceptions(self):
760 # Verify that user_function exceptions get passed through without
761 # creating a hard-to-read chained exception.
762 # http://bugs.python.org/issue13177
Antoine Pitroub5b37142012-11-13 21:35:40 +0100763 for maxsize in (None, 128):
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700764 @functools.lru_cache(maxsize)
765 def func(i):
766 return 'abc'[i]
767 self.assertEqual(func(0), 'a')
768 with self.assertRaises(IndexError) as cm:
769 func(15)
770 self.assertIsNone(cm.exception.__context__)
771 # Verify that the previous exception did not result in a cached entry
772 with self.assertRaises(IndexError):
773 func(15)
774
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700775 def test_lru_with_types(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100776 for maxsize in (None, 128):
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700777 @functools.lru_cache(maxsize=maxsize, typed=True)
778 def square(x):
779 return x * x
780 self.assertEqual(square(3), 9)
781 self.assertEqual(type(square(3)), type(9))
782 self.assertEqual(square(3.0), 9.0)
783 self.assertEqual(type(square(3.0)), type(9.0))
784 self.assertEqual(square(x=3), 9)
785 self.assertEqual(type(square(x=3)), type(9))
786 self.assertEqual(square(x=3.0), 9.0)
787 self.assertEqual(type(square(x=3.0)), type(9.0))
788 self.assertEqual(square.cache_info().hits, 4)
789 self.assertEqual(square.cache_info().misses, 4)
790
Antoine Pitroub5b37142012-11-13 21:35:40 +0100791 def test_lru_with_keyword_args(self):
792 @functools.lru_cache()
793 def fib(n):
794 if n < 2:
795 return n
796 return fib(n=n-1) + fib(n=n-2)
797 self.assertEqual(
798 [fib(n=number) for number in range(16)],
799 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
800 )
801 self.assertEqual(fib.cache_info(),
802 functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16))
803 fib.cache_clear()
804 self.assertEqual(fib.cache_info(),
805 functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0))
806
807 def test_lru_with_keyword_args_maxsize_none(self):
808 @functools.lru_cache(maxsize=None)
809 def fib(n):
810 if n < 2:
811 return n
812 return fib(n=n-1) + fib(n=n-2)
813 self.assertEqual([fib(n=number) for number in range(16)],
814 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
815 self.assertEqual(fib.cache_info(),
816 functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
817 fib.cache_clear()
818 self.assertEqual(fib.cache_info(),
819 functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
820
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000821def test_main(verbose=None):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000822 test_classes = (
Antoine Pitroub5b37142012-11-13 21:35:40 +0100823 TestPartialC,
824 TestPartialPy,
825 TestPartialCSubclass,
826 TestPartialPySubclass,
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000827 TestUpdateWrapper,
Benjamin Peterson9c2930e2010-08-23 17:40:33 +0000828 TestTotalOrdering,
Antoine Pitroub5b37142012-11-13 21:35:40 +0100829 TestCmpToKeyC,
830 TestCmpToKeyPy,
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000831 TestWraps,
Georg Brandl2e7346a2010-07-31 18:09:23 +0000832 TestReduce,
833 TestLRU,
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000834 )
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000835 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000836
837 # verify reference counting
838 if verbose and hasattr(sys, "gettotalrefcount"):
839 import gc
840 counts = [None] * 5
Guido van Rossum805365e2007-05-07 22:24:25 +0000841 for i in range(len(counts)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000842 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000843 gc.collect()
844 counts[i] = sys.gettotalrefcount()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000845 print(counts)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000846
847if __name__ == '__main__':
848 test_main(verbose=True)