blob: bb1150084efa13cfd416a55acce5e564e02a79fc [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 Hettinger2d32f632009-03-02 21:24:57 +00004import inspect
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005from test import support
Raymond Hettinger426e0522011-01-03 02:12:02 +00006from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger2d32f632009-03-02 21:24:57 +00007from test import mapping_tests
Georg Brandlc28e1fa2008-06-10 19:20:26 +00008import pickle, copy
Raymond Hettinger2d32f632009-03-02 21:24:57 +00009from random import randrange, shuffle
Raymond Hettinger499b2ee2009-05-27 01:53:46 +000010import keyword
11import re
R. David Murray378c0cf2010-02-24 01:46:21 +000012import sys
Raymond Hettinger57d1a882011-02-23 00:46:28 +000013from collections import UserDict
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000014from collections import ChainMap
Raymond Hettinger57d1a882011-02-23 00:46:28 +000015from collections.abc import Hashable, Iterable, Iterator
16from collections.abc import Sized, Container, Callable
17from collections.abc import Set, MutableSet
18from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
19from collections.abc import Sequence, MutableSequence
20from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000021
Raymond Hettinger499e1932011-02-23 07:56:53 +000022
23################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000024### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000025################################################################################
26
27class TestChainMap(unittest.TestCase):
28
29 def test_basics(self):
30 c = ChainMap()
31 c['a'] = 1
32 c['b'] = 2
33 d = c.new_child()
34 d['b'] = 20
35 d['c'] = 30
36 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
37 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
38 self.assertEqual(len(d), 3) # check len
39 for key in 'abc': # check contains
40 self.assertIn(key, d)
41 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
42 self.assertEqual(d.get(k, 100), v)
43
44 del d['b'] # unmask a value
45 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
46 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
47 self.assertEqual(len(d), 3) # check len
48 for key in 'abc': # check contains
49 self.assertIn(key, d)
50 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
51 self.assertEqual(d.get(k, 100), v)
52 self.assertIn(repr(d), [ # check repr
53 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
54 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
55 ])
56
57 for e in d.copy(), copy.copy(d): # check shallow copies
58 self.assertEqual(d, e)
59 self.assertEqual(d.maps, e.maps)
60 self.assertIsNot(d, e)
61 self.assertIsNot(d.maps[0], e.maps[0])
62 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
63 self.assertIs(m1, m2)
64
65 for e in [pickle.loads(pickle.dumps(d)),
66 copy.deepcopy(d),
67 eval(repr(d))
68 ]: # check deep copies
69 self.assertEqual(d, e)
70 self.assertEqual(d.maps, e.maps)
71 self.assertIsNot(d, e)
72 for m1, m2 in zip(d.maps, e.maps):
73 self.assertIsNot(m1, m2, e)
74
Raymond Hettingerd0321312011-02-26 06:53:58 +000075 f = d.new_child()
76 f['b'] = 5
77 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
78 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
79 self.assertEqual(f['b'], 5) # find first in chain
80 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +000081
82 def test_contructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +000083 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +000084 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
85
Raymond Hettingerd0321312011-02-26 06:53:58 +000086 def test_bool(self):
87 self.assertFalse(ChainMap())
88 self.assertFalse(ChainMap({}, {}))
89 self.assertTrue(ChainMap({1:2}, {}))
90 self.assertTrue(ChainMap({}, {1:2}))
91
Raymond Hettinger499e1932011-02-23 07:56:53 +000092 def test_missing(self):
93 class DefaultChainMap(ChainMap):
94 def __missing__(self, key):
95 return 999
96 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
97 for k, v in dict(a=1, b=2, c=30, d=999).items():
98 self.assertEqual(d[k], v) # check __getitem__ w/missing
99 for k, v in dict(a=1, b=2, c=30, d=77).items():
100 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
101 for k, v in dict(a=True, b=True, c=True, d=False).items():
102 self.assertEqual(k in d, v) # check __contains__ w/missing
103 self.assertEqual(d.pop('a', 1001), 1, d)
104 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
105 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
106 with self.assertRaises(KeyError):
107 d.popitem()
108
109 def test_dict_coercion(self):
110 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
111 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
112 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
113
114
115################################################################################
116### Named Tuples
117################################################################################
118
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000119TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000120
121class TestNamedTuple(unittest.TestCase):
122
123 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000124 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000125 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000126 self.assertEqual(Point.__slots__, ())
127 self.assertEqual(Point.__module__, __name__)
128 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000129 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000130
131 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
132 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
133 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
134
135 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
136 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
137 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000138 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000139 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
140
141 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000142 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000143
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000144 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000145 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000146 nt = namedtuple('nt', ('the', 'quick')) # 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
Christian Heimesfaf2f632008-01-06 16:59:19 +0000149 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
150 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
151
R. David Murray378c0cf2010-02-24 01:46:21 +0000152 @unittest.skipIf(sys.flags.optimize >= 2,
153 "Docstrings are omitted with -O2 and above")
154 def test_factory_doc_attr(self):
155 Point = namedtuple('Point', 'x y')
156 self.assertEqual(Point.__doc__, 'Point(x, y)')
157
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000158 def test_name_fixer(self):
159 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000160 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
161 [('abc', 'class'), ('abc', '_1')], # field has keyword
162 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
163 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
164 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
165 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000166 ]:
167 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
168
Guido van Rossumd8faa362007-04-27 19:54:29 +0000169 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000170 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000171 p = Point(11, 22)
172 self.assertEqual(p, Point(x=11, y=22))
173 self.assertEqual(p, Point(11, y=22))
174 self.assertEqual(p, Point(y=22, x=11))
175 self.assertEqual(p, Point(*(11, 22)))
176 self.assertEqual(p, Point(**dict(x=11, y=22)))
177 self.assertRaises(TypeError, Point, 1) # too few args
178 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
179 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
180 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
181 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000182 self.assertNotIn('__dict__', dir(p)) # verify instance has no dict
183 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000184 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000185 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
186 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
187 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000188
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000189 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000190 p._replace(x=1, error=2)
191 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000192 pass
193 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000194 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000195
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000196 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000197 Point = namedtuple('Point', 'x, y')
198 p = Point(x=11, y=22)
199 self.assertEqual(repr(p), 'Point(x=11, y=22)')
200
201 # verify that fieldspec can be a non-string sequence
202 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000203 p = Point(x=11, y=22)
204 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000205
206 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000207 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000208 p = Point(11, 22)
209
Ezio Melottie9615932010-01-24 19:26:24 +0000210 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000211 self.assertEqual(p, (11, 22)) # matches a real tuple
212 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
213 self.assertEqual(list(p), [11, 22]) # coercable to a list
214 self.assertEqual(max(p), 22) # iterable
215 self.assertEqual(max(*p), 22) # star-able
216 x, y = p
217 self.assertEqual(p, (x, y)) # unpacks like a tuple
218 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
219 self.assertRaises(IndexError, p.__getitem__, 3)
220
221 self.assertEqual(p.x, x)
222 self.assertEqual(p.y, y)
223 self.assertRaises(AttributeError, eval, 'p.z', locals())
224
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000225 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000226 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000227 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000228 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000229 self.assertEqual(repr(Zero()), 'Zero()')
230 self.assertEqual(Zero()._asdict(), {})
231 self.assertEqual(Zero()._fields, ())
232
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000233 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000234 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000235 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000236 self.assertEqual(Dot(1).d, 1)
237 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
238 self.assertEqual(Dot(1)._asdict(), {'d':1})
239 self.assertEqual(Dot(1)._replace(d=999), (999,))
240 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000241
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000242 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000243 n = 254 # SyntaxError: more than 255 arguments:
244 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000245 names = list(set(''.join([random.choice(string.ascii_letters)
246 for j in range(10)]) for i in range(n)))
247 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000248 Big = namedtuple('Big', names)
249 b = Big(*range(n))
250 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000251 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000252 for pos, name in enumerate(names):
253 self.assertEqual(getattr(b, name), pos)
254 repr(b) # make sure repr() doesn't blow-up
255 d = b._asdict()
256 d_expected = dict(zip(names, range(n)))
257 self.assertEqual(d, d_expected)
258 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
259 b2_expected = list(range(n))
260 b2_expected[1] = 999
261 b2_expected[-5] = 42
262 self.assertEqual(b2, tuple(b2_expected))
263 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000264
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000265 def test_pickle(self):
266 p = TestNT(x=10, y=20, z=30)
267 for module in (pickle,):
268 loads = getattr(module, 'loads')
269 dumps = getattr(module, 'dumps')
270 for protocol in -1, 0, 1, 2:
271 q = loads(dumps(p, protocol))
272 self.assertEqual(p, q)
273 self.assertEqual(p._fields, q._fields)
274
275 def test_copy(self):
276 p = TestNT(x=10, y=20, z=30)
277 for copier in copy.copy, copy.deepcopy:
278 q = copier(p)
279 self.assertEqual(p, q)
280 self.assertEqual(p._fields, q._fields)
281
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000282 def test_name_conflicts(self):
283 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
284 # failed when used as field names. Test to make sure these now work.
285 T = namedtuple('T', 'itemgetter property self cls tuple')
286 t = T(1, 2, 3, 4, 5)
287 self.assertEqual(t, (1,2,3,4,5))
288 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
289 self.assertEqual(newt, (10,20,30,40,50))
290
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000291 # Broader test of all interesting names in a template
292 with support.captured_stdout() as template:
293 T = namedtuple('T', 'x', verbose=True)
294 words = set(re.findall('[A-Za-z]+', template.getvalue()))
295 words -= set(keyword.kwlist)
296 T = namedtuple('T', words)
297 # test __new__
298 values = tuple(range(len(words)))
299 t = T(*values)
300 self.assertEqual(t, values)
301 t = T(**dict(zip(T._fields, values)))
302 self.assertEqual(t, values)
303 # test _make
304 t = T._make(values)
305 self.assertEqual(t, values)
306 # exercise __repr__
307 repr(t)
308 # test _asdict
309 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
310 # test _replace
311 t = T._make(values)
312 newvalues = tuple(v*10 for v in values)
313 newt = t._replace(**dict(zip(T._fields, newvalues)))
314 self.assertEqual(newt, newvalues)
315 # test _fields
316 self.assertEqual(T._fields, tuple(words))
317 # test __getnewargs__
318 self.assertEqual(t.__getnewargs__(), values)
319
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000320 def test_repr(self):
321 with support.captured_stdout() as template:
322 A = namedtuple('A', 'x', verbose=True)
323 self.assertEqual(repr(A(1)), 'A(x=1)')
324 # repr should show the name of the subclass
325 class B(A):
326 pass
327 self.assertEqual(repr(B(1)), 'B(x=1)')
328
329
Raymond Hettinger499e1932011-02-23 07:56:53 +0000330################################################################################
331### Abstract Base Classes
332################################################################################
333
Raymond Hettingerae650182009-01-28 23:33:59 +0000334class ABCTestCase(unittest.TestCase):
335
336 def validate_abstract_methods(self, abc, *names):
337 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
338
339 # everything should work will all required methods are present
340 C = type('C', (abc,), methodstubs)
341 C()
342
343 # instantiation should fail if a required method is missing
344 for name in names:
345 stubs = methodstubs.copy()
346 del stubs[name]
347 C = type('C', (abc,), stubs)
348 self.assertRaises(TypeError, C, name)
349
Florent Xiclunace153f62010-03-08 15:34:35 +0000350 def validate_isinstance(self, abc, name):
351 stub = lambda s, *args: 0
352
353 C = type('C', (object,), {'__hash__': None})
354 setattr(C, name, stub)
355 self.assertIsInstance(C(), abc)
356 self.assertTrue(issubclass(C, abc))
357
358 C = type('C', (object,), {'__hash__': None})
359 self.assertNotIsInstance(C(), abc)
360 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000361
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000362 def validate_comparison(self, instance):
363 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
364 operators = {}
365 for op in ops:
366 name = '__' + op + '__'
367 operators[name] = getattr(operator, name)
368
369 class Other:
370 def __init__(self):
371 self.right_side = False
372 def __eq__(self, other):
373 self.right_side = True
374 return True
375 __lt__ = __eq__
376 __gt__ = __eq__
377 __le__ = __eq__
378 __ge__ = __eq__
379 __ne__ = __eq__
380 __ror__ = __eq__
381 __rand__ = __eq__
382 __rxor__ = __eq__
383 __rsub__ = __eq__
384
385 for name, op in operators.items():
386 if not hasattr(instance, name):
387 continue
388 other = Other()
389 op(instance, other)
390 self.assertTrue(other.right_side,'Right side not called for %s.%s'
391 % (type(instance), name))
392
Raymond Hettingerae650182009-01-28 23:33:59 +0000393class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000394
395 def test_Hashable(self):
396 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000397 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000398 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000399 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000400 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000401 # Check some hashables
402 samples = [None,
403 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000404 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000405 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000406 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000407 ]
408 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000409 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000410 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000411 self.assertRaises(TypeError, Hashable)
412 # Check direct subclassing
413 class H(Hashable):
414 def __hash__(self):
415 return super().__hash__()
416 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000417 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000418 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000419 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000420
421 def test_Iterable(self):
422 # Check some non-iterables
423 non_samples = [None, 42, 3.14, 1j]
424 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000425 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000426 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000427 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000428 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000429 tuple(), list(), set(), frozenset(), dict(),
430 dict().keys(), dict().items(), dict().values(),
431 (lambda: (yield))(),
432 (x for x in []),
433 ]
434 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000435 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000436 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000437 # Check direct subclassing
438 class I(Iterable):
439 def __iter__(self):
440 return super().__iter__()
441 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000442 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000443 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000444 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000445
446 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000447 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000448 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000449 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000450 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000451 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000452 iter(tuple()), iter(list()), iter(dict()),
453 iter(set()), iter(frozenset()),
454 iter(dict().keys()), iter(dict().items()),
455 iter(dict().values()),
456 (lambda: (yield))(),
457 (x for x in []),
458 ]
459 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000460 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000461 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000462 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
463
464 # Issue 10565
465 class NextOnly:
466 def __next__(self):
467 yield 1
468 raise StopIteration
469 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000470
471 def test_Sized(self):
472 non_samples = [None, 42, 3.14, 1j,
473 (lambda: (yield))(),
474 (x for x in []),
475 ]
476 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000477 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000478 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000479 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000480 tuple(), list(), set(), frozenset(), dict(),
481 dict().keys(), dict().items(), dict().values(),
482 ]
483 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000484 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000485 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000486 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000487 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000488
489 def test_Container(self):
490 non_samples = [None, 42, 3.14, 1j,
491 (lambda: (yield))(),
492 (x for x in []),
493 ]
494 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000495 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000496 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000497 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000498 tuple(), list(), set(), frozenset(), dict(),
499 dict().keys(), dict().items(),
500 ]
501 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000502 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000503 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000504 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000505 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000506
507 def test_Callable(self):
508 non_samples = [None, 42, 3.14, 1j,
509 "", b"", (), [], {}, set(),
510 (lambda: (yield))(),
511 (x for x in []),
512 ]
513 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000514 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000515 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000516 samples = [lambda: None,
517 type, int, object,
518 len,
519 list.append, [].append,
520 ]
521 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000522 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000523 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000524 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000525 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000526
527 def test_direct_subclassing(self):
528 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
529 class C(B):
530 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000531 self.assertTrue(issubclass(C, B))
532 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000533
534 def test_registration(self):
535 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
536 class C:
537 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000538 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000539 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000540 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000541
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000542class WithSet(MutableSet):
543
544 def __init__(self, it=()):
545 self.data = set(it)
546
547 def __len__(self):
548 return len(self.data)
549
550 def __iter__(self):
551 return iter(self.data)
552
553 def __contains__(self, item):
554 return item in self.data
555
556 def add(self, item):
557 self.data.add(item)
558
559 def discard(self, item):
560 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000561
Raymond Hettingerae650182009-01-28 23:33:59 +0000562class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000563
564 # XXX For now, we only test some virtual inheritance properties.
565 # We should also test the proper behavior of the collection ABCs
566 # as real base classes or mix-in classes.
567
568 def test_Set(self):
569 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000570 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000571 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000572 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000573 class MySet(Set):
574 def __contains__(self, x):
575 return False
576 def __len__(self):
577 return 0
578 def __iter__(self):
579 return iter([])
580 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000581
Benjamin Peterson41181742008-07-02 20:22:54 +0000582 def test_hash_Set(self):
583 class OneTwoThreeSet(Set):
584 def __init__(self):
585 self.contents = [1, 2, 3]
586 def __contains__(self, x):
587 return x in self.contents
588 def __len__(self):
589 return len(self.contents)
590 def __iter__(self):
591 return iter(self.contents)
592 def __hash__(self):
593 return self._hash()
594 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000595 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000596
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000597 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000598 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000599 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000600 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000601 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000602 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
603 'add', 'discard')
604
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000605 def test_issue_5647(self):
606 # MutableSet.__iand__ mutated the set during iteration
607 s = WithSet('abcd')
608 s &= WithSet('cdef') # This used to fail
609 self.assertEqual(set(s), set('cd'))
610
Raymond Hettingerae650182009-01-28 23:33:59 +0000611 def test_issue_4920(self):
612 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000613 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000614 __slots__=['__s']
615 def __init__(self,items=None):
616 if items is None:
617 items=[]
618 self.__s=set(items)
619 def __contains__(self,v):
620 return v in self.__s
621 def __iter__(self):
622 return iter(self.__s)
623 def __len__(self):
624 return len(self.__s)
625 def add(self,v):
626 result=v not in self.__s
627 self.__s.add(v)
628 return result
629 def discard(self,v):
630 result=v in self.__s
631 self.__s.discard(v)
632 return result
633 def __repr__(self):
634 return "MySet(%s)" % repr(list(self))
635 s = MySet([5,43,2,1])
636 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000637
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000638 def test_issue8750(self):
639 empty = WithSet()
640 full = WithSet(range(10))
641 s = WithSet(full)
642 s -= s
643 self.assertEqual(s, empty)
644 s = WithSet(full)
645 s ^= s
646 self.assertEqual(s, empty)
647 s = WithSet(full)
648 s &= s
649 self.assertEqual(s, full)
650 s |= s
651 self.assertEqual(s, full)
652
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000653 def test_Mapping(self):
654 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000655 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000656 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000657 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
658 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000659 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000660 def __len__(self):
661 return 0
662 def __getitem__(self, i):
663 raise IndexError
664 def __iter__(self):
665 return iter(())
666 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000667
668 def test_MutableMapping(self):
669 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000670 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000671 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000672 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
673 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000674
Raymond Hettinger9117c752010-08-22 07:44:24 +0000675 def test_MutableMapping_subclass(self):
676 # Test issue 9214
677 mymap = UserDict()
678 mymap['red'] = 5
679 self.assertIsInstance(mymap.keys(), Set)
680 self.assertIsInstance(mymap.keys(), KeysView)
681 self.assertIsInstance(mymap.items(), Set)
682 self.assertIsInstance(mymap.items(), ItemsView)
683
684 mymap = UserDict()
685 mymap['red'] = 5
686 z = mymap.keys() | {'orange'}
687 self.assertIsInstance(z, set)
688 list(z)
689 mymap['blue'] = 7 # Shouldn't affect 'z'
690 self.assertEqual(sorted(z), ['orange', 'red'])
691
692 mymap = UserDict()
693 mymap['red'] = 5
694 z = mymap.items() | {('orange', 3)}
695 self.assertIsInstance(z, set)
696 list(z)
697 mymap['blue'] = 7 # Shouldn't affect 'z'
698 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
699
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000700 def test_Sequence(self):
701 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000702 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000703 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000704 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000705 self.assertTrue(issubclass(range, Sequence))
706 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000707 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
708 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000709
Guido van Rossumd05eb002007-11-21 22:26:24 +0000710 def test_ByteString(self):
711 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000712 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000713 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000714 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000715 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000716 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000717 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000718 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000719
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000720 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000721 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000722 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000723 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000724 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000725 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000726 self.assertTrue(issubclass(sample, MutableSequence))
727 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000728 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
729 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000730
Raymond Hettinger499e1932011-02-23 07:56:53 +0000731
732################################################################################
733### Counter
734################################################################################
735
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000736class TestCounter(unittest.TestCase):
737
738 def test_basics(self):
739 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000740 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
741 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +0000742 self.assertIsInstance(c, dict)
743 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000744 self.assertTrue(issubclass(Counter, dict))
745 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000746 self.assertEqual(len(c), 3)
747 self.assertEqual(sum(c.values()), 6)
748 self.assertEqual(sorted(c.values()), [1, 2, 3])
749 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
750 self.assertEqual(sorted(c), ['a', 'b', 'c'])
751 self.assertEqual(sorted(c.items()),
752 [('a', 3), ('b', 2), ('c', 1)])
753 self.assertEqual(c['b'], 2)
754 self.assertEqual(c['z'], 0)
755 self.assertEqual(c.__contains__('c'), True)
756 self.assertEqual(c.__contains__('z'), False)
757 self.assertEqual(c.get('b', 10), 2)
758 self.assertEqual(c.get('z', 10), 10)
759 self.assertEqual(c, dict(a=3, b=2, c=1))
760 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
761 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
762 for i in range(5):
763 self.assertEqual(c.most_common(i),
764 [('a', 3), ('b', 2), ('c', 1)][:i])
765 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
766 c['a'] += 1 # increment an existing value
767 c['b'] -= 2 # sub existing value to zero
768 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000769 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000770 c['d'] -= 2 # sub from a missing value
771 c['e'] = -5 # directly assign a missing value
772 c['f'] += 4 # add to a missing value
773 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
774 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
775 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000776 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000777 for i in range(3):
778 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000779 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000780 c.clear()
781 self.assertEqual(c, {})
782 self.assertEqual(repr(c), 'Counter()')
783 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
784 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000785 c.update(dict(a=5, b=3))
786 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000787 c.update(Counter('a' * 50 + 'b' * 30))
788 c.update() # test case with no args
789 c.__init__('a' * 500 + 'b' * 300)
790 c.__init__('cdc')
791 c.__init__()
792 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
793 self.assertEqual(c.setdefault('d', 5), 1)
794 self.assertEqual(c['d'], 1)
795 self.assertEqual(c.setdefault('e', 5), 5)
796 self.assertEqual(c['e'], 5)
797
798 def test_copying(self):
799 # Check that counters are copyable, deepcopyable, picklable, and
800 #have a repr/eval round-trip
801 words = Counter('which witch had which witches wrist watch'.split())
802 update_test = Counter()
803 update_test.update(words)
804 for i, dup in enumerate([
805 words.copy(),
806 copy.copy(words),
807 copy.deepcopy(words),
808 pickle.loads(pickle.dumps(words, 0)),
809 pickle.loads(pickle.dumps(words, 1)),
810 pickle.loads(pickle.dumps(words, 2)),
811 pickle.loads(pickle.dumps(words, -1)),
812 eval(repr(words)),
813 update_test,
814 Counter(words),
815 ]):
816 msg = (i, dup, words)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000817 self.assertTrue(dup is not words)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000818 self.assertEqual(dup, words)
819 self.assertEqual(len(dup), len(words))
820 self.assertEqual(type(dup), type(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000821
822 def test_conversions(self):
823 # Convert to: set, list, dict
824 s = 'she sells sea shells by the sea shore'
825 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
826 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
827 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
828 self.assertEqual(set(Counter(s)), set(s))
829
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000830 def test_invariant_for_the_in_operator(self):
831 c = Counter(a=10, b=-2, c=0)
832 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000833 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000834 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000835
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000836 def test_multiset_operations(self):
837 # Verify that adding a zero counter will strip zeros and negatives
838 c = Counter(a=10, b=-2, c=0) + Counter()
839 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000840
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000841 elements = 'abcd'
842 for i in range(1000):
843 # test random pairs of multisets
844 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000845 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000846 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000847 q.update(h=1, i=-1, j=0)
848 for counterop, numberop in [
849 (Counter.__add__, lambda x, y: max(0, x+y)),
850 (Counter.__sub__, lambda x, y: max(0, x-y)),
851 (Counter.__or__, lambda x, y: max(0,x,y)),
852 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000853 ]:
854 result = counterop(p, q)
855 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000856 self.assertEqual(numberop(p[x], q[x]), result[x],
857 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000858 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000859 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000860
861 elements = 'abcdef'
862 for i in range(100):
863 # verify that random multisets with no repeats are exactly like sets
864 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
865 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
866 for counterop, setop in [
867 (Counter.__sub__, set.__sub__),
868 (Counter.__or__, set.__or__),
869 (Counter.__and__, set.__and__),
870 ]:
871 counter_result = counterop(p, q)
872 set_result = setop(set(p.elements()), set(q.elements()))
873 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000874
Raymond Hettinger9c01e442010-04-03 10:32:58 +0000875 def test_subtract(self):
876 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
877 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
878 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
879 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
880 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
881 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
882 c = Counter('aaabbcd')
883 c.subtract('aaaabbcce')
884 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000885
Raymond Hettinger426e0522011-01-03 02:12:02 +0000886 def test_helper_function(self):
887 # two paths, one for real dicts and one for other mappings
888 elems = list('abracadabra')
889
890 d = dict()
891 _count_elements(d, elems)
892 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
893
894 m = OrderedDict()
895 _count_elements(m, elems)
896 self.assertEqual(m,
897 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
898
Raymond Hettinger499e1932011-02-23 07:56:53 +0000899
900################################################################################
901### OrderedDict
902################################################################################
903
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000904class TestOrderedDict(unittest.TestCase):
905
906 def test_init(self):
907 with self.assertRaises(TypeError):
908 OrderedDict([('a', 1), ('b', 2)], None) # too many args
909 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
910 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
911 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
912 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
913 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
914 c=3, e=5).items()), pairs) # mixed input
915
916 # make sure no positional args conflict with possible kwdargs
917 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
918 ['self'])
919
920 # Make sure that direct calls to __init__ do not clear previous contents
921 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
922 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
923 self.assertEqual(list(d.items()),
924 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
925
926 def test_update(self):
927 with self.assertRaises(TypeError):
928 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
929 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
930 od = OrderedDict()
931 od.update(dict(pairs))
932 self.assertEqual(sorted(od.items()), pairs) # dict input
933 od = OrderedDict()
934 od.update(**dict(pairs))
935 self.assertEqual(sorted(od.items()), pairs) # kwds input
936 od = OrderedDict()
937 od.update(pairs)
938 self.assertEqual(list(od.items()), pairs) # pairs input
939 od = OrderedDict()
940 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
941 self.assertEqual(list(od.items()), pairs) # mixed input
942
Mark Dickinsonb214e902010-07-11 18:53:06 +0000943 # Issue 9137: Named argument called 'other' or 'self'
944 # shouldn't be treated specially.
945 od = OrderedDict()
946 od.update(self=23)
947 self.assertEqual(list(od.items()), [('self', 23)])
948 od = OrderedDict()
949 od.update(other={})
950 self.assertEqual(list(od.items()), [('other', {})])
951 od = OrderedDict()
952 od.update(red=5, blue=6, other=7, self=8)
953 self.assertEqual(sorted(list(od.items())),
954 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
955
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000956 # Make sure that direct calls to update do not clear previous contents
957 # add that updates items are not moved to the end
958 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
959 d.update([('e', 5), ('f', 6)], g=7, d=4)
960 self.assertEqual(list(d.items()),
961 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
962
Raymond Hettinger345c49b2011-01-01 23:51:55 +0000963 def test_abc(self):
964 self.assertIsInstance(OrderedDict(), MutableMapping)
965 self.assertTrue(issubclass(OrderedDict, MutableMapping))
966
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000967 def test_clear(self):
968 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
969 shuffle(pairs)
970 od = OrderedDict(pairs)
971 self.assertEqual(len(od), len(pairs))
972 od.clear()
973 self.assertEqual(len(od), 0)
974
975 def test_delitem(self):
976 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
977 od = OrderedDict(pairs)
978 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +0000979 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000980 with self.assertRaises(KeyError):
981 del od['a']
982 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
983
984 def test_setitem(self):
985 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
986 od['c'] = 10 # existing element
987 od['f'] = 20 # new element
988 self.assertEqual(list(od.items()),
989 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
990
991 def test_iterators(self):
992 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
993 shuffle(pairs)
994 od = OrderedDict(pairs)
995 self.assertEqual(list(od), [t[0] for t in pairs])
996 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
997 self.assertEqual(list(od.values()), [t[1] for t in pairs])
998 self.assertEqual(list(od.items()), pairs)
999 self.assertEqual(list(reversed(od)),
1000 [t[0] for t in reversed(pairs)])
1001
1002 def test_popitem(self):
1003 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1004 shuffle(pairs)
1005 od = OrderedDict(pairs)
1006 while pairs:
1007 self.assertEqual(od.popitem(), pairs.pop())
1008 with self.assertRaises(KeyError):
1009 od.popitem()
1010 self.assertEqual(len(od), 0)
1011
1012 def test_pop(self):
1013 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1014 shuffle(pairs)
1015 od = OrderedDict(pairs)
1016 shuffle(pairs)
1017 while pairs:
1018 k, v = pairs.pop()
1019 self.assertEqual(od.pop(k), v)
1020 with self.assertRaises(KeyError):
1021 od.pop('xyz')
1022 self.assertEqual(len(od), 0)
1023 self.assertEqual(od.pop(k, 12345), 12345)
1024
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001025 # make sure pop still works when __missing__ is defined
1026 class Missing(OrderedDict):
1027 def __missing__(self, key):
1028 return 0
1029 m = Missing(a=1)
1030 self.assertEqual(m.pop('b', 5), 5)
1031 self.assertEqual(m.pop('a', 6), 1)
1032 self.assertEqual(m.pop('a', 6), 6)
1033 with self.assertRaises(KeyError):
1034 m.pop('a')
1035
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001036 def test_equality(self):
1037 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1038 shuffle(pairs)
1039 od1 = OrderedDict(pairs)
1040 od2 = OrderedDict(pairs)
1041 self.assertEqual(od1, od2) # same order implies equality
1042 pairs = pairs[2:] + pairs[:2]
1043 od2 = OrderedDict(pairs)
1044 self.assertNotEqual(od1, od2) # different order implies inequality
1045 # comparison to regular dict is not order sensitive
1046 self.assertEqual(od1, dict(od2))
1047 self.assertEqual(dict(od2), od1)
1048 # different length implied inequality
1049 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1050
1051 def test_copying(self):
1052 # Check that ordered dicts are copyable, deepcopyable, picklable,
1053 # and have a repr/eval round-trip
1054 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1055 od = OrderedDict(pairs)
1056 update_test = OrderedDict()
1057 update_test.update(od)
1058 for i, dup in enumerate([
1059 od.copy(),
1060 copy.copy(od),
1061 copy.deepcopy(od),
1062 pickle.loads(pickle.dumps(od, 0)),
1063 pickle.loads(pickle.dumps(od, 1)),
1064 pickle.loads(pickle.dumps(od, 2)),
1065 pickle.loads(pickle.dumps(od, 3)),
1066 pickle.loads(pickle.dumps(od, -1)),
1067 eval(repr(od)),
1068 update_test,
1069 OrderedDict(od),
1070 ]):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001071 self.assertTrue(dup is not od)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001072 self.assertEqual(dup, od)
1073 self.assertEqual(list(dup.items()), list(od.items()))
1074 self.assertEqual(len(dup), len(od))
1075 self.assertEqual(type(dup), type(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001076
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001077 def test_yaml_linkage(self):
1078 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1079 # In yaml, lists are native but tuples are not.
1080 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1081 od = OrderedDict(pairs)
1082 # yaml.dump(od) -->
1083 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001084 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001085
Raymond Hettingerb2121572009-03-03 22:50:04 +00001086 def test_reduce_not_too_fat(self):
1087 # do not save instance dictionary if not needed
1088 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1089 od = OrderedDict(pairs)
1090 self.assertEqual(len(od.__reduce__()), 2)
1091 od.x = 10
1092 self.assertEqual(len(od.__reduce__()), 3)
1093
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001094 def test_repr(self):
1095 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1096 self.assertEqual(repr(od),
1097 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1098 self.assertEqual(eval(repr(od)), od)
1099 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1100
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001101 def test_repr_recursive(self):
1102 # See issue #9826
1103 od = OrderedDict.fromkeys('abc')
1104 od['x'] = od
1105 self.assertEqual(repr(od),
1106 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1107
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001108 def test_setdefault(self):
1109 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1110 shuffle(pairs)
1111 od = OrderedDict(pairs)
1112 pair_order = list(od.items())
1113 self.assertEqual(od.setdefault('a', 10), 3)
1114 # make sure order didn't change
1115 self.assertEqual(list(od.items()), pair_order)
1116 self.assertEqual(od.setdefault('x', 10), 10)
1117 # make sure 'x' is added to the end
1118 self.assertEqual(list(od.items())[-1], ('x', 10))
1119
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001120 # make sure setdefault still works when __missing__ is defined
1121 class Missing(OrderedDict):
1122 def __missing__(self, key):
1123 return 0
1124 self.assertEqual(Missing().setdefault(5, 9), 9)
1125
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001126 def test_reinsert(self):
1127 # Given insert a, insert b, delete a, re-insert a,
1128 # verify that a is now later than b.
1129 od = OrderedDict()
1130 od['a'] = 1
1131 od['b'] = 2
1132 del od['a']
1133 od['a'] = 1
1134 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1135
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001136 def test_move_to_end(self):
1137 od = OrderedDict.fromkeys('abcde')
1138 self.assertEqual(list(od), list('abcde'))
1139 od.move_to_end('c')
1140 self.assertEqual(list(od), list('abdec'))
1141 od.move_to_end('c', 0)
1142 self.assertEqual(list(od), list('cabde'))
1143 od.move_to_end('c', 0)
1144 self.assertEqual(list(od), list('cabde'))
1145 od.move_to_end('e')
1146 self.assertEqual(list(od), list('cabde'))
1147 with self.assertRaises(KeyError):
1148 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001149
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001150 def test_sizeof(self):
1151 # Wimpy test: Just verify the reported size is larger than a regular dict
1152 d = dict(a=1)
1153 od = OrderedDict(**d)
1154 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1155
Raymond Hettinger32062e92011-01-01 22:38:00 +00001156 def test_override_update(self):
1157 # Verify that subclasses can override update() without breaking __init__()
1158 class MyOD(OrderedDict):
1159 def update(self, *args, **kwds):
1160 raise Exception()
1161 items = [('a', 1), ('c', 3), ('b', 2)]
1162 self.assertEqual(list(MyOD(items).items()), items)
1163
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001164class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1165 type2test = OrderedDict
1166
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001167 def test_popitem(self):
1168 d = self._empty_mapping()
1169 self.assertRaises(KeyError, d.popitem)
1170
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001171class MyOrderedDict(OrderedDict):
1172 pass
1173
1174class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1175 type2test = MyOrderedDict
1176
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001177 def test_popitem(self):
1178 d = self._empty_mapping()
1179 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001180
1181
Raymond Hettinger499e1932011-02-23 07:56:53 +00001182################################################################################
1183### Run tests
1184################################################################################
1185
Christian Heimes25bb7832008-01-11 16:17:00 +00001186import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001187
Guido van Rossumd8faa362007-04-27 19:54:29 +00001188def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001189 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001190 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001191 TestCollectionABCs, TestCounter, TestChainMap,
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001192 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001193 support.run_unittest(*test_classes)
1194 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001195
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001196
Guido van Rossumd8faa362007-04-27 19:54:29 +00001197if __name__ == "__main__":
1198 test_main(verbose=True)