blob: 9b3c31ef33950c35dae0a8f97be86c02efad08c5 [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
Antoine Pitroub5b37142012-11-13 21:35:40 +010011py_functools = support.import_fresh_module('functools', blocked=['_functools'])
12c_functools = support.import_fresh_module('functools', fresh=['_functools'])
13
Raymond Hettinger9c323f82005-02-28 19:39:44 +000014def capture(*args, **kw):
15 """capture all positional and keyword arguments"""
16 return args, kw
17
Jack Diederiche0cbd692009-04-01 04:27:09 +000018def signature(part):
19 """ return the signature of a partial object """
20 return (part.func, part.args, part.keywords, part.__dict__)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000021
Serhiy Storchakaca4220b2013-02-05 22:12:59 +020022class TestPartial:
Raymond Hettinger9c323f82005-02-28 19:39:44 +000023
24 def test_basic_examples(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010025 p = self.partial(capture, 1, 2, a=10, b=20)
26 self.assertTrue(callable(p))
Raymond Hettinger9c323f82005-02-28 19:39:44 +000027 self.assertEqual(p(3, 4, b=30, c=40),
28 ((1, 2, 3, 4), dict(a=10, b=30, c=40)))
Antoine Pitroub5b37142012-11-13 21:35:40 +010029 p = self.partial(map, lambda x: x*10)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000030 self.assertEqual(list(p([1,2,3,4])), [10, 20, 30, 40])
Raymond Hettinger9c323f82005-02-28 19:39:44 +000031
32 def test_attributes(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010033 p = self.partial(capture, 1, 2, a=10, b=20)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000034 # attributes should be readable
35 self.assertEqual(p.func, capture)
36 self.assertEqual(p.args, (1, 2))
37 self.assertEqual(p.keywords, dict(a=10, b=20))
38 # attributes should not be writable
Antoine Pitroub5b37142012-11-13 21:35:40 +010039 if not isinstance(self.partial, type):
Raymond Hettinger9c323f82005-02-28 19:39:44 +000040 return
Georg Brandl89fad142010-03-14 10:23:39 +000041 self.assertRaises(AttributeError, setattr, p, 'func', map)
42 self.assertRaises(AttributeError, setattr, p, 'args', (1, 2))
43 self.assertRaises(AttributeError, setattr, p, 'keywords', dict(a=1, b=2))
44
Antoine Pitroub5b37142012-11-13 21:35:40 +010045 p = self.partial(hex)
Georg Brandl89fad142010-03-14 10:23:39 +000046 try:
47 del p.__dict__
48 except TypeError:
49 pass
50 else:
51 self.fail('partial object allowed __dict__ to be deleted')
Raymond Hettinger9c323f82005-02-28 19:39:44 +000052
53 def test_argument_checking(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010054 self.assertRaises(TypeError, self.partial) # need at least a func arg
Raymond Hettinger9c323f82005-02-28 19:39:44 +000055 try:
Antoine Pitroub5b37142012-11-13 21:35:40 +010056 self.partial(2)()
Raymond Hettinger9c323f82005-02-28 19:39:44 +000057 except TypeError:
58 pass
59 else:
60 self.fail('First arg not checked for callability')
61
62 def test_protection_of_callers_dict_argument(self):
63 # a caller's dictionary should not be altered by partial
64 def func(a=10, b=20):
65 return a
66 d = {'a':3}
Antoine Pitroub5b37142012-11-13 21:35:40 +010067 p = self.partial(func, a=5)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000068 self.assertEqual(p(**d), 3)
69 self.assertEqual(d, {'a':3})
70 p(b=7)
71 self.assertEqual(d, {'a':3})
72
73 def test_arg_combinations(self):
74 # exercise special code paths for zero args in either partial
75 # object or the caller
Antoine Pitroub5b37142012-11-13 21:35:40 +010076 p = self.partial(capture)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000077 self.assertEqual(p(), ((), {}))
78 self.assertEqual(p(1,2), ((1,2), {}))
Antoine Pitroub5b37142012-11-13 21:35:40 +010079 p = self.partial(capture, 1, 2)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000080 self.assertEqual(p(), ((1,2), {}))
81 self.assertEqual(p(3,4), ((1,2,3,4), {}))
82
83 def test_kw_combinations(self):
84 # exercise special code paths for no keyword args in
85 # either the partial object or the caller
Antoine Pitroub5b37142012-11-13 21:35:40 +010086 p = self.partial(capture)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000087 self.assertEqual(p(), ((), {}))
88 self.assertEqual(p(a=1), ((), {'a':1}))
Antoine Pitroub5b37142012-11-13 21:35:40 +010089 p = self.partial(capture, a=1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000090 self.assertEqual(p(), ((), {'a':1}))
91 self.assertEqual(p(b=2), ((), {'a':1, 'b':2}))
92 # keyword args in the call override those in the partial object
93 self.assertEqual(p(a=3, b=2), ((), {'a':3, 'b':2}))
94
95 def test_positional(self):
96 # make sure positional arguments are captured correctly
97 for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]:
Antoine Pitroub5b37142012-11-13 21:35:40 +010098 p = self.partial(capture, *args)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000099 expected = args + ('x',)
100 got, empty = p('x')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000101 self.assertTrue(expected == got and empty == {})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000102
103 def test_keyword(self):
104 # make sure keyword arguments are captured correctly
105 for a in ['a', 0, None, 3.5]:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100106 p = self.partial(capture, a=a)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000107 expected = {'a':a,'x':None}
108 empty, got = p(x=None)
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_no_side_effects(self):
112 # make sure there are no side effects that affect subsequent calls
Antoine Pitroub5b37142012-11-13 21:35:40 +0100113 p = self.partial(capture, 0, a=1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000114 args1, kw1 = p(1, b=2)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000115 self.assertTrue(args1 == (0,1) and kw1 == {'a':1,'b':2})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000116 args2, kw2 = p()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000117 self.assertTrue(args2 == (0,) and kw2 == {'a':1})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000118
119 def test_error_propagation(self):
120 def f(x, y):
121 x / y
Antoine Pitroub5b37142012-11-13 21:35:40 +0100122 self.assertRaises(ZeroDivisionError, self.partial(f, 1, 0))
123 self.assertRaises(ZeroDivisionError, self.partial(f, 1), 0)
124 self.assertRaises(ZeroDivisionError, self.partial(f), 1, 0)
125 self.assertRaises(ZeroDivisionError, self.partial(f, y=0), 1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000126
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000127 def test_weakref(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100128 f = self.partial(int, base=16)
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000129 p = proxy(f)
130 self.assertEqual(f.func, p.func)
131 f = None
132 self.assertRaises(ReferenceError, getattr, p, 'func')
133
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000134 def test_with_bound_and_unbound_methods(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000135 data = list(map(str, range(10)))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100136 join = self.partial(str.join, '')
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000137 self.assertEqual(join(data), '0123456789')
Antoine Pitroub5b37142012-11-13 21:35:40 +0100138 join = self.partial(''.join)
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000139 self.assertEqual(join(data), '0123456789')
Tim Peterseba28be2005-03-28 01:08:02 +0000140
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200141@unittest.skipUnless(c_functools, 'requires the C _functools module')
142class TestPartialC(TestPartial, unittest.TestCase):
143 if c_functools:
144 partial = c_functools.partial
145
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000146 def test_repr(self):
147 args = (object(), object())
148 args_repr = ', '.join(repr(a) for a in args)
149 kwargs = {'a': object(), 'b': object()}
150 kwargs_repr = ', '.join("%s=%r" % (k, v) for k, v in kwargs.items())
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200151 if self.partial is c_functools.partial:
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000152 name = 'functools.partial'
153 else:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100154 name = self.partial.__name__
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000155
Antoine Pitroub5b37142012-11-13 21:35:40 +0100156 f = self.partial(capture)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000157 self.assertEqual('{}({!r})'.format(name, capture),
158 repr(f))
159
Antoine Pitroub5b37142012-11-13 21:35:40 +0100160 f = self.partial(capture, *args)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000161 self.assertEqual('{}({!r}, {})'.format(name, capture, args_repr),
162 repr(f))
163
Antoine Pitroub5b37142012-11-13 21:35:40 +0100164 f = self.partial(capture, **kwargs)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000165 self.assertEqual('{}({!r}, {})'.format(name, capture, kwargs_repr),
166 repr(f))
167
Antoine Pitroub5b37142012-11-13 21:35:40 +0100168 f = self.partial(capture, *args, **kwargs)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000169 self.assertEqual('{}({!r}, {}, {})'.format(name, capture, args_repr, kwargs_repr),
170 repr(f))
171
Jack Diederiche0cbd692009-04-01 04:27:09 +0000172 def test_pickle(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100173 f = self.partial(signature, 'asdf', bar=True)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000174 f.add_something_to__dict__ = True
175 f_copy = pickle.loads(pickle.dumps(f))
176 self.assertEqual(signature(f), signature(f_copy))
177
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200178 # Issue 6083: Reference counting bug
179 def test_setstate_refcount(self):
180 class BadSequence:
181 def __len__(self):
182 return 4
183 def __getitem__(self, key):
184 if key == 0:
185 return max
186 elif key == 1:
187 return tuple(range(1000000))
188 elif key in (2, 3):
189 return {}
190 raise IndexError
191
Serhiy Storchakab6a53402013-02-04 12:57:16 +0200192 f = self.partial(object)
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200193 self.assertRaisesRegex(SystemError,
194 "new style getargs format but argument is not a tuple",
195 f.__setstate__, BadSequence())
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000196
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200197class TestPartialPy(TestPartial, unittest.TestCase):
198 partial = staticmethod(py_functools.partial)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000199
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200200if c_functools:
201 class PartialSubclass(c_functools.partial):
202 pass
Antoine Pitrou33543272012-11-13 21:36:21 +0100203
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200204@unittest.skipUnless(c_functools, 'requires the C _functools module')
Serhiy Storchakab6a53402013-02-04 12:57:16 +0200205class TestPartialCSubclass(TestPartialC):
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200206 if c_functools:
207 partial = PartialSubclass
Jack Diederiche0cbd692009-04-01 04:27:09 +0000208
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000209class TestUpdateWrapper(unittest.TestCase):
210
211 def check_wrapper(self, wrapper, wrapped,
212 assigned=functools.WRAPPER_ASSIGNMENTS,
213 updated=functools.WRAPPER_UPDATES):
214 # Check attributes were assigned
215 for name in assigned:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000216 self.assertTrue(getattr(wrapper, name) is getattr(wrapped, name))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000217 # Check attributes were updated
218 for name in updated:
219 wrapper_attr = getattr(wrapper, name)
220 wrapped_attr = getattr(wrapped, name)
221 for key in wrapped_attr:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000222 self.assertTrue(wrapped_attr[key] is wrapper_attr[key])
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000223
R. David Murray378c0cf2010-02-24 01:46:21 +0000224 def _default_update(self):
Antoine Pitrou560f7642010-08-04 18:28:02 +0000225 def f(a:'This is a new annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000226 """This is a test"""
227 pass
228 f.attr = 'This is also a test'
Antoine Pitrou560f7642010-08-04 18:28:02 +0000229 def wrapper(b:'This is the prior annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000230 pass
231 functools.update_wrapper(wrapper, f)
R. David Murray378c0cf2010-02-24 01:46:21 +0000232 return wrapper, f
233
234 def test_default_update(self):
235 wrapper, f = self._default_update()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000236 self.check_wrapper(wrapper, f)
Nick Coghlan98876832010-08-17 06:17:18 +0000237 self.assertIs(wrapper.__wrapped__, f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000238 self.assertEqual(wrapper.__name__, 'f')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600239 self.assertEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000240 self.assertEqual(wrapper.attr, 'This is also a test')
Antoine Pitrou560f7642010-08-04 18:28:02 +0000241 self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation')
242 self.assertNotIn('b', wrapper.__annotations__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000243
R. David Murray378c0cf2010-02-24 01:46:21 +0000244 @unittest.skipIf(sys.flags.optimize >= 2,
245 "Docstrings are omitted with -O2 and above")
246 def test_default_update_doc(self):
247 wrapper, f = self._default_update()
248 self.assertEqual(wrapper.__doc__, 'This is a test')
249
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000250 def test_no_update(self):
251 def f():
252 """This is a test"""
253 pass
254 f.attr = 'This is also a test'
255 def wrapper():
256 pass
257 functools.update_wrapper(wrapper, f, (), ())
258 self.check_wrapper(wrapper, f, (), ())
259 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600260 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000261 self.assertEqual(wrapper.__doc__, None)
Antoine Pitrou560f7642010-08-04 18:28:02 +0000262 self.assertEqual(wrapper.__annotations__, {})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000263 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000264
265 def test_selective_update(self):
266 def f():
267 pass
268 f.attr = 'This is a different test'
269 f.dict_attr = dict(a=1, b=2, c=3)
270 def wrapper():
271 pass
272 wrapper.dict_attr = {}
273 assign = ('attr',)
274 update = ('dict_attr',)
275 functools.update_wrapper(wrapper, f, assign, update)
276 self.check_wrapper(wrapper, f, assign, update)
277 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600278 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000279 self.assertEqual(wrapper.__doc__, None)
280 self.assertEqual(wrapper.attr, 'This is a different test')
281 self.assertEqual(wrapper.dict_attr, f.dict_attr)
282
Nick Coghlan98876832010-08-17 06:17:18 +0000283 def test_missing_attributes(self):
284 def f():
285 pass
286 def wrapper():
287 pass
288 wrapper.dict_attr = {}
289 assign = ('attr',)
290 update = ('dict_attr',)
291 # Missing attributes on wrapped object are ignored
292 functools.update_wrapper(wrapper, f, assign, update)
293 self.assertNotIn('attr', wrapper.__dict__)
294 self.assertEqual(wrapper.dict_attr, {})
295 # Wrapper must have expected attributes for updating
296 del wrapper.dict_attr
297 with self.assertRaises(AttributeError):
298 functools.update_wrapper(wrapper, f, assign, update)
299 wrapper.dict_attr = 1
300 with self.assertRaises(AttributeError):
301 functools.update_wrapper(wrapper, f, assign, update)
302
Serhiy Storchaka9d0add02013-01-27 19:47:45 +0200303 @support.requires_docstrings
Nick Coghlan98876832010-08-17 06:17:18 +0000304 @unittest.skipIf(sys.flags.optimize >= 2,
305 "Docstrings are omitted with -O2 and above")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000306 def test_builtin_update(self):
307 # Test for bug #1576241
308 def wrapper():
309 pass
310 functools.update_wrapper(wrapper, max)
311 self.assertEqual(wrapper.__name__, 'max')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000312 self.assertTrue(wrapper.__doc__.startswith('max('))
Antoine Pitrou560f7642010-08-04 18:28:02 +0000313 self.assertEqual(wrapper.__annotations__, {})
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000314
315class TestWraps(TestUpdateWrapper):
316
R. David Murray378c0cf2010-02-24 01:46:21 +0000317 def _default_update(self):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000318 def f():
319 """This is a test"""
320 pass
321 f.attr = 'This is also a test'
322 @functools.wraps(f)
323 def wrapper():
324 pass
325 self.check_wrapper(wrapper, f)
Meador Ingeff7f64c2011-12-11 22:37:31 -0600326 return wrapper, f
R. David Murray378c0cf2010-02-24 01:46:21 +0000327
328 def test_default_update(self):
Meador Ingeff7f64c2011-12-11 22:37:31 -0600329 wrapper, f = self._default_update()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000330 self.assertEqual(wrapper.__name__, 'f')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600331 self.assertEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000332 self.assertEqual(wrapper.attr, 'This is also a test')
333
Antoine Pitroub5b37142012-11-13 21:35:40 +0100334 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000335 "Docstrings are omitted with -O2 and above")
336 def test_default_update_doc(self):
Meador Ingeff7f64c2011-12-11 22:37:31 -0600337 wrapper, _ = self._default_update()
R. David Murray378c0cf2010-02-24 01:46:21 +0000338 self.assertEqual(wrapper.__doc__, 'This is a test')
339
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000340 def test_no_update(self):
341 def f():
342 """This is a test"""
343 pass
344 f.attr = 'This is also a test'
345 @functools.wraps(f, (), ())
346 def wrapper():
347 pass
348 self.check_wrapper(wrapper, f, (), ())
349 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600350 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000351 self.assertEqual(wrapper.__doc__, None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000352 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000353
354 def test_selective_update(self):
355 def f():
356 pass
357 f.attr = 'This is a different test'
358 f.dict_attr = dict(a=1, b=2, c=3)
359 def add_dict_attr(f):
360 f.dict_attr = {}
361 return f
362 assign = ('attr',)
363 update = ('dict_attr',)
364 @functools.wraps(f, assign, update)
365 @add_dict_attr
366 def wrapper():
367 pass
368 self.check_wrapper(wrapper, f, assign, update)
369 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600370 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000371 self.assertEqual(wrapper.__doc__, None)
372 self.assertEqual(wrapper.attr, 'This is a different test')
373 self.assertEqual(wrapper.dict_attr, f.dict_attr)
374
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000375class TestReduce(unittest.TestCase):
376 func = functools.reduce
377
378 def test_reduce(self):
379 class Squares:
380 def __init__(self, max):
381 self.max = max
382 self.sofar = []
383
384 def __len__(self):
385 return len(self.sofar)
386
387 def __getitem__(self, i):
388 if not 0 <= i < self.max: raise IndexError
389 n = len(self.sofar)
390 while n <= i:
391 self.sofar.append(n*n)
392 n += 1
393 return self.sofar[i]
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000394 def add(x, y):
395 return x + y
396 self.assertEqual(self.func(add, ['a', 'b', 'c'], ''), 'abc')
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000397 self.assertEqual(
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000398 self.func(add, [['a', 'c'], [], ['d', 'w']], []),
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000399 ['a','c','d','w']
400 )
401 self.assertEqual(self.func(lambda x, y: x*y, range(2,8), 1), 5040)
402 self.assertEqual(
Guido van Rossume2a383d2007-01-15 16:59:06 +0000403 self.func(lambda x, y: x*y, range(2,21), 1),
404 2432902008176640000
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000405 )
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000406 self.assertEqual(self.func(add, Squares(10)), 285)
407 self.assertEqual(self.func(add, Squares(10), 0), 285)
408 self.assertEqual(self.func(add, Squares(0), 0), 0)
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000409 self.assertRaises(TypeError, self.func)
410 self.assertRaises(TypeError, self.func, 42, 42)
411 self.assertRaises(TypeError, self.func, 42, 42, 42)
412 self.assertEqual(self.func(42, "1"), "1") # func is never called with one item
413 self.assertEqual(self.func(42, "", "1"), "1") # func is never called with one item
414 self.assertRaises(TypeError, self.func, 42, (42, 42))
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000415 self.assertRaises(TypeError, self.func, add, []) # arg 2 must not be empty sequence with no initial value
416 self.assertRaises(TypeError, self.func, add, "")
417 self.assertRaises(TypeError, self.func, add, ())
418 self.assertRaises(TypeError, self.func, add, object())
419
420 class TestFailingIter:
421 def __iter__(self):
422 raise RuntimeError
423 self.assertRaises(RuntimeError, self.func, add, TestFailingIter())
424
425 self.assertEqual(self.func(add, [], None), None)
426 self.assertEqual(self.func(add, [], 42), 42)
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000427
428 class BadSeq:
429 def __getitem__(self, index):
430 raise ValueError
431 self.assertRaises(ValueError, self.func, 42, BadSeq())
432
433 # Test reduce()'s use of iterators.
434 def test_iterator_usage(self):
435 class SequenceClass:
436 def __init__(self, n):
437 self.n = n
438 def __getitem__(self, i):
439 if 0 <= i < self.n:
440 return i
441 else:
442 raise IndexError
Guido van Rossumd8faa362007-04-27 19:54:29 +0000443
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000444 from operator import add
445 self.assertEqual(self.func(add, SequenceClass(5)), 10)
446 self.assertEqual(self.func(add, SequenceClass(5), 42), 52)
447 self.assertRaises(TypeError, self.func, add, SequenceClass(0))
448 self.assertEqual(self.func(add, SequenceClass(0), 42), 42)
449 self.assertEqual(self.func(add, SequenceClass(1)), 0)
450 self.assertEqual(self.func(add, SequenceClass(1), 42), 42)
451
452 d = {"one": 1, "two": 2, "three": 3}
453 self.assertEqual(self.func(add, d), "".join(d.keys()))
454
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200455class TestCmpToKey:
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700456
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000457 def test_cmp_to_key(self):
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700458 def cmp1(x, y):
459 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100460 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700461 self.assertEqual(key(3), key(3))
462 self.assertGreater(key(3), key(1))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100463 self.assertGreaterEqual(key(3), key(3))
464
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700465 def cmp2(x, y):
466 return int(x) - int(y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100467 key = self.cmp_to_key(cmp2)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700468 self.assertEqual(key(4.0), key('4'))
469 self.assertLess(key(2), key('35'))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100470 self.assertLessEqual(key(2), key('35'))
471 self.assertNotEqual(key(2), key('35'))
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700472
473 def test_cmp_to_key_arguments(self):
474 def cmp1(x, y):
475 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100476 key = self.cmp_to_key(mycmp=cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700477 self.assertEqual(key(obj=3), key(obj=3))
478 self.assertGreater(key(obj=3), key(obj=1))
479 with self.assertRaises((TypeError, AttributeError)):
480 key(3) > 1 # rhs is not a K object
481 with self.assertRaises((TypeError, AttributeError)):
482 1 < key(3) # lhs is not a K object
483 with self.assertRaises(TypeError):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100484 key = self.cmp_to_key() # too few args
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700485 with self.assertRaises(TypeError):
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200486 key = self.cmp_to_key(cmp1, None) # too many args
Antoine Pitroub5b37142012-11-13 21:35:40 +0100487 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700488 with self.assertRaises(TypeError):
489 key() # too few args
490 with self.assertRaises(TypeError):
491 key(None, None) # too many args
492
493 def test_bad_cmp(self):
494 def cmp1(x, y):
495 raise ZeroDivisionError
Antoine Pitroub5b37142012-11-13 21:35:40 +0100496 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700497 with self.assertRaises(ZeroDivisionError):
498 key(3) > key(1)
499
500 class BadCmp:
501 def __lt__(self, other):
502 raise ZeroDivisionError
503 def cmp1(x, y):
504 return BadCmp()
505 with self.assertRaises(ZeroDivisionError):
506 key(3) > key(1)
507
508 def test_obj_field(self):
509 def cmp1(x, y):
510 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100511 key = self.cmp_to_key(mycmp=cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700512 self.assertEqual(key(50).obj, 50)
513
514 def test_sort_int(self):
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000515 def mycmp(x, y):
516 return y - x
Antoine Pitroub5b37142012-11-13 21:35:40 +0100517 self.assertEqual(sorted(range(5), key=self.cmp_to_key(mycmp)),
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000518 [4, 3, 2, 1, 0])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000519
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700520 def test_sort_int_str(self):
521 def mycmp(x, y):
522 x, y = int(x), int(y)
523 return (x > y) - (x < y)
524 values = [5, '3', 7, 2, '0', '1', 4, '10', 1]
Antoine Pitroub5b37142012-11-13 21:35:40 +0100525 values = sorted(values, key=self.cmp_to_key(mycmp))
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700526 self.assertEqual([int(value) for value in values],
527 [0, 1, 1, 2, 3, 4, 5, 7, 10])
528
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000529 def test_hash(self):
530 def mycmp(x, y):
531 return y - x
Antoine Pitroub5b37142012-11-13 21:35:40 +0100532 key = self.cmp_to_key(mycmp)
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000533 k = key(10)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700534 self.assertRaises(TypeError, hash, k)
Raymond Hettingere7a24302011-05-03 11:16:36 -0700535 self.assertNotIsInstance(k, collections.Hashable)
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000536
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200537@unittest.skipUnless(c_functools, 'requires the C _functools module')
538class TestCmpToKeyC(TestCmpToKey, unittest.TestCase):
539 if c_functools:
540 cmp_to_key = c_functools.cmp_to_key
Antoine Pitroub5b37142012-11-13 21:35:40 +0100541
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200542class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100543 cmp_to_key = staticmethod(py_functools.cmp_to_key)
544
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000545class TestTotalOrdering(unittest.TestCase):
546
547 def test_total_ordering_lt(self):
548 @functools.total_ordering
549 class A:
550 def __init__(self, value):
551 self.value = value
552 def __lt__(self, other):
553 return self.value < other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000554 def __eq__(self, other):
555 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000556 self.assertTrue(A(1) < A(2))
557 self.assertTrue(A(2) > A(1))
558 self.assertTrue(A(1) <= A(2))
559 self.assertTrue(A(2) >= A(1))
560 self.assertTrue(A(2) <= A(2))
561 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000562
563 def test_total_ordering_le(self):
564 @functools.total_ordering
565 class A:
566 def __init__(self, value):
567 self.value = value
568 def __le__(self, other):
569 return self.value <= other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000570 def __eq__(self, other):
571 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000572 self.assertTrue(A(1) < A(2))
573 self.assertTrue(A(2) > A(1))
574 self.assertTrue(A(1) <= A(2))
575 self.assertTrue(A(2) >= A(1))
576 self.assertTrue(A(2) <= A(2))
577 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000578
579 def test_total_ordering_gt(self):
580 @functools.total_ordering
581 class A:
582 def __init__(self, value):
583 self.value = value
584 def __gt__(self, other):
585 return self.value > other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000586 def __eq__(self, other):
587 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000588 self.assertTrue(A(1) < A(2))
589 self.assertTrue(A(2) > A(1))
590 self.assertTrue(A(1) <= A(2))
591 self.assertTrue(A(2) >= A(1))
592 self.assertTrue(A(2) <= A(2))
593 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000594
595 def test_total_ordering_ge(self):
596 @functools.total_ordering
597 class A:
598 def __init__(self, value):
599 self.value = value
600 def __ge__(self, other):
601 return self.value >= other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000602 def __eq__(self, other):
603 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000604 self.assertTrue(A(1) < A(2))
605 self.assertTrue(A(2) > A(1))
606 self.assertTrue(A(1) <= A(2))
607 self.assertTrue(A(2) >= A(1))
608 self.assertTrue(A(2) <= A(2))
609 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000610
611 def test_total_ordering_no_overwrite(self):
612 # new methods should not overwrite existing
613 @functools.total_ordering
614 class A(int):
Benjamin Peterson9c2930e2010-08-23 17:40:33 +0000615 pass
Ezio Melottib3aedd42010-11-20 19:04:17 +0000616 self.assertTrue(A(1) < A(2))
617 self.assertTrue(A(2) > A(1))
618 self.assertTrue(A(1) <= A(2))
619 self.assertTrue(A(2) >= A(1))
620 self.assertTrue(A(2) <= A(2))
621 self.assertTrue(A(2) >= A(2))
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000622
Benjamin Peterson42ebee32010-04-11 01:43:16 +0000623 def test_no_operations_defined(self):
624 with self.assertRaises(ValueError):
625 @functools.total_ordering
626 class A:
627 pass
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000628
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000629 def test_bug_10042(self):
630 @functools.total_ordering
631 class TestTO:
632 def __init__(self, value):
633 self.value = value
634 def __eq__(self, other):
635 if isinstance(other, TestTO):
636 return self.value == other.value
637 return False
638 def __lt__(self, other):
639 if isinstance(other, TestTO):
640 return self.value < other.value
641 raise TypeError
642 with self.assertRaises(TypeError):
643 TestTO(8) <= ()
644
Georg Brandl2e7346a2010-07-31 18:09:23 +0000645class TestLRU(unittest.TestCase):
646
647 def test_lru(self):
648 def orig(x, y):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100649 return 3 * x + y
Georg Brandl2e7346a2010-07-31 18:09:23 +0000650 f = functools.lru_cache(maxsize=20)(orig)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000651 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000652 self.assertEqual(maxsize, 20)
653 self.assertEqual(currsize, 0)
654 self.assertEqual(hits, 0)
655 self.assertEqual(misses, 0)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000656
657 domain = range(5)
658 for i in range(1000):
659 x, y = choice(domain), choice(domain)
660 actual = f(x, y)
661 expected = orig(x, y)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000662 self.assertEqual(actual, expected)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000663 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000664 self.assertTrue(hits > misses)
665 self.assertEqual(hits + misses, 1000)
666 self.assertEqual(currsize, 20)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000667
Raymond Hettinger02566ec2010-09-04 22:46:06 +0000668 f.cache_clear() # test clearing
Raymond Hettinger7496b412010-11-30 19:15:45 +0000669 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000670 self.assertEqual(hits, 0)
671 self.assertEqual(misses, 0)
672 self.assertEqual(currsize, 0)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000673 f(x, y)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000674 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000675 self.assertEqual(hits, 0)
676 self.assertEqual(misses, 1)
677 self.assertEqual(currsize, 1)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000678
Nick Coghlan98876832010-08-17 06:17:18 +0000679 # Test bypassing the cache
680 self.assertIs(f.__wrapped__, orig)
681 f.__wrapped__(x, y)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000682 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000683 self.assertEqual(hits, 0)
684 self.assertEqual(misses, 1)
685 self.assertEqual(currsize, 1)
Nick Coghlan98876832010-08-17 06:17:18 +0000686
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000687 # test size zero (which means "never-cache")
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000688 @functools.lru_cache(0)
689 def f():
690 nonlocal f_cnt
691 f_cnt += 1
692 return 20
Nick Coghlan234515a2010-11-30 06:19:46 +0000693 self.assertEqual(f.cache_info().maxsize, 0)
Raymond Hettingerf3098282010-08-15 03:30:45 +0000694 f_cnt = 0
695 for i in range(5):
696 self.assertEqual(f(), 20)
697 self.assertEqual(f_cnt, 5)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000698 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000699 self.assertEqual(hits, 0)
700 self.assertEqual(misses, 5)
701 self.assertEqual(currsize, 0)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000702
703 # test size one
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000704 @functools.lru_cache(1)
705 def f():
706 nonlocal f_cnt
707 f_cnt += 1
708 return 20
Nick Coghlan234515a2010-11-30 06:19:46 +0000709 self.assertEqual(f.cache_info().maxsize, 1)
Raymond Hettingerf3098282010-08-15 03:30:45 +0000710 f_cnt = 0
711 for i in range(5):
712 self.assertEqual(f(), 20)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000713 self.assertEqual(f_cnt, 1)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000714 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000715 self.assertEqual(hits, 4)
716 self.assertEqual(misses, 1)
717 self.assertEqual(currsize, 1)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000718
Raymond Hettingerf3098282010-08-15 03:30:45 +0000719 # test size two
720 @functools.lru_cache(2)
721 def f(x):
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000722 nonlocal f_cnt
723 f_cnt += 1
Raymond Hettingerf3098282010-08-15 03:30:45 +0000724 return x*10
Nick Coghlan234515a2010-11-30 06:19:46 +0000725 self.assertEqual(f.cache_info().maxsize, 2)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000726 f_cnt = 0
Raymond Hettingerf3098282010-08-15 03:30:45 +0000727 for x in 7, 9, 7, 9, 7, 9, 8, 8, 8, 9, 9, 9, 8, 8, 8, 7:
728 # * * * *
729 self.assertEqual(f(x), x*10)
730 self.assertEqual(f_cnt, 4)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000731 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000732 self.assertEqual(hits, 12)
733 self.assertEqual(misses, 4)
734 self.assertEqual(currsize, 2)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000735
Raymond Hettingerc79fb0e2010-12-01 03:45:41 +0000736 def test_lru_with_maxsize_none(self):
737 @functools.lru_cache(maxsize=None)
738 def fib(n):
739 if n < 2:
740 return n
741 return fib(n-1) + fib(n-2)
742 self.assertEqual([fib(n) for n in range(16)],
743 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
744 self.assertEqual(fib.cache_info(),
745 functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
746 fib.cache_clear()
747 self.assertEqual(fib.cache_info(),
748 functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
749
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700750 def test_lru_with_exceptions(self):
751 # Verify that user_function exceptions get passed through without
752 # creating a hard-to-read chained exception.
753 # http://bugs.python.org/issue13177
Antoine Pitroub5b37142012-11-13 21:35:40 +0100754 for maxsize in (None, 128):
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700755 @functools.lru_cache(maxsize)
756 def func(i):
757 return 'abc'[i]
758 self.assertEqual(func(0), 'a')
759 with self.assertRaises(IndexError) as cm:
760 func(15)
761 self.assertIsNone(cm.exception.__context__)
762 # Verify that the previous exception did not result in a cached entry
763 with self.assertRaises(IndexError):
764 func(15)
765
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700766 def test_lru_with_types(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100767 for maxsize in (None, 128):
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700768 @functools.lru_cache(maxsize=maxsize, typed=True)
769 def square(x):
770 return x * x
771 self.assertEqual(square(3), 9)
772 self.assertEqual(type(square(3)), type(9))
773 self.assertEqual(square(3.0), 9.0)
774 self.assertEqual(type(square(3.0)), type(9.0))
775 self.assertEqual(square(x=3), 9)
776 self.assertEqual(type(square(x=3)), type(9))
777 self.assertEqual(square(x=3.0), 9.0)
778 self.assertEqual(type(square(x=3.0)), type(9.0))
779 self.assertEqual(square.cache_info().hits, 4)
780 self.assertEqual(square.cache_info().misses, 4)
781
Antoine Pitroub5b37142012-11-13 21:35:40 +0100782 def test_lru_with_keyword_args(self):
783 @functools.lru_cache()
784 def fib(n):
785 if n < 2:
786 return n
787 return fib(n=n-1) + fib(n=n-2)
788 self.assertEqual(
789 [fib(n=number) for number in range(16)],
790 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
791 )
792 self.assertEqual(fib.cache_info(),
793 functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16))
794 fib.cache_clear()
795 self.assertEqual(fib.cache_info(),
796 functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0))
797
798 def test_lru_with_keyword_args_maxsize_none(self):
799 @functools.lru_cache(maxsize=None)
800 def fib(n):
801 if n < 2:
802 return n
803 return fib(n=n-1) + fib(n=n-2)
804 self.assertEqual([fib(n=number) for number in range(16)],
805 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
806 self.assertEqual(fib.cache_info(),
807 functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
808 fib.cache_clear()
809 self.assertEqual(fib.cache_info(),
810 functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
811
Raymond Hettinger03923422013-03-04 02:52:50 -0500812 def test_need_for_rlock(self):
813 # This will deadlock on an LRU cache that uses a regular lock
814
815 @functools.lru_cache(maxsize=10)
816 def test_func(x):
817 'Used to demonstrate a reentrant lru_cache call within a single thread'
818 return x
819
820 class DoubleEq:
821 'Demonstrate a reentrant lru_cache call within a single thread'
822 def __init__(self, x):
823 self.x = x
824 def __hash__(self):
825 return self.x
826 def __eq__(self, other):
827 if self.x == 2:
828 test_func(DoubleEq(1))
829 return self.x == other.x
830
831 test_func(DoubleEq(1)) # Load the cache
832 test_func(DoubleEq(2)) # Load the cache
833 self.assertEqual(test_func(DoubleEq(2)), # Trigger a re-entrant __eq__ call
834 DoubleEq(2)) # Verify the correct return value
835
836
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000837def test_main(verbose=None):
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000838 test_classes = (
Antoine Pitroub5b37142012-11-13 21:35:40 +0100839 TestPartialC,
840 TestPartialPy,
841 TestPartialCSubclass,
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000842 TestUpdateWrapper,
Benjamin Peterson9c2930e2010-08-23 17:40:33 +0000843 TestTotalOrdering,
Antoine Pitroub5b37142012-11-13 21:35:40 +0100844 TestCmpToKeyC,
845 TestCmpToKeyPy,
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000846 TestWraps,
Georg Brandl2e7346a2010-07-31 18:09:23 +0000847 TestReduce,
848 TestLRU,
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000849 )
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000850 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000851
852 # verify reference counting
853 if verbose and hasattr(sys, "gettotalrefcount"):
854 import gc
855 counts = [None] * 5
Guido van Rossum805365e2007-05-07 22:24:25 +0000856 for i in range(len(counts)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000857 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000858 gc.collect()
859 counts[i] = sys.gettotalrefcount()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000860 print(counts)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000861
862if __name__ == '__main__':
863 test_main(verbose=True)