blob: ab76efbfefae2aa1cc41884b30afee1185db46e7 [file] [log] [blame]
Raymond Hettinger003be522011-05-03 11:01:32 -07001import collections
Łukasz Langa6f692512013-06-05 12:20:24 +02002from itertools import permutations
Jack Diederiche0cbd692009-04-01 04:27:09 +00003import pickle
Georg Brandl2e7346a2010-07-31 18:09:23 +00004from random import choice
Łukasz Langa6f692512013-06-05 12:20:24 +02005import sys
6from test import support
7import unittest
8from weakref import proxy
Raymond Hettinger9c323f82005-02-28 19:39:44 +00009
Antoine Pitroub5b37142012-11-13 21:35:40 +010010import functools
11
Antoine Pitroub5b37142012-11-13 21:35:40 +010012py_functools = support.import_fresh_module('functools', blocked=['_functools'])
13c_functools = support.import_fresh_module('functools', fresh=['_functools'])
14
Łukasz Langa6f692512013-06-05 12:20:24 +020015decimal = support.import_fresh_module('decimal', fresh=['_decimal'])
16
17
Raymond Hettinger9c323f82005-02-28 19:39:44 +000018def capture(*args, **kw):
19 """capture all positional and keyword arguments"""
20 return args, kw
21
Łukasz Langa6f692512013-06-05 12:20:24 +020022
Jack Diederiche0cbd692009-04-01 04:27:09 +000023def signature(part):
24 """ return the signature of a partial object """
25 return (part.func, part.args, part.keywords, part.__dict__)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000026
Łukasz Langa6f692512013-06-05 12:20:24 +020027
Serhiy Storchakaca4220b2013-02-05 22:12:59 +020028class TestPartial:
Raymond Hettinger9c323f82005-02-28 19:39:44 +000029
30 def test_basic_examples(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010031 p = self.partial(capture, 1, 2, a=10, b=20)
32 self.assertTrue(callable(p))
Raymond Hettinger9c323f82005-02-28 19:39:44 +000033 self.assertEqual(p(3, 4, b=30, c=40),
34 ((1, 2, 3, 4), dict(a=10, b=30, c=40)))
Antoine Pitroub5b37142012-11-13 21:35:40 +010035 p = self.partial(map, lambda x: x*10)
Guido van Rossumc1f779c2007-07-03 08:25:58 +000036 self.assertEqual(list(p([1,2,3,4])), [10, 20, 30, 40])
Raymond Hettinger9c323f82005-02-28 19:39:44 +000037
38 def test_attributes(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010039 p = self.partial(capture, 1, 2, a=10, b=20)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000040 # attributes should be readable
41 self.assertEqual(p.func, capture)
42 self.assertEqual(p.args, (1, 2))
43 self.assertEqual(p.keywords, dict(a=10, b=20))
44 # attributes should not be writable
Antoine Pitroub5b37142012-11-13 21:35:40 +010045 if not isinstance(self.partial, type):
Raymond Hettinger9c323f82005-02-28 19:39:44 +000046 return
Georg Brandl89fad142010-03-14 10:23:39 +000047 self.assertRaises(AttributeError, setattr, p, 'func', map)
48 self.assertRaises(AttributeError, setattr, p, 'args', (1, 2))
49 self.assertRaises(AttributeError, setattr, p, 'keywords', dict(a=1, b=2))
50
Antoine Pitroub5b37142012-11-13 21:35:40 +010051 p = self.partial(hex)
Georg Brandl89fad142010-03-14 10:23:39 +000052 try:
53 del p.__dict__
54 except TypeError:
55 pass
56 else:
57 self.fail('partial object allowed __dict__ to be deleted')
Raymond Hettinger9c323f82005-02-28 19:39:44 +000058
59 def test_argument_checking(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +010060 self.assertRaises(TypeError, self.partial) # need at least a func arg
Raymond Hettinger9c323f82005-02-28 19:39:44 +000061 try:
Antoine Pitroub5b37142012-11-13 21:35:40 +010062 self.partial(2)()
Raymond Hettinger9c323f82005-02-28 19:39:44 +000063 except TypeError:
64 pass
65 else:
66 self.fail('First arg not checked for callability')
67
68 def test_protection_of_callers_dict_argument(self):
69 # a caller's dictionary should not be altered by partial
70 def func(a=10, b=20):
71 return a
72 d = {'a':3}
Antoine Pitroub5b37142012-11-13 21:35:40 +010073 p = self.partial(func, a=5)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000074 self.assertEqual(p(**d), 3)
75 self.assertEqual(d, {'a':3})
76 p(b=7)
77 self.assertEqual(d, {'a':3})
78
79 def test_arg_combinations(self):
80 # exercise special code paths for zero args in either partial
81 # object or the caller
Antoine Pitroub5b37142012-11-13 21:35:40 +010082 p = self.partial(capture)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000083 self.assertEqual(p(), ((), {}))
84 self.assertEqual(p(1,2), ((1,2), {}))
Antoine Pitroub5b37142012-11-13 21:35:40 +010085 p = self.partial(capture, 1, 2)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000086 self.assertEqual(p(), ((1,2), {}))
87 self.assertEqual(p(3,4), ((1,2,3,4), {}))
88
89 def test_kw_combinations(self):
90 # exercise special code paths for no keyword args in
91 # either the partial object or the caller
Antoine Pitroub5b37142012-11-13 21:35:40 +010092 p = self.partial(capture)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000093 self.assertEqual(p(), ((), {}))
94 self.assertEqual(p(a=1), ((), {'a':1}))
Antoine Pitroub5b37142012-11-13 21:35:40 +010095 p = self.partial(capture, a=1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +000096 self.assertEqual(p(), ((), {'a':1}))
97 self.assertEqual(p(b=2), ((), {'a':1, 'b':2}))
98 # keyword args in the call override those in the partial object
99 self.assertEqual(p(a=3, b=2), ((), {'a':3, 'b':2}))
100
101 def test_positional(self):
102 # make sure positional arguments are captured correctly
103 for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100104 p = self.partial(capture, *args)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000105 expected = args + ('x',)
106 got, empty = p('x')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000107 self.assertTrue(expected == got and empty == {})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000108
109 def test_keyword(self):
110 # make sure keyword arguments are captured correctly
111 for a in ['a', 0, None, 3.5]:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100112 p = self.partial(capture, a=a)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000113 expected = {'a':a,'x':None}
114 empty, got = p(x=None)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000115 self.assertTrue(expected == got and empty == ())
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000116
117 def test_no_side_effects(self):
118 # make sure there are no side effects that affect subsequent calls
Antoine Pitroub5b37142012-11-13 21:35:40 +0100119 p = self.partial(capture, 0, a=1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000120 args1, kw1 = p(1, b=2)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000121 self.assertTrue(args1 == (0,1) and kw1 == {'a':1,'b':2})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000122 args2, kw2 = p()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000123 self.assertTrue(args2 == (0,) and kw2 == {'a':1})
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000124
125 def test_error_propagation(self):
126 def f(x, y):
127 x / y
Antoine Pitroub5b37142012-11-13 21:35:40 +0100128 self.assertRaises(ZeroDivisionError, self.partial(f, 1, 0))
129 self.assertRaises(ZeroDivisionError, self.partial(f, 1), 0)
130 self.assertRaises(ZeroDivisionError, self.partial(f), 1, 0)
131 self.assertRaises(ZeroDivisionError, self.partial(f, y=0), 1)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000132
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000133 def test_weakref(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100134 f = self.partial(int, base=16)
Raymond Hettingerc8b6d1b2005-03-08 06:14:50 +0000135 p = proxy(f)
136 self.assertEqual(f.func, p.func)
137 f = None
138 self.assertRaises(ReferenceError, getattr, p, 'func')
139
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000140 def test_with_bound_and_unbound_methods(self):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000141 data = list(map(str, range(10)))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100142 join = self.partial(str.join, '')
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000143 self.assertEqual(join(data), '0123456789')
Antoine Pitroub5b37142012-11-13 21:35:40 +0100144 join = self.partial(''.join)
Raymond Hettinger26e512a2005-03-11 06:48:49 +0000145 self.assertEqual(join(data), '0123456789')
Tim Peterseba28be2005-03-28 01:08:02 +0000146
Łukasz Langa6f692512013-06-05 12:20:24 +0200147
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200148@unittest.skipUnless(c_functools, 'requires the C _functools module')
149class TestPartialC(TestPartial, unittest.TestCase):
150 if c_functools:
151 partial = c_functools.partial
152
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000153 def test_repr(self):
154 args = (object(), object())
155 args_repr = ', '.join(repr(a) for a in args)
156 kwargs = {'a': object(), 'b': object()}
157 kwargs_repr = ', '.join("%s=%r" % (k, v) for k, v in kwargs.items())
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200158 if self.partial is c_functools.partial:
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000159 name = 'functools.partial'
160 else:
Antoine Pitroub5b37142012-11-13 21:35:40 +0100161 name = self.partial.__name__
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000162
Antoine Pitroub5b37142012-11-13 21:35:40 +0100163 f = self.partial(capture)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000164 self.assertEqual('{}({!r})'.format(name, capture),
165 repr(f))
166
Antoine Pitroub5b37142012-11-13 21:35:40 +0100167 f = self.partial(capture, *args)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000168 self.assertEqual('{}({!r}, {})'.format(name, capture, args_repr),
169 repr(f))
170
Antoine Pitroub5b37142012-11-13 21:35:40 +0100171 f = self.partial(capture, **kwargs)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000172 self.assertEqual('{}({!r}, {})'.format(name, capture, kwargs_repr),
173 repr(f))
174
Antoine Pitroub5b37142012-11-13 21:35:40 +0100175 f = self.partial(capture, *args, **kwargs)
Alexander Belopolsky41e422a2010-12-01 20:05:49 +0000176 self.assertEqual('{}({!r}, {}, {})'.format(name, capture, args_repr, kwargs_repr),
177 repr(f))
178
Jack Diederiche0cbd692009-04-01 04:27:09 +0000179 def test_pickle(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100180 f = self.partial(signature, 'asdf', bar=True)
Jack Diederiche0cbd692009-04-01 04:27:09 +0000181 f.add_something_to__dict__ = True
182 f_copy = pickle.loads(pickle.dumps(f))
183 self.assertEqual(signature(f), signature(f_copy))
184
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200185 # Issue 6083: Reference counting bug
186 def test_setstate_refcount(self):
187 class BadSequence:
188 def __len__(self):
189 return 4
190 def __getitem__(self, key):
191 if key == 0:
192 return max
193 elif key == 1:
194 return tuple(range(1000000))
195 elif key in (2, 3):
196 return {}
197 raise IndexError
198
Serhiy Storchakab6a53402013-02-04 12:57:16 +0200199 f = self.partial(object)
Serhiy Storchaka19c4e0d2013-02-04 12:47:24 +0200200 self.assertRaisesRegex(SystemError,
201 "new style getargs format but argument is not a tuple",
202 f.__setstate__, BadSequence())
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000203
Łukasz Langa6f692512013-06-05 12:20:24 +0200204
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200205class TestPartialPy(TestPartial, unittest.TestCase):
206 partial = staticmethod(py_functools.partial)
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000207
Łukasz Langa6f692512013-06-05 12:20:24 +0200208
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200209if c_functools:
210 class PartialSubclass(c_functools.partial):
211 pass
Antoine Pitrou33543272012-11-13 21:36:21 +0100212
Łukasz Langa6f692512013-06-05 12:20:24 +0200213
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200214@unittest.skipUnless(c_functools, 'requires the C _functools module')
Serhiy Storchakab6a53402013-02-04 12:57:16 +0200215class TestPartialCSubclass(TestPartialC):
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200216 if c_functools:
217 partial = PartialSubclass
Jack Diederiche0cbd692009-04-01 04:27:09 +0000218
Łukasz Langa6f692512013-06-05 12:20:24 +0200219
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000220class TestUpdateWrapper(unittest.TestCase):
221
222 def check_wrapper(self, wrapper, wrapped,
223 assigned=functools.WRAPPER_ASSIGNMENTS,
224 updated=functools.WRAPPER_UPDATES):
225 # Check attributes were assigned
226 for name in assigned:
Nick Coghlan24c05bc2013-07-15 21:13:08 +1000227 self.assertIs(getattr(wrapper, name), getattr(wrapped, name))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000228 # Check attributes were updated
229 for name in updated:
230 wrapper_attr = getattr(wrapper, name)
231 wrapped_attr = getattr(wrapped, name)
232 for key in wrapped_attr:
Nick Coghlan24c05bc2013-07-15 21:13:08 +1000233 if name == "__dict__" and key == "__wrapped__":
234 # __wrapped__ is overwritten by the update code
235 continue
236 self.assertIs(wrapped_attr[key], wrapper_attr[key])
237 # Check __wrapped__
238 self.assertIs(wrapper.__wrapped__, wrapped)
239
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000240
R. David Murray378c0cf2010-02-24 01:46:21 +0000241 def _default_update(self):
Antoine Pitrou560f7642010-08-04 18:28:02 +0000242 def f(a:'This is a new annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000243 """This is a test"""
244 pass
245 f.attr = 'This is also a test'
Nick Coghlan24c05bc2013-07-15 21:13:08 +1000246 f.__wrapped__ = "This is a bald faced lie"
Antoine Pitrou560f7642010-08-04 18:28:02 +0000247 def wrapper(b:'This is the prior annotation'):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000248 pass
249 functools.update_wrapper(wrapper, f)
R. David Murray378c0cf2010-02-24 01:46:21 +0000250 return wrapper, f
251
252 def test_default_update(self):
253 wrapper, f = self._default_update()
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000254 self.check_wrapper(wrapper, f)
Nick Coghlan98876832010-08-17 06:17:18 +0000255 self.assertIs(wrapper.__wrapped__, f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000256 self.assertEqual(wrapper.__name__, 'f')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600257 self.assertEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000258 self.assertEqual(wrapper.attr, 'This is also a test')
Antoine Pitrou560f7642010-08-04 18:28:02 +0000259 self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation')
260 self.assertNotIn('b', wrapper.__annotations__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000261
R. David Murray378c0cf2010-02-24 01:46:21 +0000262 @unittest.skipIf(sys.flags.optimize >= 2,
263 "Docstrings are omitted with -O2 and above")
264 def test_default_update_doc(self):
265 wrapper, f = self._default_update()
266 self.assertEqual(wrapper.__doc__, 'This is a test')
267
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000268 def test_no_update(self):
269 def f():
270 """This is a test"""
271 pass
272 f.attr = 'This is also a test'
273 def wrapper():
274 pass
275 functools.update_wrapper(wrapper, f, (), ())
276 self.check_wrapper(wrapper, f, (), ())
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)
Antoine Pitrou560f7642010-08-04 18:28:02 +0000280 self.assertEqual(wrapper.__annotations__, {})
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000281 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000282
283 def test_selective_update(self):
284 def f():
285 pass
286 f.attr = 'This is a different test'
287 f.dict_attr = dict(a=1, b=2, c=3)
288 def wrapper():
289 pass
290 wrapper.dict_attr = {}
291 assign = ('attr',)
292 update = ('dict_attr',)
293 functools.update_wrapper(wrapper, f, assign, update)
294 self.check_wrapper(wrapper, f, assign, update)
295 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600296 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000297 self.assertEqual(wrapper.__doc__, None)
298 self.assertEqual(wrapper.attr, 'This is a different test')
299 self.assertEqual(wrapper.dict_attr, f.dict_attr)
300
Nick Coghlan98876832010-08-17 06:17:18 +0000301 def test_missing_attributes(self):
302 def f():
303 pass
304 def wrapper():
305 pass
306 wrapper.dict_attr = {}
307 assign = ('attr',)
308 update = ('dict_attr',)
309 # Missing attributes on wrapped object are ignored
310 functools.update_wrapper(wrapper, f, assign, update)
311 self.assertNotIn('attr', wrapper.__dict__)
312 self.assertEqual(wrapper.dict_attr, {})
313 # Wrapper must have expected attributes for updating
314 del wrapper.dict_attr
315 with self.assertRaises(AttributeError):
316 functools.update_wrapper(wrapper, f, assign, update)
317 wrapper.dict_attr = 1
318 with self.assertRaises(AttributeError):
319 functools.update_wrapper(wrapper, f, assign, update)
320
Serhiy Storchaka9d0add02013-01-27 19:47:45 +0200321 @support.requires_docstrings
Nick Coghlan98876832010-08-17 06:17:18 +0000322 @unittest.skipIf(sys.flags.optimize >= 2,
323 "Docstrings are omitted with -O2 and above")
Thomas Wouters89f507f2006-12-13 04:49:30 +0000324 def test_builtin_update(self):
325 # Test for bug #1576241
326 def wrapper():
327 pass
328 functools.update_wrapper(wrapper, max)
329 self.assertEqual(wrapper.__name__, 'max')
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000330 self.assertTrue(wrapper.__doc__.startswith('max('))
Antoine Pitrou560f7642010-08-04 18:28:02 +0000331 self.assertEqual(wrapper.__annotations__, {})
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000332
Łukasz Langa6f692512013-06-05 12:20:24 +0200333
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000334class TestWraps(TestUpdateWrapper):
335
R. David Murray378c0cf2010-02-24 01:46:21 +0000336 def _default_update(self):
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000337 def f():
338 """This is a test"""
339 pass
340 f.attr = 'This is also a test'
Nick Coghlan24c05bc2013-07-15 21:13:08 +1000341 f.__wrapped__ = "This is still a bald faced lie"
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000342 @functools.wraps(f)
343 def wrapper():
344 pass
Meador Ingeff7f64c2011-12-11 22:37:31 -0600345 return wrapper, f
R. David Murray378c0cf2010-02-24 01:46:21 +0000346
347 def test_default_update(self):
Meador Ingeff7f64c2011-12-11 22:37:31 -0600348 wrapper, f = self._default_update()
Nick Coghlan24c05bc2013-07-15 21:13:08 +1000349 self.check_wrapper(wrapper, f)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000350 self.assertEqual(wrapper.__name__, 'f')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600351 self.assertEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000352 self.assertEqual(wrapper.attr, 'This is also a test')
353
Antoine Pitroub5b37142012-11-13 21:35:40 +0100354 @unittest.skipIf(sys.flags.optimize >= 2,
R. David Murray378c0cf2010-02-24 01:46:21 +0000355 "Docstrings are omitted with -O2 and above")
356 def test_default_update_doc(self):
Meador Ingeff7f64c2011-12-11 22:37:31 -0600357 wrapper, _ = self._default_update()
R. David Murray378c0cf2010-02-24 01:46:21 +0000358 self.assertEqual(wrapper.__doc__, 'This is a test')
359
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000360 def test_no_update(self):
361 def f():
362 """This is a test"""
363 pass
364 f.attr = 'This is also a test'
365 @functools.wraps(f, (), ())
366 def wrapper():
367 pass
368 self.check_wrapper(wrapper, f, (), ())
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)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000372 self.assertFalse(hasattr(wrapper, 'attr'))
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000373
374 def test_selective_update(self):
375 def f():
376 pass
377 f.attr = 'This is a different test'
378 f.dict_attr = dict(a=1, b=2, c=3)
379 def add_dict_attr(f):
380 f.dict_attr = {}
381 return f
382 assign = ('attr',)
383 update = ('dict_attr',)
384 @functools.wraps(f, assign, update)
385 @add_dict_attr
386 def wrapper():
387 pass
388 self.check_wrapper(wrapper, f, assign, update)
389 self.assertEqual(wrapper.__name__, 'wrapper')
Meador Ingeff7f64c2011-12-11 22:37:31 -0600390 self.assertNotEqual(wrapper.__qualname__, f.__qualname__)
Thomas Wouters73e5a5b2006-06-08 15:35:45 +0000391 self.assertEqual(wrapper.__doc__, None)
392 self.assertEqual(wrapper.attr, 'This is a different test')
393 self.assertEqual(wrapper.dict_attr, f.dict_attr)
394
Łukasz Langa6f692512013-06-05 12:20:24 +0200395
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000396class TestReduce(unittest.TestCase):
397 func = functools.reduce
398
399 def test_reduce(self):
400 class Squares:
401 def __init__(self, max):
402 self.max = max
403 self.sofar = []
404
405 def __len__(self):
406 return len(self.sofar)
407
408 def __getitem__(self, i):
409 if not 0 <= i < self.max: raise IndexError
410 n = len(self.sofar)
411 while n <= i:
412 self.sofar.append(n*n)
413 n += 1
414 return self.sofar[i]
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000415 def add(x, y):
416 return x + y
417 self.assertEqual(self.func(add, ['a', 'b', 'c'], ''), 'abc')
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000418 self.assertEqual(
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000419 self.func(add, [['a', 'c'], [], ['d', 'w']], []),
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000420 ['a','c','d','w']
421 )
422 self.assertEqual(self.func(lambda x, y: x*y, range(2,8), 1), 5040)
423 self.assertEqual(
Guido van Rossume2a383d2007-01-15 16:59:06 +0000424 self.func(lambda x, y: x*y, range(2,21), 1),
425 2432902008176640000
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000426 )
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000427 self.assertEqual(self.func(add, Squares(10)), 285)
428 self.assertEqual(self.func(add, Squares(10), 0), 285)
429 self.assertEqual(self.func(add, Squares(0), 0), 0)
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000430 self.assertRaises(TypeError, self.func)
431 self.assertRaises(TypeError, self.func, 42, 42)
432 self.assertRaises(TypeError, self.func, 42, 42, 42)
433 self.assertEqual(self.func(42, "1"), "1") # func is never called with one item
434 self.assertEqual(self.func(42, "", "1"), "1") # func is never called with one item
435 self.assertRaises(TypeError, self.func, 42, (42, 42))
Alexander Belopolskye29e6bf2010-08-16 18:55:46 +0000436 self.assertRaises(TypeError, self.func, add, []) # arg 2 must not be empty sequence with no initial value
437 self.assertRaises(TypeError, self.func, add, "")
438 self.assertRaises(TypeError, self.func, add, ())
439 self.assertRaises(TypeError, self.func, add, object())
440
441 class TestFailingIter:
442 def __iter__(self):
443 raise RuntimeError
444 self.assertRaises(RuntimeError, self.func, add, TestFailingIter())
445
446 self.assertEqual(self.func(add, [], None), None)
447 self.assertEqual(self.func(add, [], 42), 42)
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000448
449 class BadSeq:
450 def __getitem__(self, index):
451 raise ValueError
452 self.assertRaises(ValueError, self.func, 42, BadSeq())
453
454 # Test reduce()'s use of iterators.
455 def test_iterator_usage(self):
456 class SequenceClass:
457 def __init__(self, n):
458 self.n = n
459 def __getitem__(self, i):
460 if 0 <= i < self.n:
461 return i
462 else:
463 raise IndexError
Guido van Rossumd8faa362007-04-27 19:54:29 +0000464
Guido van Rossum0919a1a2006-08-26 20:49:04 +0000465 from operator import add
466 self.assertEqual(self.func(add, SequenceClass(5)), 10)
467 self.assertEqual(self.func(add, SequenceClass(5), 42), 52)
468 self.assertRaises(TypeError, self.func, add, SequenceClass(0))
469 self.assertEqual(self.func(add, SequenceClass(0), 42), 42)
470 self.assertEqual(self.func(add, SequenceClass(1)), 0)
471 self.assertEqual(self.func(add, SequenceClass(1), 42), 42)
472
473 d = {"one": 1, "two": 2, "three": 3}
474 self.assertEqual(self.func(add, d), "".join(d.keys()))
475
Łukasz Langa6f692512013-06-05 12:20:24 +0200476
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200477class TestCmpToKey:
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700478
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000479 def test_cmp_to_key(self):
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700480 def cmp1(x, y):
481 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100482 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700483 self.assertEqual(key(3), key(3))
484 self.assertGreater(key(3), key(1))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100485 self.assertGreaterEqual(key(3), key(3))
486
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700487 def cmp2(x, y):
488 return int(x) - int(y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100489 key = self.cmp_to_key(cmp2)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700490 self.assertEqual(key(4.0), key('4'))
491 self.assertLess(key(2), key('35'))
Antoine Pitroub5b37142012-11-13 21:35:40 +0100492 self.assertLessEqual(key(2), key('35'))
493 self.assertNotEqual(key(2), key('35'))
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700494
495 def test_cmp_to_key_arguments(self):
496 def cmp1(x, y):
497 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100498 key = self.cmp_to_key(mycmp=cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700499 self.assertEqual(key(obj=3), key(obj=3))
500 self.assertGreater(key(obj=3), key(obj=1))
501 with self.assertRaises((TypeError, AttributeError)):
502 key(3) > 1 # rhs is not a K object
503 with self.assertRaises((TypeError, AttributeError)):
504 1 < key(3) # lhs is not a K object
505 with self.assertRaises(TypeError):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100506 key = self.cmp_to_key() # too few args
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700507 with self.assertRaises(TypeError):
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200508 key = self.cmp_to_key(cmp1, None) # too many args
Antoine Pitroub5b37142012-11-13 21:35:40 +0100509 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700510 with self.assertRaises(TypeError):
511 key() # too few args
512 with self.assertRaises(TypeError):
513 key(None, None) # too many args
514
515 def test_bad_cmp(self):
516 def cmp1(x, y):
517 raise ZeroDivisionError
Antoine Pitroub5b37142012-11-13 21:35:40 +0100518 key = self.cmp_to_key(cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700519 with self.assertRaises(ZeroDivisionError):
520 key(3) > key(1)
521
522 class BadCmp:
523 def __lt__(self, other):
524 raise ZeroDivisionError
525 def cmp1(x, y):
526 return BadCmp()
527 with self.assertRaises(ZeroDivisionError):
528 key(3) > key(1)
529
530 def test_obj_field(self):
531 def cmp1(x, y):
532 return (x > y) - (x < y)
Antoine Pitroub5b37142012-11-13 21:35:40 +0100533 key = self.cmp_to_key(mycmp=cmp1)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700534 self.assertEqual(key(50).obj, 50)
535
536 def test_sort_int(self):
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000537 def mycmp(x, y):
538 return y - x
Antoine Pitroub5b37142012-11-13 21:35:40 +0100539 self.assertEqual(sorted(range(5), key=self.cmp_to_key(mycmp)),
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000540 [4, 3, 2, 1, 0])
Guido van Rossumd8faa362007-04-27 19:54:29 +0000541
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700542 def test_sort_int_str(self):
543 def mycmp(x, y):
544 x, y = int(x), int(y)
545 return (x > y) - (x < y)
546 values = [5, '3', 7, 2, '0', '1', 4, '10', 1]
Antoine Pitroub5b37142012-11-13 21:35:40 +0100547 values = sorted(values, key=self.cmp_to_key(mycmp))
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700548 self.assertEqual([int(value) for value in values],
549 [0, 1, 1, 2, 3, 4, 5, 7, 10])
550
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000551 def test_hash(self):
552 def mycmp(x, y):
553 return y - x
Antoine Pitroub5b37142012-11-13 21:35:40 +0100554 key = self.cmp_to_key(mycmp)
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000555 k = key(10)
Raymond Hettinger7ab9e222011-04-05 02:33:54 -0700556 self.assertRaises(TypeError, hash, k)
Raymond Hettingere7a24302011-05-03 11:16:36 -0700557 self.assertNotIsInstance(k, collections.Hashable)
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000558
Łukasz Langa6f692512013-06-05 12:20:24 +0200559
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200560@unittest.skipUnless(c_functools, 'requires the C _functools module')
561class TestCmpToKeyC(TestCmpToKey, unittest.TestCase):
562 if c_functools:
563 cmp_to_key = c_functools.cmp_to_key
Antoine Pitroub5b37142012-11-13 21:35:40 +0100564
Łukasz Langa6f692512013-06-05 12:20:24 +0200565
Serhiy Storchakaca4220b2013-02-05 22:12:59 +0200566class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100567 cmp_to_key = staticmethod(py_functools.cmp_to_key)
568
Łukasz Langa6f692512013-06-05 12:20:24 +0200569
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000570class TestTotalOrdering(unittest.TestCase):
571
572 def test_total_ordering_lt(self):
573 @functools.total_ordering
574 class A:
575 def __init__(self, value):
576 self.value = value
577 def __lt__(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_le(self):
589 @functools.total_ordering
590 class A:
591 def __init__(self, value):
592 self.value = value
593 def __le__(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_gt(self):
605 @functools.total_ordering
606 class A:
607 def __init__(self, value):
608 self.value = value
609 def __gt__(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_ge(self):
621 @functools.total_ordering
622 class A:
623 def __init__(self, value):
624 self.value = value
625 def __ge__(self, other):
626 return self.value >= other.value
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000627 def __eq__(self, other):
628 return self.value == other.value
Ezio Melottib3aedd42010-11-20 19:04:17 +0000629 self.assertTrue(A(1) < A(2))
630 self.assertTrue(A(2) > A(1))
631 self.assertTrue(A(1) <= A(2))
632 self.assertTrue(A(2) >= A(1))
633 self.assertTrue(A(2) <= A(2))
634 self.assertTrue(A(2) >= A(2))
Raymond Hettingerc50846a2010-04-05 18:56:31 +0000635
636 def test_total_ordering_no_overwrite(self):
637 # new methods should not overwrite existing
638 @functools.total_ordering
639 class A(int):
Benjamin Peterson9c2930e2010-08-23 17:40:33 +0000640 pass
Ezio Melottib3aedd42010-11-20 19:04:17 +0000641 self.assertTrue(A(1) < A(2))
642 self.assertTrue(A(2) > A(1))
643 self.assertTrue(A(1) <= A(2))
644 self.assertTrue(A(2) >= A(1))
645 self.assertTrue(A(2) <= A(2))
646 self.assertTrue(A(2) >= A(2))
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000647
Benjamin Peterson42ebee32010-04-11 01:43:16 +0000648 def test_no_operations_defined(self):
649 with self.assertRaises(ValueError):
650 @functools.total_ordering
651 class A:
652 pass
Raymond Hettinger9c323f82005-02-28 19:39:44 +0000653
Raymond Hettinger23f9fc32011-01-08 07:01:56 +0000654 def test_bug_10042(self):
655 @functools.total_ordering
656 class TestTO:
657 def __init__(self, value):
658 self.value = value
659 def __eq__(self, other):
660 if isinstance(other, TestTO):
661 return self.value == other.value
662 return False
663 def __lt__(self, other):
664 if isinstance(other, TestTO):
665 return self.value < other.value
666 raise TypeError
667 with self.assertRaises(TypeError):
668 TestTO(8) <= ()
669
Łukasz Langa6f692512013-06-05 12:20:24 +0200670
Georg Brandl2e7346a2010-07-31 18:09:23 +0000671class TestLRU(unittest.TestCase):
672
673 def test_lru(self):
674 def orig(x, y):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100675 return 3 * x + y
Georg Brandl2e7346a2010-07-31 18:09:23 +0000676 f = functools.lru_cache(maxsize=20)(orig)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000677 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000678 self.assertEqual(maxsize, 20)
679 self.assertEqual(currsize, 0)
680 self.assertEqual(hits, 0)
681 self.assertEqual(misses, 0)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000682
683 domain = range(5)
684 for i in range(1000):
685 x, y = choice(domain), choice(domain)
686 actual = f(x, y)
687 expected = orig(x, y)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000688 self.assertEqual(actual, expected)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000689 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000690 self.assertTrue(hits > misses)
691 self.assertEqual(hits + misses, 1000)
692 self.assertEqual(currsize, 20)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000693
Raymond Hettinger02566ec2010-09-04 22:46:06 +0000694 f.cache_clear() # test clearing
Raymond Hettinger7496b412010-11-30 19:15:45 +0000695 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000696 self.assertEqual(hits, 0)
697 self.assertEqual(misses, 0)
698 self.assertEqual(currsize, 0)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000699 f(x, y)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000700 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000701 self.assertEqual(hits, 0)
702 self.assertEqual(misses, 1)
703 self.assertEqual(currsize, 1)
Georg Brandl2e7346a2010-07-31 18:09:23 +0000704
Nick Coghlan98876832010-08-17 06:17:18 +0000705 # Test bypassing the cache
706 self.assertIs(f.__wrapped__, orig)
707 f.__wrapped__(x, y)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000708 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000709 self.assertEqual(hits, 0)
710 self.assertEqual(misses, 1)
711 self.assertEqual(currsize, 1)
Nick Coghlan98876832010-08-17 06:17:18 +0000712
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000713 # test size zero (which means "never-cache")
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000714 @functools.lru_cache(0)
715 def f():
716 nonlocal f_cnt
717 f_cnt += 1
718 return 20
Nick Coghlan234515a2010-11-30 06:19:46 +0000719 self.assertEqual(f.cache_info().maxsize, 0)
Raymond Hettingerf3098282010-08-15 03:30:45 +0000720 f_cnt = 0
721 for i in range(5):
722 self.assertEqual(f(), 20)
723 self.assertEqual(f_cnt, 5)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000724 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000725 self.assertEqual(hits, 0)
726 self.assertEqual(misses, 5)
727 self.assertEqual(currsize, 0)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000728
729 # test size one
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000730 @functools.lru_cache(1)
731 def f():
732 nonlocal f_cnt
733 f_cnt += 1
734 return 20
Nick Coghlan234515a2010-11-30 06:19:46 +0000735 self.assertEqual(f.cache_info().maxsize, 1)
Raymond Hettingerf3098282010-08-15 03:30:45 +0000736 f_cnt = 0
737 for i in range(5):
738 self.assertEqual(f(), 20)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000739 self.assertEqual(f_cnt, 1)
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, 4)
742 self.assertEqual(misses, 1)
743 self.assertEqual(currsize, 1)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000744
Raymond Hettingerf3098282010-08-15 03:30:45 +0000745 # test size two
746 @functools.lru_cache(2)
747 def f(x):
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000748 nonlocal f_cnt
749 f_cnt += 1
Raymond Hettingerf3098282010-08-15 03:30:45 +0000750 return x*10
Nick Coghlan234515a2010-11-30 06:19:46 +0000751 self.assertEqual(f.cache_info().maxsize, 2)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000752 f_cnt = 0
Raymond Hettingerf3098282010-08-15 03:30:45 +0000753 for x in 7, 9, 7, 9, 7, 9, 8, 8, 8, 9, 9, 9, 8, 8, 8, 7:
754 # * * * *
755 self.assertEqual(f(x), x*10)
756 self.assertEqual(f_cnt, 4)
Raymond Hettinger7496b412010-11-30 19:15:45 +0000757 hits, misses, maxsize, currsize = f.cache_info()
Nick Coghlan234515a2010-11-30 06:19:46 +0000758 self.assertEqual(hits, 12)
759 self.assertEqual(misses, 4)
760 self.assertEqual(currsize, 2)
Raymond Hettinger0f56e902010-08-14 23:52:08 +0000761
Raymond Hettingerc79fb0e2010-12-01 03:45:41 +0000762 def test_lru_with_maxsize_none(self):
763 @functools.lru_cache(maxsize=None)
764 def fib(n):
765 if n < 2:
766 return n
767 return fib(n-1) + fib(n-2)
768 self.assertEqual([fib(n) for n in range(16)],
769 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
770 self.assertEqual(fib.cache_info(),
771 functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
772 fib.cache_clear()
773 self.assertEqual(fib.cache_info(),
774 functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
775
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700776 def test_lru_with_exceptions(self):
777 # Verify that user_function exceptions get passed through without
778 # creating a hard-to-read chained exception.
779 # http://bugs.python.org/issue13177
Antoine Pitroub5b37142012-11-13 21:35:40 +0100780 for maxsize in (None, 128):
Raymond Hettinger4b779b32011-10-15 23:50:42 -0700781 @functools.lru_cache(maxsize)
782 def func(i):
783 return 'abc'[i]
784 self.assertEqual(func(0), 'a')
785 with self.assertRaises(IndexError) as cm:
786 func(15)
787 self.assertIsNone(cm.exception.__context__)
788 # Verify that the previous exception did not result in a cached entry
789 with self.assertRaises(IndexError):
790 func(15)
791
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700792 def test_lru_with_types(self):
Antoine Pitroub5b37142012-11-13 21:35:40 +0100793 for maxsize in (None, 128):
Raymond Hettingercd9fdfd2011-10-20 08:57:45 -0700794 @functools.lru_cache(maxsize=maxsize, typed=True)
795 def square(x):
796 return x * x
797 self.assertEqual(square(3), 9)
798 self.assertEqual(type(square(3)), type(9))
799 self.assertEqual(square(3.0), 9.0)
800 self.assertEqual(type(square(3.0)), type(9.0))
801 self.assertEqual(square(x=3), 9)
802 self.assertEqual(type(square(x=3)), type(9))
803 self.assertEqual(square(x=3.0), 9.0)
804 self.assertEqual(type(square(x=3.0)), type(9.0))
805 self.assertEqual(square.cache_info().hits, 4)
806 self.assertEqual(square.cache_info().misses, 4)
807
Antoine Pitroub5b37142012-11-13 21:35:40 +0100808 def test_lru_with_keyword_args(self):
809 @functools.lru_cache()
810 def fib(n):
811 if n < 2:
812 return n
813 return fib(n=n-1) + fib(n=n-2)
814 self.assertEqual(
815 [fib(n=number) for number in range(16)],
816 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
817 )
818 self.assertEqual(fib.cache_info(),
819 functools._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16))
820 fib.cache_clear()
821 self.assertEqual(fib.cache_info(),
822 functools._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0))
823
824 def test_lru_with_keyword_args_maxsize_none(self):
825 @functools.lru_cache(maxsize=None)
826 def fib(n):
827 if n < 2:
828 return n
829 return fib(n=n-1) + fib(n=n-2)
830 self.assertEqual([fib(n=number) for number in range(16)],
831 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610])
832 self.assertEqual(fib.cache_info(),
833 functools._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16))
834 fib.cache_clear()
835 self.assertEqual(fib.cache_info(),
836 functools._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0))
837
Raymond Hettinger03923422013-03-04 02:52:50 -0500838 def test_need_for_rlock(self):
839 # This will deadlock on an LRU cache that uses a regular lock
840
841 @functools.lru_cache(maxsize=10)
842 def test_func(x):
843 'Used to demonstrate a reentrant lru_cache call within a single thread'
844 return x
845
846 class DoubleEq:
847 'Demonstrate a reentrant lru_cache call within a single thread'
848 def __init__(self, x):
849 self.x = x
850 def __hash__(self):
851 return self.x
852 def __eq__(self, other):
853 if self.x == 2:
854 test_func(DoubleEq(1))
855 return self.x == other.x
856
857 test_func(DoubleEq(1)) # Load the cache
858 test_func(DoubleEq(2)) # Load the cache
859 self.assertEqual(test_func(DoubleEq(2)), # Trigger a re-entrant __eq__ call
860 DoubleEq(2)) # Verify the correct return value
861
862
Łukasz Langa6f692512013-06-05 12:20:24 +0200863class TestSingleDispatch(unittest.TestCase):
864 def test_simple_overloads(self):
865 @functools.singledispatch
866 def g(obj):
867 return "base"
868 def g_int(i):
869 return "integer"
870 g.register(int, g_int)
871 self.assertEqual(g("str"), "base")
872 self.assertEqual(g(1), "integer")
873 self.assertEqual(g([1,2,3]), "base")
874
875 def test_mro(self):
876 @functools.singledispatch
877 def g(obj):
878 return "base"
Łukasz Langa7f7a67a2013-06-07 22:25:27 +0200879 class A:
Łukasz Langa6f692512013-06-05 12:20:24 +0200880 pass
Łukasz Langa7f7a67a2013-06-07 22:25:27 +0200881 class C(A):
Łukasz Langa6f692512013-06-05 12:20:24 +0200882 pass
Łukasz Langa7f7a67a2013-06-07 22:25:27 +0200883 class B(A):
Łukasz Langa6f692512013-06-05 12:20:24 +0200884 pass
Łukasz Langa7f7a67a2013-06-07 22:25:27 +0200885 class D(C, B):
Łukasz Langa6f692512013-06-05 12:20:24 +0200886 pass
Łukasz Langa7f7a67a2013-06-07 22:25:27 +0200887 def g_A(a):
888 return "A"
889 def g_B(b):
890 return "B"
891 g.register(A, g_A)
892 g.register(B, g_B)
893 self.assertEqual(g(A()), "A")
894 self.assertEqual(g(B()), "B")
895 self.assertEqual(g(C()), "A")
896 self.assertEqual(g(D()), "B")
Łukasz Langa6f692512013-06-05 12:20:24 +0200897
898 def test_register_decorator(self):
899 @functools.singledispatch
900 def g(obj):
901 return "base"
902 @g.register(int)
903 def g_int(i):
904 return "int %s" % (i,)
905 self.assertEqual(g(""), "base")
906 self.assertEqual(g(12), "int 12")
907 self.assertIs(g.dispatch(int), g_int)
908 self.assertIs(g.dispatch(object), g.dispatch(str))
909 # Note: in the assert above this is not g.
910 # @singledispatch returns the wrapper.
911
912 def test_wrapping_attributes(self):
913 @functools.singledispatch
914 def g(obj):
915 "Simple test"
916 return "Test"
917 self.assertEqual(g.__name__, "g")
918 self.assertEqual(g.__doc__, "Simple test")
919
920 @unittest.skipUnless(decimal, 'requires _decimal')
921 @support.cpython_only
922 def test_c_classes(self):
923 @functools.singledispatch
924 def g(obj):
925 return "base"
926 @g.register(decimal.DecimalException)
927 def _(obj):
928 return obj.args
929 subn = decimal.Subnormal("Exponent < Emin")
930 rnd = decimal.Rounded("Number got rounded")
931 self.assertEqual(g(subn), ("Exponent < Emin",))
932 self.assertEqual(g(rnd), ("Number got rounded",))
933 @g.register(decimal.Subnormal)
934 def _(obj):
935 return "Too small to care."
936 self.assertEqual(g(subn), "Too small to care.")
937 self.assertEqual(g(rnd), ("Number got rounded",))
938
939 def test_compose_mro(self):
Łukasz Langa3720c772013-07-01 16:00:38 +0200940 # None of the examples in this test depend on haystack ordering.
Łukasz Langa6f692512013-06-05 12:20:24 +0200941 c = collections
942 mro = functools._compose_mro
943 bases = [c.Sequence, c.MutableMapping, c.Mapping, c.Set]
944 for haystack in permutations(bases):
945 m = mro(dict, haystack)
Łukasz Langa3720c772013-07-01 16:00:38 +0200946 self.assertEqual(m, [dict, c.MutableMapping, c.Mapping, c.Sized,
947 c.Iterable, c.Container, object])
Łukasz Langa6f692512013-06-05 12:20:24 +0200948 bases = [c.Container, c.Mapping, c.MutableMapping, c.OrderedDict]
949 for haystack in permutations(bases):
950 m = mro(c.ChainMap, haystack)
951 self.assertEqual(m, [c.ChainMap, c.MutableMapping, c.Mapping,
952 c.Sized, c.Iterable, c.Container, object])
Łukasz Langa3720c772013-07-01 16:00:38 +0200953
954 # If there's a generic function with implementations registered for
955 # both Sized and Container, passing a defaultdict to it results in an
956 # ambiguous dispatch which will cause a RuntimeError (see
957 # test_mro_conflicts).
958 bases = [c.Container, c.Sized, str]
959 for haystack in permutations(bases):
960 m = mro(c.defaultdict, [c.Sized, c.Container, str])
961 self.assertEqual(m, [c.defaultdict, dict, c.Sized, c.Container,
962 object])
963
964 # MutableSequence below is registered directly on D. In other words, it
965 # preceeds MutableMapping which means single dispatch will always
966 # choose MutableSequence here.
967 class D(c.defaultdict):
968 pass
969 c.MutableSequence.register(D)
970 bases = [c.MutableSequence, c.MutableMapping]
971 for haystack in permutations(bases):
972 m = mro(D, bases)
973 self.assertEqual(m, [D, c.MutableSequence, c.Sequence,
974 c.defaultdict, dict, c.MutableMapping,
975 c.Mapping, c.Sized, c.Iterable, c.Container,
976 object])
977
978 # Container and Callable are registered on different base classes and
979 # a generic function supporting both should always pick the Callable
980 # implementation if a C instance is passed.
981 class C(c.defaultdict):
982 def __call__(self):
983 pass
984 bases = [c.Sized, c.Callable, c.Container, c.Mapping]
985 for haystack in permutations(bases):
986 m = mro(C, haystack)
987 self.assertEqual(m, [C, c.Callable, c.defaultdict, dict, c.Mapping,
988 c.Sized, c.Iterable, c.Container, object])
Łukasz Langa6f692512013-06-05 12:20:24 +0200989
990 def test_register_abc(self):
991 c = collections
992 d = {"a": "b"}
993 l = [1, 2, 3]
994 s = {object(), None}
995 f = frozenset(s)
996 t = (1, 2, 3)
997 @functools.singledispatch
998 def g(obj):
999 return "base"
1000 self.assertEqual(g(d), "base")
1001 self.assertEqual(g(l), "base")
1002 self.assertEqual(g(s), "base")
1003 self.assertEqual(g(f), "base")
1004 self.assertEqual(g(t), "base")
1005 g.register(c.Sized, lambda obj: "sized")
1006 self.assertEqual(g(d), "sized")
1007 self.assertEqual(g(l), "sized")
1008 self.assertEqual(g(s), "sized")
1009 self.assertEqual(g(f), "sized")
1010 self.assertEqual(g(t), "sized")
1011 g.register(c.MutableMapping, lambda obj: "mutablemapping")
1012 self.assertEqual(g(d), "mutablemapping")
1013 self.assertEqual(g(l), "sized")
1014 self.assertEqual(g(s), "sized")
1015 self.assertEqual(g(f), "sized")
1016 self.assertEqual(g(t), "sized")
1017 g.register(c.ChainMap, lambda obj: "chainmap")
1018 self.assertEqual(g(d), "mutablemapping") # irrelevant ABCs registered
1019 self.assertEqual(g(l), "sized")
1020 self.assertEqual(g(s), "sized")
1021 self.assertEqual(g(f), "sized")
1022 self.assertEqual(g(t), "sized")
1023 g.register(c.MutableSequence, lambda obj: "mutablesequence")
1024 self.assertEqual(g(d), "mutablemapping")
1025 self.assertEqual(g(l), "mutablesequence")
1026 self.assertEqual(g(s), "sized")
1027 self.assertEqual(g(f), "sized")
1028 self.assertEqual(g(t), "sized")
1029 g.register(c.MutableSet, lambda obj: "mutableset")
1030 self.assertEqual(g(d), "mutablemapping")
1031 self.assertEqual(g(l), "mutablesequence")
1032 self.assertEqual(g(s), "mutableset")
1033 self.assertEqual(g(f), "sized")
1034 self.assertEqual(g(t), "sized")
1035 g.register(c.Mapping, lambda obj: "mapping")
1036 self.assertEqual(g(d), "mutablemapping") # not specific enough
1037 self.assertEqual(g(l), "mutablesequence")
1038 self.assertEqual(g(s), "mutableset")
1039 self.assertEqual(g(f), "sized")
1040 self.assertEqual(g(t), "sized")
1041 g.register(c.Sequence, lambda obj: "sequence")
1042 self.assertEqual(g(d), "mutablemapping")
1043 self.assertEqual(g(l), "mutablesequence")
1044 self.assertEqual(g(s), "mutableset")
1045 self.assertEqual(g(f), "sized")
1046 self.assertEqual(g(t), "sequence")
1047 g.register(c.Set, lambda obj: "set")
1048 self.assertEqual(g(d), "mutablemapping")
1049 self.assertEqual(g(l), "mutablesequence")
1050 self.assertEqual(g(s), "mutableset")
1051 self.assertEqual(g(f), "set")
1052 self.assertEqual(g(t), "sequence")
1053 g.register(dict, lambda obj: "dict")
1054 self.assertEqual(g(d), "dict")
1055 self.assertEqual(g(l), "mutablesequence")
1056 self.assertEqual(g(s), "mutableset")
1057 self.assertEqual(g(f), "set")
1058 self.assertEqual(g(t), "sequence")
1059 g.register(list, lambda obj: "list")
1060 self.assertEqual(g(d), "dict")
1061 self.assertEqual(g(l), "list")
1062 self.assertEqual(g(s), "mutableset")
1063 self.assertEqual(g(f), "set")
1064 self.assertEqual(g(t), "sequence")
1065 g.register(set, lambda obj: "concrete-set")
1066 self.assertEqual(g(d), "dict")
1067 self.assertEqual(g(l), "list")
1068 self.assertEqual(g(s), "concrete-set")
1069 self.assertEqual(g(f), "set")
1070 self.assertEqual(g(t), "sequence")
1071 g.register(frozenset, lambda obj: "frozen-set")
1072 self.assertEqual(g(d), "dict")
1073 self.assertEqual(g(l), "list")
1074 self.assertEqual(g(s), "concrete-set")
1075 self.assertEqual(g(f), "frozen-set")
1076 self.assertEqual(g(t), "sequence")
1077 g.register(tuple, lambda obj: "tuple")
1078 self.assertEqual(g(d), "dict")
1079 self.assertEqual(g(l), "list")
1080 self.assertEqual(g(s), "concrete-set")
1081 self.assertEqual(g(f), "frozen-set")
1082 self.assertEqual(g(t), "tuple")
1083
Łukasz Langa3720c772013-07-01 16:00:38 +02001084 def test_c3_abc(self):
1085 c = collections
1086 mro = functools._c3_mro
1087 class A(object):
1088 pass
1089 class B(A):
1090 def __len__(self):
1091 return 0 # implies Sized
1092 @c.Container.register
1093 class C(object):
1094 pass
1095 class D(object):
1096 pass # unrelated
1097 class X(D, C, B):
1098 def __call__(self):
1099 pass # implies Callable
1100 expected = [X, c.Callable, D, C, c.Container, B, c.Sized, A, object]
1101 for abcs in permutations([c.Sized, c.Callable, c.Container]):
1102 self.assertEqual(mro(X, abcs=abcs), expected)
1103 # unrelated ABCs don't appear in the resulting MRO
1104 many_abcs = [c.Mapping, c.Sized, c.Callable, c.Container, c.Iterable]
1105 self.assertEqual(mro(X, abcs=many_abcs), expected)
1106
Łukasz Langa6f692512013-06-05 12:20:24 +02001107 def test_mro_conflicts(self):
1108 c = collections
Łukasz Langa6f692512013-06-05 12:20:24 +02001109 @functools.singledispatch
1110 def g(arg):
1111 return "base"
Łukasz Langa6f692512013-06-05 12:20:24 +02001112 class O(c.Sized):
1113 def __len__(self):
1114 return 0
Łukasz Langa6f692512013-06-05 12:20:24 +02001115 o = O()
1116 self.assertEqual(g(o), "base")
1117 g.register(c.Iterable, lambda arg: "iterable")
1118 g.register(c.Container, lambda arg: "container")
1119 g.register(c.Sized, lambda arg: "sized")
1120 g.register(c.Set, lambda arg: "set")
1121 self.assertEqual(g(o), "sized")
1122 c.Iterable.register(O)
1123 self.assertEqual(g(o), "sized") # because it's explicitly in __mro__
1124 c.Container.register(O)
1125 self.assertEqual(g(o), "sized") # see above: Sized is in __mro__
Łukasz Langa3720c772013-07-01 16:00:38 +02001126 c.Set.register(O)
1127 self.assertEqual(g(o), "set") # because c.Set is a subclass of
1128 # c.Sized and c.Container
Łukasz Langa6f692512013-06-05 12:20:24 +02001129 class P:
1130 pass
Łukasz Langa6f692512013-06-05 12:20:24 +02001131 p = P()
1132 self.assertEqual(g(p), "base")
1133 c.Iterable.register(P)
1134 self.assertEqual(g(p), "iterable")
1135 c.Container.register(P)
Łukasz Langa3720c772013-07-01 16:00:38 +02001136 with self.assertRaises(RuntimeError) as re_one:
Łukasz Langa6f692512013-06-05 12:20:24 +02001137 g(p)
Łukasz Langa3720c772013-07-01 16:00:38 +02001138 self.assertIn(
1139 str(re_one.exception),
1140 (("Ambiguous dispatch: <class 'collections.abc.Container'> "
1141 "or <class 'collections.abc.Iterable'>"),
1142 ("Ambiguous dispatch: <class 'collections.abc.Iterable'> "
1143 "or <class 'collections.abc.Container'>")),
1144 )
Łukasz Langa6f692512013-06-05 12:20:24 +02001145 class Q(c.Sized):
1146 def __len__(self):
1147 return 0
Łukasz Langa6f692512013-06-05 12:20:24 +02001148 q = Q()
1149 self.assertEqual(g(q), "sized")
1150 c.Iterable.register(Q)
1151 self.assertEqual(g(q), "sized") # because it's explicitly in __mro__
1152 c.Set.register(Q)
1153 self.assertEqual(g(q), "set") # because c.Set is a subclass of
Łukasz Langa3720c772013-07-01 16:00:38 +02001154 # c.Sized and c.Iterable
1155 @functools.singledispatch
1156 def h(arg):
1157 return "base"
1158 @h.register(c.Sized)
1159 def _(arg):
1160 return "sized"
1161 @h.register(c.Container)
1162 def _(arg):
1163 return "container"
1164 # Even though Sized and Container are explicit bases of MutableMapping,
1165 # this ABC is implicitly registered on defaultdict which makes all of
1166 # MutableMapping's bases implicit as well from defaultdict's
1167 # perspective.
1168 with self.assertRaises(RuntimeError) as re_two:
1169 h(c.defaultdict(lambda: 0))
1170 self.assertIn(
1171 str(re_two.exception),
1172 (("Ambiguous dispatch: <class 'collections.abc.Container'> "
1173 "or <class 'collections.abc.Sized'>"),
1174 ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
1175 "or <class 'collections.abc.Container'>")),
1176 )
1177 class R(c.defaultdict):
1178 pass
1179 c.MutableSequence.register(R)
1180 @functools.singledispatch
1181 def i(arg):
1182 return "base"
1183 @i.register(c.MutableMapping)
1184 def _(arg):
1185 return "mapping"
1186 @i.register(c.MutableSequence)
1187 def _(arg):
1188 return "sequence"
1189 r = R()
1190 self.assertEqual(i(r), "sequence")
1191 class S:
1192 pass
1193 class T(S, c.Sized):
1194 def __len__(self):
1195 return 0
1196 t = T()
1197 self.assertEqual(h(t), "sized")
1198 c.Container.register(T)
1199 self.assertEqual(h(t), "sized") # because it's explicitly in the MRO
1200 class U:
1201 def __len__(self):
1202 return 0
1203 u = U()
1204 self.assertEqual(h(u), "sized") # implicit Sized subclass inferred
1205 # from the existence of __len__()
1206 c.Container.register(U)
1207 # There is no preference for registered versus inferred ABCs.
1208 with self.assertRaises(RuntimeError) as re_three:
1209 h(u)
1210 self.assertIn(
1211 str(re_three.exception),
1212 (("Ambiguous dispatch: <class 'collections.abc.Container'> "
1213 "or <class 'collections.abc.Sized'>"),
1214 ("Ambiguous dispatch: <class 'collections.abc.Sized'> "
1215 "or <class 'collections.abc.Container'>")),
1216 )
1217 class V(c.Sized, S):
1218 def __len__(self):
1219 return 0
1220 @functools.singledispatch
1221 def j(arg):
1222 return "base"
1223 @j.register(S)
1224 def _(arg):
1225 return "s"
1226 @j.register(c.Container)
1227 def _(arg):
1228 return "container"
1229 v = V()
1230 self.assertEqual(j(v), "s")
1231 c.Container.register(V)
1232 self.assertEqual(j(v), "container") # because it ends up right after
1233 # Sized in the MRO
Łukasz Langa6f692512013-06-05 12:20:24 +02001234
1235 def test_cache_invalidation(self):
1236 from collections import UserDict
1237 class TracingDict(UserDict):
1238 def __init__(self, *args, **kwargs):
1239 super(TracingDict, self).__init__(*args, **kwargs)
1240 self.set_ops = []
1241 self.get_ops = []
1242 def __getitem__(self, key):
1243 result = self.data[key]
1244 self.get_ops.append(key)
1245 return result
1246 def __setitem__(self, key, value):
1247 self.set_ops.append(key)
1248 self.data[key] = value
1249 def clear(self):
1250 self.data.clear()
1251 _orig_wkd = functools.WeakKeyDictionary
1252 td = TracingDict()
1253 functools.WeakKeyDictionary = lambda: td
1254 c = collections
1255 @functools.singledispatch
1256 def g(arg):
1257 return "base"
1258 d = {}
1259 l = []
1260 self.assertEqual(len(td), 0)
1261 self.assertEqual(g(d), "base")
1262 self.assertEqual(len(td), 1)
1263 self.assertEqual(td.get_ops, [])
1264 self.assertEqual(td.set_ops, [dict])
1265 self.assertEqual(td.data[dict], g.registry[object])
1266 self.assertEqual(g(l), "base")
1267 self.assertEqual(len(td), 2)
1268 self.assertEqual(td.get_ops, [])
1269 self.assertEqual(td.set_ops, [dict, list])
1270 self.assertEqual(td.data[dict], g.registry[object])
1271 self.assertEqual(td.data[list], g.registry[object])
1272 self.assertEqual(td.data[dict], td.data[list])
1273 self.assertEqual(g(l), "base")
1274 self.assertEqual(g(d), "base")
1275 self.assertEqual(td.get_ops, [list, dict])
1276 self.assertEqual(td.set_ops, [dict, list])
1277 g.register(list, lambda arg: "list")
1278 self.assertEqual(td.get_ops, [list, dict])
1279 self.assertEqual(len(td), 0)
1280 self.assertEqual(g(d), "base")
1281 self.assertEqual(len(td), 1)
1282 self.assertEqual(td.get_ops, [list, dict])
1283 self.assertEqual(td.set_ops, [dict, list, dict])
1284 self.assertEqual(td.data[dict],
1285 functools._find_impl(dict, g.registry))
1286 self.assertEqual(g(l), "list")
1287 self.assertEqual(len(td), 2)
1288 self.assertEqual(td.get_ops, [list, dict])
1289 self.assertEqual(td.set_ops, [dict, list, dict, list])
1290 self.assertEqual(td.data[list],
1291 functools._find_impl(list, g.registry))
1292 class X:
1293 pass
1294 c.MutableMapping.register(X) # Will not invalidate the cache,
1295 # not using ABCs yet.
1296 self.assertEqual(g(d), "base")
1297 self.assertEqual(g(l), "list")
1298 self.assertEqual(td.get_ops, [list, dict, dict, list])
1299 self.assertEqual(td.set_ops, [dict, list, dict, list])
1300 g.register(c.Sized, lambda arg: "sized")
1301 self.assertEqual(len(td), 0)
1302 self.assertEqual(g(d), "sized")
1303 self.assertEqual(len(td), 1)
1304 self.assertEqual(td.get_ops, [list, dict, dict, list])
1305 self.assertEqual(td.set_ops, [dict, list, dict, list, dict])
1306 self.assertEqual(g(l), "list")
1307 self.assertEqual(len(td), 2)
1308 self.assertEqual(td.get_ops, [list, dict, dict, list])
1309 self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
1310 self.assertEqual(g(l), "list")
1311 self.assertEqual(g(d), "sized")
1312 self.assertEqual(td.get_ops, [list, dict, dict, list, list, dict])
1313 self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
1314 g.dispatch(list)
1315 g.dispatch(dict)
1316 self.assertEqual(td.get_ops, [list, dict, dict, list, list, dict,
1317 list, dict])
1318 self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list])
1319 c.MutableSet.register(X) # Will invalidate the cache.
1320 self.assertEqual(len(td), 2) # Stale cache.
1321 self.assertEqual(g(l), "list")
1322 self.assertEqual(len(td), 1)
1323 g.register(c.MutableMapping, lambda arg: "mutablemapping")
1324 self.assertEqual(len(td), 0)
1325 self.assertEqual(g(d), "mutablemapping")
1326 self.assertEqual(len(td), 1)
1327 self.assertEqual(g(l), "list")
1328 self.assertEqual(len(td), 2)
1329 g.register(dict, lambda arg: "dict")
1330 self.assertEqual(g(d), "dict")
1331 self.assertEqual(g(l), "list")
1332 g._clear_cache()
1333 self.assertEqual(len(td), 0)
1334 functools.WeakKeyDictionary = _orig_wkd
1335
1336
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001337def test_main(verbose=None):
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001338 test_classes = (
Antoine Pitroub5b37142012-11-13 21:35:40 +01001339 TestPartialC,
1340 TestPartialPy,
1341 TestPartialCSubclass,
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001342 TestUpdateWrapper,
Benjamin Peterson9c2930e2010-08-23 17:40:33 +00001343 TestTotalOrdering,
Antoine Pitroub5b37142012-11-13 21:35:40 +01001344 TestCmpToKeyC,
1345 TestCmpToKeyPy,
Guido van Rossum0919a1a2006-08-26 20:49:04 +00001346 TestWraps,
Georg Brandl2e7346a2010-07-31 18:09:23 +00001347 TestReduce,
1348 TestLRU,
Łukasz Langa6f692512013-06-05 12:20:24 +02001349 TestSingleDispatch,
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001350 )
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001351 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001352
1353 # verify reference counting
1354 if verbose and hasattr(sys, "gettotalrefcount"):
1355 import gc
1356 counts = [None] * 5
Guido van Rossum805365e2007-05-07 22:24:25 +00001357 for i in range(len(counts)):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001358 support.run_unittest(*test_classes)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001359 gc.collect()
1360 counts[i] = sys.gettotalrefcount()
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001361 print(counts)
Raymond Hettinger9c323f82005-02-28 19:39:44 +00001362
1363if __name__ == '__main__':
1364 test_main(verbose=True)