blob: ff52755354b187f0c0218e581e3808e59d988447 [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00003import unittest, doctest, operator
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -07004from test.support import TESTFN, forget, unlink
Raymond Hettinger2d32f632009-03-02 21:24:57 +00005import inspect
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Raymond Hettinger426e0522011-01-03 02:12:02 +00007from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger2d32f632009-03-02 21:24:57 +00008from test import mapping_tests
Georg Brandlc28e1fa2008-06-10 19:20:26 +00009import pickle, copy
Raymond Hettinger2d32f632009-03-02 21:24:57 +000010from random import randrange, shuffle
Raymond Hettinger499b2ee2009-05-27 01:53:46 +000011import keyword
12import re
R. David Murray378c0cf2010-02-24 01:46:21 +000013import sys
Raymond Hettinger57d1a882011-02-23 00:46:28 +000014from collections import UserDict
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000015from collections import ChainMap
Raymond Hettinger57d1a882011-02-23 00:46:28 +000016from collections.abc import Hashable, Iterable, Iterator
17from collections.abc import Sized, Container, Callable
18from collections.abc import Set, MutableSet
19from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
20from collections.abc import Sequence, MutableSequence
21from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000022
Raymond Hettinger499e1932011-02-23 07:56:53 +000023
24################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000025### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000026################################################################################
27
28class TestChainMap(unittest.TestCase):
29
30 def test_basics(self):
31 c = ChainMap()
32 c['a'] = 1
33 c['b'] = 2
34 d = c.new_child()
35 d['b'] = 20
36 d['c'] = 30
37 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
38 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
39 self.assertEqual(len(d), 3) # check len
40 for key in 'abc': # check contains
41 self.assertIn(key, d)
42 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
43 self.assertEqual(d.get(k, 100), v)
44
45 del d['b'] # unmask a value
46 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
47 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
48 self.assertEqual(len(d), 3) # check len
49 for key in 'abc': # check contains
50 self.assertIn(key, d)
51 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
52 self.assertEqual(d.get(k, 100), v)
53 self.assertIn(repr(d), [ # check repr
54 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
55 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
56 ])
57
58 for e in d.copy(), copy.copy(d): # check shallow copies
59 self.assertEqual(d, e)
60 self.assertEqual(d.maps, e.maps)
61 self.assertIsNot(d, e)
62 self.assertIsNot(d.maps[0], e.maps[0])
63 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
64 self.assertIs(m1, m2)
65
66 for e in [pickle.loads(pickle.dumps(d)),
67 copy.deepcopy(d),
68 eval(repr(d))
69 ]: # check deep copies
70 self.assertEqual(d, e)
71 self.assertEqual(d.maps, e.maps)
72 self.assertIsNot(d, e)
73 for m1, m2 in zip(d.maps, e.maps):
74 self.assertIsNot(m1, m2, e)
75
Raymond Hettingerd0321312011-02-26 06:53:58 +000076 f = d.new_child()
77 f['b'] = 5
78 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
79 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
80 self.assertEqual(f['b'], 5) # find first in chain
81 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +000082
83 def test_contructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +000084 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +000085 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
86
Raymond Hettingerd0321312011-02-26 06:53:58 +000087 def test_bool(self):
88 self.assertFalse(ChainMap())
89 self.assertFalse(ChainMap({}, {}))
90 self.assertTrue(ChainMap({1:2}, {}))
91 self.assertTrue(ChainMap({}, {1:2}))
92
Raymond Hettinger499e1932011-02-23 07:56:53 +000093 def test_missing(self):
94 class DefaultChainMap(ChainMap):
95 def __missing__(self, key):
96 return 999
97 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
98 for k, v in dict(a=1, b=2, c=30, d=999).items():
99 self.assertEqual(d[k], v) # check __getitem__ w/missing
100 for k, v in dict(a=1, b=2, c=30, d=77).items():
101 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
102 for k, v in dict(a=True, b=True, c=True, d=False).items():
103 self.assertEqual(k in d, v) # check __contains__ w/missing
104 self.assertEqual(d.pop('a', 1001), 1, d)
105 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
106 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
107 with self.assertRaises(KeyError):
108 d.popitem()
109
110 def test_dict_coercion(self):
111 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
112 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
113 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
114
115
116################################################################################
117### Named Tuples
118################################################################################
119
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000120TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000121
122class TestNamedTuple(unittest.TestCase):
123
124 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000125 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000126 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000127 self.assertEqual(Point.__slots__, ())
128 self.assertEqual(Point.__module__, __name__)
129 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000130 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettinger2ebea412011-03-23 12:52:23 -0700131 self.assertIn('class Point(tuple)', Point._source)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000132
133 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
134 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
135 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
136
137 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
138 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
139 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000140 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000141 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
142
143 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000144 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000146 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000147 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000148 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000149 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000150
Christian Heimesfaf2f632008-01-06 16:59:19 +0000151 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
152 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
153
R. David Murray378c0cf2010-02-24 01:46:21 +0000154 @unittest.skipIf(sys.flags.optimize >= 2,
155 "Docstrings are omitted with -O2 and above")
156 def test_factory_doc_attr(self):
157 Point = namedtuple('Point', 'x y')
158 self.assertEqual(Point.__doc__, 'Point(x, y)')
159
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000160 def test_name_fixer(self):
161 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000162 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
163 [('abc', 'class'), ('abc', '_1')], # field has keyword
164 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
165 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
166 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
167 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000168 ]:
169 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
170
Guido van Rossumd8faa362007-04-27 19:54:29 +0000171 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000172 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000173 p = Point(11, 22)
174 self.assertEqual(p, Point(x=11, y=22))
175 self.assertEqual(p, Point(11, y=22))
176 self.assertEqual(p, Point(y=22, x=11))
177 self.assertEqual(p, Point(*(11, 22)))
178 self.assertEqual(p, Point(**dict(x=11, y=22)))
179 self.assertRaises(TypeError, Point, 1) # too few args
180 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
181 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
182 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
183 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000184 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000185 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000186 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
187 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
188 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Raymond Hettinger3d890572011-06-02 23:40:24 -0700189 self.assertEqual(vars(p), p._asdict()) # verify that vars() works
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000190
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000191 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000192 p._replace(x=1, error=2)
193 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000194 pass
195 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000196 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000197
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000198 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000199 Point = namedtuple('Point', 'x, y')
200 p = Point(x=11, y=22)
201 self.assertEqual(repr(p), 'Point(x=11, y=22)')
202
203 # verify that fieldspec can be a non-string sequence
204 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000205 p = Point(x=11, y=22)
206 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000207
208 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000209 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000210 p = Point(11, 22)
211
Ezio Melottie9615932010-01-24 19:26:24 +0000212 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000213 self.assertEqual(p, (11, 22)) # matches a real tuple
214 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
215 self.assertEqual(list(p), [11, 22]) # coercable to a list
216 self.assertEqual(max(p), 22) # iterable
217 self.assertEqual(max(*p), 22) # star-able
218 x, y = p
219 self.assertEqual(p, (x, y)) # unpacks like a tuple
220 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
221 self.assertRaises(IndexError, p.__getitem__, 3)
222
223 self.assertEqual(p.x, x)
224 self.assertEqual(p.y, y)
225 self.assertRaises(AttributeError, eval, 'p.z', locals())
226
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000227 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000228 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000229 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000230 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000231 self.assertEqual(repr(Zero()), 'Zero()')
232 self.assertEqual(Zero()._asdict(), {})
233 self.assertEqual(Zero()._fields, ())
234
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000235 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000236 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000237 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000238 self.assertEqual(Dot(1).d, 1)
239 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
240 self.assertEqual(Dot(1)._asdict(), {'d':1})
241 self.assertEqual(Dot(1)._replace(d=999), (999,))
242 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000243
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000244 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000245 n = 254 # SyntaxError: more than 255 arguments:
246 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000247 names = list(set(''.join([random.choice(string.ascii_letters)
248 for j in range(10)]) for i in range(n)))
249 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000250 Big = namedtuple('Big', names)
251 b = Big(*range(n))
252 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000253 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000254 for pos, name in enumerate(names):
255 self.assertEqual(getattr(b, name), pos)
256 repr(b) # make sure repr() doesn't blow-up
257 d = b._asdict()
258 d_expected = dict(zip(names, range(n)))
259 self.assertEqual(d, d_expected)
260 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
261 b2_expected = list(range(n))
262 b2_expected[1] = 999
263 b2_expected[-5] = 42
264 self.assertEqual(b2, tuple(b2_expected))
265 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000266
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000267 def test_pickle(self):
268 p = TestNT(x=10, y=20, z=30)
269 for module in (pickle,):
270 loads = getattr(module, 'loads')
271 dumps = getattr(module, 'dumps')
272 for protocol in -1, 0, 1, 2:
273 q = loads(dumps(p, protocol))
274 self.assertEqual(p, q)
275 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700276 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000277
278 def test_copy(self):
279 p = TestNT(x=10, y=20, z=30)
280 for copier in copy.copy, copy.deepcopy:
281 q = copier(p)
282 self.assertEqual(p, q)
283 self.assertEqual(p._fields, q._fields)
284
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000285 def test_name_conflicts(self):
286 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
287 # failed when used as field names. Test to make sure these now work.
288 T = namedtuple('T', 'itemgetter property self cls tuple')
289 t = T(1, 2, 3, 4, 5)
290 self.assertEqual(t, (1,2,3,4,5))
291 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
292 self.assertEqual(newt, (10,20,30,40,50))
293
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000294 # Broader test of all interesting names in a template
295 with support.captured_stdout() as template:
296 T = namedtuple('T', 'x', verbose=True)
297 words = set(re.findall('[A-Za-z]+', template.getvalue()))
298 words -= set(keyword.kwlist)
299 T = namedtuple('T', words)
300 # test __new__
301 values = tuple(range(len(words)))
302 t = T(*values)
303 self.assertEqual(t, values)
304 t = T(**dict(zip(T._fields, values)))
305 self.assertEqual(t, values)
306 # test _make
307 t = T._make(values)
308 self.assertEqual(t, values)
309 # exercise __repr__
310 repr(t)
311 # test _asdict
312 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
313 # test _replace
314 t = T._make(values)
315 newvalues = tuple(v*10 for v in values)
316 newt = t._replace(**dict(zip(T._fields, newvalues)))
317 self.assertEqual(newt, newvalues)
318 # test _fields
319 self.assertEqual(T._fields, tuple(words))
320 # test __getnewargs__
321 self.assertEqual(t.__getnewargs__(), values)
322
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000323 def test_repr(self):
324 with support.captured_stdout() as template:
325 A = namedtuple('A', 'x', verbose=True)
326 self.assertEqual(repr(A(1)), 'A(x=1)')
327 # repr should show the name of the subclass
328 class B(A):
329 pass
330 self.assertEqual(repr(B(1)), 'B(x=1)')
331
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700332 def test_source(self):
333 # verify that _source can be run through exec()
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700334 tmp = namedtuple('NTColor', 'red green blue')
335 globals().pop('NTColor', None) # remove artifacts from other tests
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700336 exec(tmp._source, globals())
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700337 self.assertIn('NTColor', globals())
338 c = NTColor(10, 20, 30)
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700339 self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700340 self.assertEqual(NTColor._fields, ('red', 'green', 'blue'))
341 globals().pop('NTColor', None) # clean-up after this test
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700342
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000343
Raymond Hettinger499e1932011-02-23 07:56:53 +0000344################################################################################
345### Abstract Base Classes
346################################################################################
347
Raymond Hettingerae650182009-01-28 23:33:59 +0000348class ABCTestCase(unittest.TestCase):
349
350 def validate_abstract_methods(self, abc, *names):
351 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
352
353 # everything should work will all required methods are present
354 C = type('C', (abc,), methodstubs)
355 C()
356
357 # instantiation should fail if a required method is missing
358 for name in names:
359 stubs = methodstubs.copy()
360 del stubs[name]
361 C = type('C', (abc,), stubs)
362 self.assertRaises(TypeError, C, name)
363
Florent Xiclunace153f62010-03-08 15:34:35 +0000364 def validate_isinstance(self, abc, name):
365 stub = lambda s, *args: 0
366
367 C = type('C', (object,), {'__hash__': None})
368 setattr(C, name, stub)
369 self.assertIsInstance(C(), abc)
370 self.assertTrue(issubclass(C, abc))
371
372 C = type('C', (object,), {'__hash__': None})
373 self.assertNotIsInstance(C(), abc)
374 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000375
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000376 def validate_comparison(self, instance):
377 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
378 operators = {}
379 for op in ops:
380 name = '__' + op + '__'
381 operators[name] = getattr(operator, name)
382
383 class Other:
384 def __init__(self):
385 self.right_side = False
386 def __eq__(self, other):
387 self.right_side = True
388 return True
389 __lt__ = __eq__
390 __gt__ = __eq__
391 __le__ = __eq__
392 __ge__ = __eq__
393 __ne__ = __eq__
394 __ror__ = __eq__
395 __rand__ = __eq__
396 __rxor__ = __eq__
397 __rsub__ = __eq__
398
399 for name, op in operators.items():
400 if not hasattr(instance, name):
401 continue
402 other = Other()
403 op(instance, other)
404 self.assertTrue(other.right_side,'Right side not called for %s.%s'
405 % (type(instance), name))
406
Raymond Hettingerae650182009-01-28 23:33:59 +0000407class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000408
409 def test_Hashable(self):
410 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000411 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000412 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000413 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000414 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000415 # Check some hashables
416 samples = [None,
417 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000418 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000419 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000420 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000421 ]
422 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000423 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000424 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000425 self.assertRaises(TypeError, Hashable)
426 # Check direct subclassing
427 class H(Hashable):
428 def __hash__(self):
429 return super().__hash__()
430 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000431 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000432 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000433 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000434
435 def test_Iterable(self):
436 # Check some non-iterables
437 non_samples = [None, 42, 3.14, 1j]
438 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000439 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000440 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000441 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000442 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000443 tuple(), list(), set(), frozenset(), dict(),
444 dict().keys(), dict().items(), dict().values(),
445 (lambda: (yield))(),
446 (x for x in []),
447 ]
448 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000449 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000450 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000451 # Check direct subclassing
452 class I(Iterable):
453 def __iter__(self):
454 return super().__iter__()
455 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000456 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000457 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000458 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000459
460 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000461 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000462 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000463 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000464 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000465 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000466 iter(tuple()), iter(list()), iter(dict()),
467 iter(set()), iter(frozenset()),
468 iter(dict().keys()), iter(dict().items()),
469 iter(dict().values()),
470 (lambda: (yield))(),
471 (x for x in []),
472 ]
473 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000474 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000475 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000476 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
477
478 # Issue 10565
479 class NextOnly:
480 def __next__(self):
481 yield 1
482 raise StopIteration
483 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000484
485 def test_Sized(self):
486 non_samples = [None, 42, 3.14, 1j,
487 (lambda: (yield))(),
488 (x for x in []),
489 ]
490 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000491 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000492 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000493 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000494 tuple(), list(), set(), frozenset(), dict(),
495 dict().keys(), dict().items(), dict().values(),
496 ]
497 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000498 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000499 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000500 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000501 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000502
503 def test_Container(self):
504 non_samples = [None, 42, 3.14, 1j,
505 (lambda: (yield))(),
506 (x for x in []),
507 ]
508 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000509 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000510 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000511 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000512 tuple(), list(), set(), frozenset(), dict(),
513 dict().keys(), dict().items(),
514 ]
515 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000516 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000517 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000518 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000519 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000520
521 def test_Callable(self):
522 non_samples = [None, 42, 3.14, 1j,
523 "", b"", (), [], {}, set(),
524 (lambda: (yield))(),
525 (x for x in []),
526 ]
527 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000528 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000529 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000530 samples = [lambda: None,
531 type, int, object,
532 len,
533 list.append, [].append,
534 ]
535 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000536 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000537 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000538 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000539 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000540
541 def test_direct_subclassing(self):
542 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
543 class C(B):
544 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000545 self.assertTrue(issubclass(C, B))
546 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000547
548 def test_registration(self):
549 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
550 class C:
551 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000552 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000553 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000554 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000555
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000556class WithSet(MutableSet):
557
558 def __init__(self, it=()):
559 self.data = set(it)
560
561 def __len__(self):
562 return len(self.data)
563
564 def __iter__(self):
565 return iter(self.data)
566
567 def __contains__(self, item):
568 return item in self.data
569
570 def add(self, item):
571 self.data.add(item)
572
573 def discard(self, item):
574 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000575
Raymond Hettingerae650182009-01-28 23:33:59 +0000576class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000577
578 # XXX For now, we only test some virtual inheritance properties.
579 # We should also test the proper behavior of the collection ABCs
580 # as real base classes or mix-in classes.
581
582 def test_Set(self):
583 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000584 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000585 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000586 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000587 class MySet(Set):
588 def __contains__(self, x):
589 return False
590 def __len__(self):
591 return 0
592 def __iter__(self):
593 return iter([])
594 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000595
Benjamin Peterson41181742008-07-02 20:22:54 +0000596 def test_hash_Set(self):
597 class OneTwoThreeSet(Set):
598 def __init__(self):
599 self.contents = [1, 2, 3]
600 def __contains__(self, x):
601 return x in self.contents
602 def __len__(self):
603 return len(self.contents)
604 def __iter__(self):
605 return iter(self.contents)
606 def __hash__(self):
607 return self._hash()
608 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000609 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000610
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000611 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000612 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000613 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000614 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000615 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000616 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
617 'add', 'discard')
618
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000619 def test_issue_5647(self):
620 # MutableSet.__iand__ mutated the set during iteration
621 s = WithSet('abcd')
622 s &= WithSet('cdef') # This used to fail
623 self.assertEqual(set(s), set('cd'))
624
Raymond Hettingerae650182009-01-28 23:33:59 +0000625 def test_issue_4920(self):
626 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000627 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000628 __slots__=['__s']
629 def __init__(self,items=None):
630 if items is None:
631 items=[]
632 self.__s=set(items)
633 def __contains__(self,v):
634 return v in self.__s
635 def __iter__(self):
636 return iter(self.__s)
637 def __len__(self):
638 return len(self.__s)
639 def add(self,v):
640 result=v not in self.__s
641 self.__s.add(v)
642 return result
643 def discard(self,v):
644 result=v in self.__s
645 self.__s.discard(v)
646 return result
647 def __repr__(self):
648 return "MySet(%s)" % repr(list(self))
649 s = MySet([5,43,2,1])
650 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000651
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000652 def test_issue8750(self):
653 empty = WithSet()
654 full = WithSet(range(10))
655 s = WithSet(full)
656 s -= s
657 self.assertEqual(s, empty)
658 s = WithSet(full)
659 s ^= s
660 self.assertEqual(s, empty)
661 s = WithSet(full)
662 s &= s
663 self.assertEqual(s, full)
664 s |= s
665 self.assertEqual(s, full)
666
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200667 def test_issue16373(self):
668 # Recursion error comparing comparable and noncomparable
669 # Set instances
670 class MyComparableSet(Set):
671 def __contains__(self, x):
672 return False
673 def __len__(self):
674 return 0
675 def __iter__(self):
676 return iter([])
677 class MyNonComparableSet(Set):
678 def __contains__(self, x):
679 return False
680 def __len__(self):
681 return 0
682 def __iter__(self):
683 return iter([])
684 def __le__(self, x):
685 return NotImplemented
686 def __lt__(self, x):
687 return NotImplemented
688
689 cs = MyComparableSet()
690 ncs = MyNonComparableSet()
691 with self.assertRaises(TypeError):
692 ncs < cs
693 with self.assertRaises(TypeError):
694 ncs <= cs
695 with self.assertRaises(TypeError):
696 cs > ncs
697 with self.assertRaises(TypeError):
698 cs >= ncs
699
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000700 def test_Mapping(self):
701 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000702 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000703 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000704 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
705 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000706 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000707 def __len__(self):
708 return 0
709 def __getitem__(self, i):
710 raise IndexError
711 def __iter__(self):
712 return iter(())
713 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000714
715 def test_MutableMapping(self):
716 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000717 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000718 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000719 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
720 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000721
Raymond Hettinger9117c752010-08-22 07:44:24 +0000722 def test_MutableMapping_subclass(self):
723 # Test issue 9214
724 mymap = UserDict()
725 mymap['red'] = 5
726 self.assertIsInstance(mymap.keys(), Set)
727 self.assertIsInstance(mymap.keys(), KeysView)
728 self.assertIsInstance(mymap.items(), Set)
729 self.assertIsInstance(mymap.items(), ItemsView)
730
731 mymap = UserDict()
732 mymap['red'] = 5
733 z = mymap.keys() | {'orange'}
734 self.assertIsInstance(z, set)
735 list(z)
736 mymap['blue'] = 7 # Shouldn't affect 'z'
737 self.assertEqual(sorted(z), ['orange', 'red'])
738
739 mymap = UserDict()
740 mymap['red'] = 5
741 z = mymap.items() | {('orange', 3)}
742 self.assertIsInstance(z, set)
743 list(z)
744 mymap['blue'] = 7 # Shouldn't affect 'z'
745 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
746
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000747 def test_Sequence(self):
748 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000749 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000750 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000751 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000752 self.assertTrue(issubclass(range, Sequence))
753 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000754 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
755 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000756
Guido van Rossumd05eb002007-11-21 22:26:24 +0000757 def test_ByteString(self):
758 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000759 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000760 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000761 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000762 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000763 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000764 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000765 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000766
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000767 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000768 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000769 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000770 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000771 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000772 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000773 self.assertTrue(issubclass(sample, MutableSequence))
774 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000775 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
776 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000777
Eli Bendersky0716a572011-03-04 10:38:14 +0000778 def test_MutableSequence_mixins(self):
779 # Test the mixins of MutableSequence by creating a miminal concrete
780 # class inherited from it.
781 class MutableSequenceSubclass(MutableSequence):
782 def __init__(self):
783 self.lst = []
784
785 def __setitem__(self, index, value):
786 self.lst[index] = value
787
788 def __getitem__(self, index):
789 return self.lst[index]
790
791 def __len__(self):
792 return len(self.lst)
793
794 def __delitem__(self, index):
795 del self.lst[index]
796
797 def insert(self, index, value):
798 self.lst.insert(index, value)
799
800 mss = MutableSequenceSubclass()
801 mss.append(0)
802 mss.extend((1, 2, 3, 4))
803 self.assertEqual(len(mss), 5)
804 self.assertEqual(mss[3], 3)
805 mss.reverse()
806 self.assertEqual(mss[3], 1)
807 mss.pop()
808 self.assertEqual(len(mss), 4)
809 mss.remove(3)
810 self.assertEqual(len(mss), 3)
811 mss += (10, 20, 30)
812 self.assertEqual(len(mss), 6)
813 self.assertEqual(mss[-1], 30)
814 mss.clear()
815 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +0000816
817################################################################################
818### Counter
819################################################################################
820
Raymond Hettingercb1d96f2013-10-04 16:51:02 -0700821class CounterSubclassWithSetItem(Counter):
822 # Test a counter subclass that overrides __setitem__
823 def __init__(self, *args, **kwds):
824 self.called = False
825 Counter.__init__(self, *args, **kwds)
826 def __setitem__(self, key, value):
827 self.called = True
828 Counter.__setitem__(self, key, value)
829
830class CounterSubclassWithGet(Counter):
831 # Test a counter subclass that overrides get()
832 def __init__(self, *args, **kwds):
833 self.called = False
834 Counter.__init__(self, *args, **kwds)
835 def get(self, key, default):
836 self.called = True
837 return Counter.get(self, key, default)
838
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000839class TestCounter(unittest.TestCase):
840
841 def test_basics(self):
842 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000843 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
844 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +0000845 self.assertIsInstance(c, dict)
846 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000847 self.assertTrue(issubclass(Counter, dict))
848 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000849 self.assertEqual(len(c), 3)
850 self.assertEqual(sum(c.values()), 6)
851 self.assertEqual(sorted(c.values()), [1, 2, 3])
852 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
853 self.assertEqual(sorted(c), ['a', 'b', 'c'])
854 self.assertEqual(sorted(c.items()),
855 [('a', 3), ('b', 2), ('c', 1)])
856 self.assertEqual(c['b'], 2)
857 self.assertEqual(c['z'], 0)
858 self.assertEqual(c.__contains__('c'), True)
859 self.assertEqual(c.__contains__('z'), False)
860 self.assertEqual(c.get('b', 10), 2)
861 self.assertEqual(c.get('z', 10), 10)
862 self.assertEqual(c, dict(a=3, b=2, c=1))
863 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
864 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
865 for i in range(5):
866 self.assertEqual(c.most_common(i),
867 [('a', 3), ('b', 2), ('c', 1)][:i])
868 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
869 c['a'] += 1 # increment an existing value
870 c['b'] -= 2 # sub existing value to zero
871 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000872 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000873 c['d'] -= 2 # sub from a missing value
874 c['e'] = -5 # directly assign a missing value
875 c['f'] += 4 # add to a missing value
876 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
877 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
878 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000879 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000880 for i in range(3):
881 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000882 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000883 c.clear()
884 self.assertEqual(c, {})
885 self.assertEqual(repr(c), 'Counter()')
886 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
887 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000888 c.update(dict(a=5, b=3))
889 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000890 c.update(Counter('a' * 50 + 'b' * 30))
891 c.update() # test case with no args
892 c.__init__('a' * 500 + 'b' * 300)
893 c.__init__('cdc')
894 c.__init__()
895 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
896 self.assertEqual(c.setdefault('d', 5), 1)
897 self.assertEqual(c['d'], 1)
898 self.assertEqual(c.setdefault('e', 5), 5)
899 self.assertEqual(c['e'], 5)
900
901 def test_copying(self):
902 # Check that counters are copyable, deepcopyable, picklable, and
903 #have a repr/eval round-trip
904 words = Counter('which witch had which witches wrist watch'.split())
905 update_test = Counter()
906 update_test.update(words)
907 for i, dup in enumerate([
908 words.copy(),
909 copy.copy(words),
910 copy.deepcopy(words),
911 pickle.loads(pickle.dumps(words, 0)),
912 pickle.loads(pickle.dumps(words, 1)),
913 pickle.loads(pickle.dumps(words, 2)),
914 pickle.loads(pickle.dumps(words, -1)),
915 eval(repr(words)),
916 update_test,
917 Counter(words),
918 ]):
919 msg = (i, dup, words)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000920 self.assertTrue(dup is not words)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000921 self.assertEqual(dup, words)
922 self.assertEqual(len(dup), len(words))
923 self.assertEqual(type(dup), type(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000924
Raymond Hettinger1c746c22011-04-15 13:16:46 -0700925 def test_copy_subclass(self):
926 class MyCounter(Counter):
927 pass
928 c = MyCounter('slartibartfast')
929 d = c.copy()
930 self.assertEqual(d, c)
931 self.assertEqual(len(d), len(c))
932 self.assertEqual(type(d), type(c))
933
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000934 def test_conversions(self):
935 # Convert to: set, list, dict
936 s = 'she sells sea shells by the sea shore'
937 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
938 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
939 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
940 self.assertEqual(set(Counter(s)), set(s))
941
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000942 def test_invariant_for_the_in_operator(self):
943 c = Counter(a=10, b=-2, c=0)
944 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000945 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000946 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000947
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000948 def test_multiset_operations(self):
949 # Verify that adding a zero counter will strip zeros and negatives
950 c = Counter(a=10, b=-2, c=0) + Counter()
951 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000952
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000953 elements = 'abcd'
954 for i in range(1000):
955 # test random pairs of multisets
956 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000957 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000958 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000959 q.update(h=1, i=-1, j=0)
960 for counterop, numberop in [
961 (Counter.__add__, lambda x, y: max(0, x+y)),
962 (Counter.__sub__, lambda x, y: max(0, x-y)),
963 (Counter.__or__, lambda x, y: max(0,x,y)),
964 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000965 ]:
966 result = counterop(p, q)
967 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000968 self.assertEqual(numberop(p[x], q[x]), result[x],
969 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000970 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000971 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000972
973 elements = 'abcdef'
974 for i in range(100):
975 # verify that random multisets with no repeats are exactly like sets
976 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
977 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
978 for counterop, setop in [
979 (Counter.__sub__, set.__sub__),
980 (Counter.__or__, set.__or__),
981 (Counter.__and__, set.__and__),
982 ]:
983 counter_result = counterop(p, q)
984 set_result = setop(set(p.elements()), set(q.elements()))
985 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000986
Raymond Hettingerbecd5682011-10-19 13:40:37 -0700987 def test_inplace_operations(self):
988 elements = 'abcd'
989 for i in range(1000):
990 # test random pairs of multisets
991 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
992 p.update(e=1, f=-1, g=0)
993 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
994 q.update(h=1, i=-1, j=0)
995 for inplace_op, regular_op in [
996 (Counter.__iadd__, Counter.__add__),
997 (Counter.__isub__, Counter.__sub__),
998 (Counter.__ior__, Counter.__or__),
999 (Counter.__iand__, Counter.__and__),
1000 ]:
1001 c = p.copy()
1002 c_id = id(c)
1003 regular_result = regular_op(c, q)
1004 inplace_result = inplace_op(c, q)
1005 self.assertEqual(inplace_result, regular_result)
1006 self.assertEqual(id(inplace_result), c_id)
1007
Raymond Hettinger9c01e442010-04-03 10:32:58 +00001008 def test_subtract(self):
1009 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1010 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
1011 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1012 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1013 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
1014 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1015 c = Counter('aaabbcd')
1016 c.subtract('aaaabbcce')
1017 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001018
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07001019 def test_unary(self):
1020 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1021 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
1022 self.assertEqual(dict(-c), dict(a=5))
1023
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07001024 def test_repr_nonsortable(self):
1025 c = Counter(a=2, b=None)
1026 r = repr(c)
1027 self.assertIn("'a': 2", r)
1028 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07001029
Raymond Hettinger426e0522011-01-03 02:12:02 +00001030 def test_helper_function(self):
1031 # two paths, one for real dicts and one for other mappings
1032 elems = list('abracadabra')
1033
1034 d = dict()
1035 _count_elements(d, elems)
1036 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1037
1038 m = OrderedDict()
1039 _count_elements(m, elems)
1040 self.assertEqual(m,
1041 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
1042
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001043 # test fidelity to the pure python version
1044 c = CounterSubclassWithSetItem('abracadabra')
1045 self.assertTrue(c.called)
1046 c = CounterSubclassWithGet('abracadabra')
1047 self.assertTrue(c.called)
1048
Raymond Hettinger499e1932011-02-23 07:56:53 +00001049
1050################################################################################
1051### OrderedDict
1052################################################################################
1053
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001054class TestOrderedDict(unittest.TestCase):
1055
1056 def test_init(self):
1057 with self.assertRaises(TypeError):
1058 OrderedDict([('a', 1), ('b', 2)], None) # too many args
1059 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1060 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
1061 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
1062 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
1063 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
1064 c=3, e=5).items()), pairs) # mixed input
1065
1066 # make sure no positional args conflict with possible kwdargs
1067 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
1068 ['self'])
1069
1070 # Make sure that direct calls to __init__ do not clear previous contents
1071 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1072 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
1073 self.assertEqual(list(d.items()),
1074 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1075
1076 def test_update(self):
1077 with self.assertRaises(TypeError):
1078 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
1079 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1080 od = OrderedDict()
1081 od.update(dict(pairs))
1082 self.assertEqual(sorted(od.items()), pairs) # dict input
1083 od = OrderedDict()
1084 od.update(**dict(pairs))
1085 self.assertEqual(sorted(od.items()), pairs) # kwds input
1086 od = OrderedDict()
1087 od.update(pairs)
1088 self.assertEqual(list(od.items()), pairs) # pairs input
1089 od = OrderedDict()
1090 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1091 self.assertEqual(list(od.items()), pairs) # mixed input
1092
Mark Dickinsonb214e902010-07-11 18:53:06 +00001093 # Issue 9137: Named argument called 'other' or 'self'
1094 # shouldn't be treated specially.
1095 od = OrderedDict()
1096 od.update(self=23)
1097 self.assertEqual(list(od.items()), [('self', 23)])
1098 od = OrderedDict()
1099 od.update(other={})
1100 self.assertEqual(list(od.items()), [('other', {})])
1101 od = OrderedDict()
1102 od.update(red=5, blue=6, other=7, self=8)
1103 self.assertEqual(sorted(list(od.items())),
1104 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
1105
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001106 # Make sure that direct calls to update do not clear previous contents
1107 # add that updates items are not moved to the end
1108 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1109 d.update([('e', 5), ('f', 6)], g=7, d=4)
1110 self.assertEqual(list(d.items()),
1111 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1112
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001113 def test_abc(self):
1114 self.assertIsInstance(OrderedDict(), MutableMapping)
1115 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1116
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001117 def test_clear(self):
1118 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1119 shuffle(pairs)
1120 od = OrderedDict(pairs)
1121 self.assertEqual(len(od), len(pairs))
1122 od.clear()
1123 self.assertEqual(len(od), 0)
1124
1125 def test_delitem(self):
1126 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1127 od = OrderedDict(pairs)
1128 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001129 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001130 with self.assertRaises(KeyError):
1131 del od['a']
1132 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1133
1134 def test_setitem(self):
1135 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1136 od['c'] = 10 # existing element
1137 od['f'] = 20 # new element
1138 self.assertEqual(list(od.items()),
1139 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1140
1141 def test_iterators(self):
1142 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1143 shuffle(pairs)
1144 od = OrderedDict(pairs)
1145 self.assertEqual(list(od), [t[0] for t in pairs])
1146 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1147 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1148 self.assertEqual(list(od.items()), pairs)
1149 self.assertEqual(list(reversed(od)),
1150 [t[0] for t in reversed(pairs)])
1151
1152 def test_popitem(self):
1153 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1154 shuffle(pairs)
1155 od = OrderedDict(pairs)
1156 while pairs:
1157 self.assertEqual(od.popitem(), pairs.pop())
1158 with self.assertRaises(KeyError):
1159 od.popitem()
1160 self.assertEqual(len(od), 0)
1161
1162 def test_pop(self):
1163 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1164 shuffle(pairs)
1165 od = OrderedDict(pairs)
1166 shuffle(pairs)
1167 while pairs:
1168 k, v = pairs.pop()
1169 self.assertEqual(od.pop(k), v)
1170 with self.assertRaises(KeyError):
1171 od.pop('xyz')
1172 self.assertEqual(len(od), 0)
1173 self.assertEqual(od.pop(k, 12345), 12345)
1174
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001175 # make sure pop still works when __missing__ is defined
1176 class Missing(OrderedDict):
1177 def __missing__(self, key):
1178 return 0
1179 m = Missing(a=1)
1180 self.assertEqual(m.pop('b', 5), 5)
1181 self.assertEqual(m.pop('a', 6), 1)
1182 self.assertEqual(m.pop('a', 6), 6)
1183 with self.assertRaises(KeyError):
1184 m.pop('a')
1185
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001186 def test_equality(self):
1187 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1188 shuffle(pairs)
1189 od1 = OrderedDict(pairs)
1190 od2 = OrderedDict(pairs)
1191 self.assertEqual(od1, od2) # same order implies equality
1192 pairs = pairs[2:] + pairs[:2]
1193 od2 = OrderedDict(pairs)
1194 self.assertNotEqual(od1, od2) # different order implies inequality
1195 # comparison to regular dict is not order sensitive
1196 self.assertEqual(od1, dict(od2))
1197 self.assertEqual(dict(od2), od1)
1198 # different length implied inequality
1199 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1200
1201 def test_copying(self):
1202 # Check that ordered dicts are copyable, deepcopyable, picklable,
1203 # and have a repr/eval round-trip
1204 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1205 od = OrderedDict(pairs)
1206 update_test = OrderedDict()
1207 update_test.update(od)
1208 for i, dup in enumerate([
1209 od.copy(),
1210 copy.copy(od),
1211 copy.deepcopy(od),
1212 pickle.loads(pickle.dumps(od, 0)),
1213 pickle.loads(pickle.dumps(od, 1)),
1214 pickle.loads(pickle.dumps(od, 2)),
1215 pickle.loads(pickle.dumps(od, 3)),
1216 pickle.loads(pickle.dumps(od, -1)),
1217 eval(repr(od)),
1218 update_test,
1219 OrderedDict(od),
1220 ]):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001221 self.assertTrue(dup is not od)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001222 self.assertEqual(dup, od)
1223 self.assertEqual(list(dup.items()), list(od.items()))
1224 self.assertEqual(len(dup), len(od))
1225 self.assertEqual(type(dup), type(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001226
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001227 def test_yaml_linkage(self):
1228 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1229 # In yaml, lists are native but tuples are not.
1230 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1231 od = OrderedDict(pairs)
1232 # yaml.dump(od) -->
1233 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001234 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001235
Raymond Hettingerb2121572009-03-03 22:50:04 +00001236 def test_reduce_not_too_fat(self):
1237 # do not save instance dictionary if not needed
1238 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1239 od = OrderedDict(pairs)
1240 self.assertEqual(len(od.__reduce__()), 2)
1241 od.x = 10
1242 self.assertEqual(len(od.__reduce__()), 3)
1243
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001244 def test_repr(self):
1245 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1246 self.assertEqual(repr(od),
1247 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1248 self.assertEqual(eval(repr(od)), od)
1249 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1250
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001251 def test_repr_recursive(self):
1252 # See issue #9826
1253 od = OrderedDict.fromkeys('abc')
1254 od['x'] = od
1255 self.assertEqual(repr(od),
1256 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1257
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001258 def test_setdefault(self):
1259 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1260 shuffle(pairs)
1261 od = OrderedDict(pairs)
1262 pair_order = list(od.items())
1263 self.assertEqual(od.setdefault('a', 10), 3)
1264 # make sure order didn't change
1265 self.assertEqual(list(od.items()), pair_order)
1266 self.assertEqual(od.setdefault('x', 10), 10)
1267 # make sure 'x' is added to the end
1268 self.assertEqual(list(od.items())[-1], ('x', 10))
1269
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001270 # make sure setdefault still works when __missing__ is defined
1271 class Missing(OrderedDict):
1272 def __missing__(self, key):
1273 return 0
1274 self.assertEqual(Missing().setdefault(5, 9), 9)
1275
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001276 def test_reinsert(self):
1277 # Given insert a, insert b, delete a, re-insert a,
1278 # verify that a is now later than b.
1279 od = OrderedDict()
1280 od['a'] = 1
1281 od['b'] = 2
1282 del od['a']
1283 od['a'] = 1
1284 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1285
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001286 def test_move_to_end(self):
1287 od = OrderedDict.fromkeys('abcde')
1288 self.assertEqual(list(od), list('abcde'))
1289 od.move_to_end('c')
1290 self.assertEqual(list(od), list('abdec'))
1291 od.move_to_end('c', 0)
1292 self.assertEqual(list(od), list('cabde'))
1293 od.move_to_end('c', 0)
1294 self.assertEqual(list(od), list('cabde'))
1295 od.move_to_end('e')
1296 self.assertEqual(list(od), list('cabde'))
1297 with self.assertRaises(KeyError):
1298 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001299
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001300 def test_sizeof(self):
1301 # Wimpy test: Just verify the reported size is larger than a regular dict
1302 d = dict(a=1)
1303 od = OrderedDict(**d)
1304 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1305
Raymond Hettinger32062e92011-01-01 22:38:00 +00001306 def test_override_update(self):
1307 # Verify that subclasses can override update() without breaking __init__()
1308 class MyOD(OrderedDict):
1309 def update(self, *args, **kwds):
1310 raise Exception()
1311 items = [('a', 1), ('c', 3), ('b', 2)]
1312 self.assertEqual(list(MyOD(items).items()), items)
1313
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001314class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1315 type2test = OrderedDict
1316
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001317 def test_popitem(self):
1318 d = self._empty_mapping()
1319 self.assertRaises(KeyError, d.popitem)
1320
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001321class MyOrderedDict(OrderedDict):
1322 pass
1323
1324class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1325 type2test = MyOrderedDict
1326
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001327 def test_popitem(self):
1328 d = self._empty_mapping()
1329 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001330
1331
Raymond Hettinger499e1932011-02-23 07:56:53 +00001332################################################################################
1333### Run tests
1334################################################################################
1335
Christian Heimes25bb7832008-01-11 16:17:00 +00001336import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001337
Guido van Rossumd8faa362007-04-27 19:54:29 +00001338def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001339 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001340 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001341 TestCollectionABCs, TestCounter, TestChainMap,
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001342 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001343 support.run_unittest(*test_classes)
1344 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001345
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001346
Guido van Rossumd8faa362007-04-27 19:54:29 +00001347if __name__ == "__main__":
1348 test_main(verbose=True)