blob: cdc7db9a7f83cc5d0b6e1618c22c38ebdf7dc9e6 [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'))
Raymond Hettinger2ebea412011-03-23 12:52:23 -0700130 self.assertIn('class Point(tuple)', Point._source)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000131
132 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
133 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
134 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
135
136 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
137 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
138 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000139 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000140 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
141
142 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000143 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000144
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000145 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000146 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000147 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000148 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000149
Christian Heimesfaf2f632008-01-06 16:59:19 +0000150 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
151 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
152
R. David Murray378c0cf2010-02-24 01:46:21 +0000153 @unittest.skipIf(sys.flags.optimize >= 2,
154 "Docstrings are omitted with -O2 and above")
155 def test_factory_doc_attr(self):
156 Point = namedtuple('Point', 'x y')
157 self.assertEqual(Point.__doc__, 'Point(x, y)')
158
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000159 def test_name_fixer(self):
160 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000161 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
162 [('abc', 'class'), ('abc', '_1')], # field has keyword
163 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
164 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
165 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
166 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000167 ]:
168 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
169
Guido van Rossumd8faa362007-04-27 19:54:29 +0000170 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000171 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000172 p = Point(11, 22)
173 self.assertEqual(p, Point(x=11, y=22))
174 self.assertEqual(p, Point(11, y=22))
175 self.assertEqual(p, Point(y=22, x=11))
176 self.assertEqual(p, Point(*(11, 22)))
177 self.assertEqual(p, Point(**dict(x=11, y=22)))
178 self.assertRaises(TypeError, Point, 1) # too few args
179 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
180 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
181 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
182 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000183 self.assertNotIn('__dict__', dir(p)) # verify instance has no dict
184 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
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000189
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000190 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000191 p._replace(x=1, error=2)
192 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000193 pass
194 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000195 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000196
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000197 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000198 Point = namedtuple('Point', 'x, y')
199 p = Point(x=11, y=22)
200 self.assertEqual(repr(p), 'Point(x=11, y=22)')
201
202 # verify that fieldspec can be a non-string sequence
203 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000204 p = Point(x=11, y=22)
205 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000206
207 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000208 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000209 p = Point(11, 22)
210
Ezio Melottie9615932010-01-24 19:26:24 +0000211 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000212 self.assertEqual(p, (11, 22)) # matches a real tuple
213 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
214 self.assertEqual(list(p), [11, 22]) # coercable to a list
215 self.assertEqual(max(p), 22) # iterable
216 self.assertEqual(max(*p), 22) # star-able
217 x, y = p
218 self.assertEqual(p, (x, y)) # unpacks like a tuple
219 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
220 self.assertRaises(IndexError, p.__getitem__, 3)
221
222 self.assertEqual(p.x, x)
223 self.assertEqual(p.y, y)
224 self.assertRaises(AttributeError, eval, 'p.z', locals())
225
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000226 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000227 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000228 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000229 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000230 self.assertEqual(repr(Zero()), 'Zero()')
231 self.assertEqual(Zero()._asdict(), {})
232 self.assertEqual(Zero()._fields, ())
233
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000234 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000235 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000236 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000237 self.assertEqual(Dot(1).d, 1)
238 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
239 self.assertEqual(Dot(1)._asdict(), {'d':1})
240 self.assertEqual(Dot(1)._replace(d=999), (999,))
241 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000242
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000243 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000244 n = 254 # SyntaxError: more than 255 arguments:
245 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000246 names = list(set(''.join([random.choice(string.ascii_letters)
247 for j in range(10)]) for i in range(n)))
248 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000249 Big = namedtuple('Big', names)
250 b = Big(*range(n))
251 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000252 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000253 for pos, name in enumerate(names):
254 self.assertEqual(getattr(b, name), pos)
255 repr(b) # make sure repr() doesn't blow-up
256 d = b._asdict()
257 d_expected = dict(zip(names, range(n)))
258 self.assertEqual(d, d_expected)
259 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
260 b2_expected = list(range(n))
261 b2_expected[1] = 999
262 b2_expected[-5] = 42
263 self.assertEqual(b2, tuple(b2_expected))
264 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000265
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000266 def test_pickle(self):
267 p = TestNT(x=10, y=20, z=30)
268 for module in (pickle,):
269 loads = getattr(module, 'loads')
270 dumps = getattr(module, 'dumps')
271 for protocol in -1, 0, 1, 2:
272 q = loads(dumps(p, protocol))
273 self.assertEqual(p, q)
274 self.assertEqual(p._fields, q._fields)
275
276 def test_copy(self):
277 p = TestNT(x=10, y=20, z=30)
278 for copier in copy.copy, copy.deepcopy:
279 q = copier(p)
280 self.assertEqual(p, q)
281 self.assertEqual(p._fields, q._fields)
282
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000283 def test_name_conflicts(self):
284 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
285 # failed when used as field names. Test to make sure these now work.
286 T = namedtuple('T', 'itemgetter property self cls tuple')
287 t = T(1, 2, 3, 4, 5)
288 self.assertEqual(t, (1,2,3,4,5))
289 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
290 self.assertEqual(newt, (10,20,30,40,50))
291
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000292 # Broader test of all interesting names in a template
293 with support.captured_stdout() as template:
294 T = namedtuple('T', 'x', verbose=True)
295 words = set(re.findall('[A-Za-z]+', template.getvalue()))
296 words -= set(keyword.kwlist)
297 T = namedtuple('T', words)
298 # test __new__
299 values = tuple(range(len(words)))
300 t = T(*values)
301 self.assertEqual(t, values)
302 t = T(**dict(zip(T._fields, values)))
303 self.assertEqual(t, values)
304 # test _make
305 t = T._make(values)
306 self.assertEqual(t, values)
307 # exercise __repr__
308 repr(t)
309 # test _asdict
310 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
311 # test _replace
312 t = T._make(values)
313 newvalues = tuple(v*10 for v in values)
314 newt = t._replace(**dict(zip(T._fields, newvalues)))
315 self.assertEqual(newt, newvalues)
316 # test _fields
317 self.assertEqual(T._fields, tuple(words))
318 # test __getnewargs__
319 self.assertEqual(t.__getnewargs__(), values)
320
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000321 def test_repr(self):
322 with support.captured_stdout() as template:
323 A = namedtuple('A', 'x', verbose=True)
324 self.assertEqual(repr(A(1)), 'A(x=1)')
325 # repr should show the name of the subclass
326 class B(A):
327 pass
328 self.assertEqual(repr(B(1)), 'B(x=1)')
329
330
Raymond Hettinger499e1932011-02-23 07:56:53 +0000331################################################################################
332### Abstract Base Classes
333################################################################################
334
Raymond Hettingerae650182009-01-28 23:33:59 +0000335class ABCTestCase(unittest.TestCase):
336
337 def validate_abstract_methods(self, abc, *names):
338 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
339
340 # everything should work will all required methods are present
341 C = type('C', (abc,), methodstubs)
342 C()
343
344 # instantiation should fail if a required method is missing
345 for name in names:
346 stubs = methodstubs.copy()
347 del stubs[name]
348 C = type('C', (abc,), stubs)
349 self.assertRaises(TypeError, C, name)
350
Florent Xiclunace153f62010-03-08 15:34:35 +0000351 def validate_isinstance(self, abc, name):
352 stub = lambda s, *args: 0
353
354 C = type('C', (object,), {'__hash__': None})
355 setattr(C, name, stub)
356 self.assertIsInstance(C(), abc)
357 self.assertTrue(issubclass(C, abc))
358
359 C = type('C', (object,), {'__hash__': None})
360 self.assertNotIsInstance(C(), abc)
361 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000362
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000363 def validate_comparison(self, instance):
364 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
365 operators = {}
366 for op in ops:
367 name = '__' + op + '__'
368 operators[name] = getattr(operator, name)
369
370 class Other:
371 def __init__(self):
372 self.right_side = False
373 def __eq__(self, other):
374 self.right_side = True
375 return True
376 __lt__ = __eq__
377 __gt__ = __eq__
378 __le__ = __eq__
379 __ge__ = __eq__
380 __ne__ = __eq__
381 __ror__ = __eq__
382 __rand__ = __eq__
383 __rxor__ = __eq__
384 __rsub__ = __eq__
385
386 for name, op in operators.items():
387 if not hasattr(instance, name):
388 continue
389 other = Other()
390 op(instance, other)
391 self.assertTrue(other.right_side,'Right side not called for %s.%s'
392 % (type(instance), name))
393
Raymond Hettingerae650182009-01-28 23:33:59 +0000394class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000395
396 def test_Hashable(self):
397 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000398 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000399 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000400 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000401 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000402 # Check some hashables
403 samples = [None,
404 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000405 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000406 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000407 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000408 ]
409 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000410 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000411 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000412 self.assertRaises(TypeError, Hashable)
413 # Check direct subclassing
414 class H(Hashable):
415 def __hash__(self):
416 return super().__hash__()
417 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000418 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000419 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000420 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000421
422 def test_Iterable(self):
423 # Check some non-iterables
424 non_samples = [None, 42, 3.14, 1j]
425 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000426 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000427 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000428 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000429 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000430 tuple(), list(), set(), frozenset(), dict(),
431 dict().keys(), dict().items(), dict().values(),
432 (lambda: (yield))(),
433 (x for x in []),
434 ]
435 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000436 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000437 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000438 # Check direct subclassing
439 class I(Iterable):
440 def __iter__(self):
441 return super().__iter__()
442 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000443 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000444 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000445 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000446
447 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000448 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000449 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000450 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000451 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000452 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000453 iter(tuple()), iter(list()), iter(dict()),
454 iter(set()), iter(frozenset()),
455 iter(dict().keys()), iter(dict().items()),
456 iter(dict().values()),
457 (lambda: (yield))(),
458 (x for x in []),
459 ]
460 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000461 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000462 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000463 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
464
465 # Issue 10565
466 class NextOnly:
467 def __next__(self):
468 yield 1
469 raise StopIteration
470 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000471
472 def test_Sized(self):
473 non_samples = [None, 42, 3.14, 1j,
474 (lambda: (yield))(),
475 (x for x in []),
476 ]
477 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000478 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000479 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000480 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000481 tuple(), list(), set(), frozenset(), dict(),
482 dict().keys(), dict().items(), dict().values(),
483 ]
484 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000485 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000486 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000487 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000488 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000489
490 def test_Container(self):
491 non_samples = [None, 42, 3.14, 1j,
492 (lambda: (yield))(),
493 (x for x in []),
494 ]
495 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000496 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000497 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000498 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000499 tuple(), list(), set(), frozenset(), dict(),
500 dict().keys(), dict().items(),
501 ]
502 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000503 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000504 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000505 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000506 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000507
508 def test_Callable(self):
509 non_samples = [None, 42, 3.14, 1j,
510 "", b"", (), [], {}, set(),
511 (lambda: (yield))(),
512 (x for x in []),
513 ]
514 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000515 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000516 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000517 samples = [lambda: None,
518 type, int, object,
519 len,
520 list.append, [].append,
521 ]
522 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000523 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000524 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000525 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000526 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000527
528 def test_direct_subclassing(self):
529 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
530 class C(B):
531 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000532 self.assertTrue(issubclass(C, B))
533 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000534
535 def test_registration(self):
536 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
537 class C:
538 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000539 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000540 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000541 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000542
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000543class WithSet(MutableSet):
544
545 def __init__(self, it=()):
546 self.data = set(it)
547
548 def __len__(self):
549 return len(self.data)
550
551 def __iter__(self):
552 return iter(self.data)
553
554 def __contains__(self, item):
555 return item in self.data
556
557 def add(self, item):
558 self.data.add(item)
559
560 def discard(self, item):
561 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000562
Raymond Hettingerae650182009-01-28 23:33:59 +0000563class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000564
565 # XXX For now, we only test some virtual inheritance properties.
566 # We should also test the proper behavior of the collection ABCs
567 # as real base classes or mix-in classes.
568
569 def test_Set(self):
570 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000571 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000572 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000573 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000574 class MySet(Set):
575 def __contains__(self, x):
576 return False
577 def __len__(self):
578 return 0
579 def __iter__(self):
580 return iter([])
581 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000582
Benjamin Peterson41181742008-07-02 20:22:54 +0000583 def test_hash_Set(self):
584 class OneTwoThreeSet(Set):
585 def __init__(self):
586 self.contents = [1, 2, 3]
587 def __contains__(self, x):
588 return x in self.contents
589 def __len__(self):
590 return len(self.contents)
591 def __iter__(self):
592 return iter(self.contents)
593 def __hash__(self):
594 return self._hash()
595 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000596 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000597
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000598 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000599 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000600 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000601 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000602 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000603 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
604 'add', 'discard')
605
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000606 def test_issue_5647(self):
607 # MutableSet.__iand__ mutated the set during iteration
608 s = WithSet('abcd')
609 s &= WithSet('cdef') # This used to fail
610 self.assertEqual(set(s), set('cd'))
611
Raymond Hettingerae650182009-01-28 23:33:59 +0000612 def test_issue_4920(self):
613 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000614 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000615 __slots__=['__s']
616 def __init__(self,items=None):
617 if items is None:
618 items=[]
619 self.__s=set(items)
620 def __contains__(self,v):
621 return v in self.__s
622 def __iter__(self):
623 return iter(self.__s)
624 def __len__(self):
625 return len(self.__s)
626 def add(self,v):
627 result=v not in self.__s
628 self.__s.add(v)
629 return result
630 def discard(self,v):
631 result=v in self.__s
632 self.__s.discard(v)
633 return result
634 def __repr__(self):
635 return "MySet(%s)" % repr(list(self))
636 s = MySet([5,43,2,1])
637 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000638
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000639 def test_issue8750(self):
640 empty = WithSet()
641 full = WithSet(range(10))
642 s = WithSet(full)
643 s -= s
644 self.assertEqual(s, empty)
645 s = WithSet(full)
646 s ^= s
647 self.assertEqual(s, empty)
648 s = WithSet(full)
649 s &= s
650 self.assertEqual(s, full)
651 s |= s
652 self.assertEqual(s, full)
653
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000654 def test_Mapping(self):
655 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000656 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000657 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000658 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
659 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000660 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000661 def __len__(self):
662 return 0
663 def __getitem__(self, i):
664 raise IndexError
665 def __iter__(self):
666 return iter(())
667 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000668
669 def test_MutableMapping(self):
670 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000671 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000672 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000673 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
674 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000675
Raymond Hettinger9117c752010-08-22 07:44:24 +0000676 def test_MutableMapping_subclass(self):
677 # Test issue 9214
678 mymap = UserDict()
679 mymap['red'] = 5
680 self.assertIsInstance(mymap.keys(), Set)
681 self.assertIsInstance(mymap.keys(), KeysView)
682 self.assertIsInstance(mymap.items(), Set)
683 self.assertIsInstance(mymap.items(), ItemsView)
684
685 mymap = UserDict()
686 mymap['red'] = 5
687 z = mymap.keys() | {'orange'}
688 self.assertIsInstance(z, set)
689 list(z)
690 mymap['blue'] = 7 # Shouldn't affect 'z'
691 self.assertEqual(sorted(z), ['orange', 'red'])
692
693 mymap = UserDict()
694 mymap['red'] = 5
695 z = mymap.items() | {('orange', 3)}
696 self.assertIsInstance(z, set)
697 list(z)
698 mymap['blue'] = 7 # Shouldn't affect 'z'
699 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
700
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000701 def test_Sequence(self):
702 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000703 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000704 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000705 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000706 self.assertTrue(issubclass(range, Sequence))
707 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000708 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
709 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000710
Guido van Rossumd05eb002007-11-21 22:26:24 +0000711 def test_ByteString(self):
712 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000713 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000714 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000715 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000716 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000717 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000718 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000719 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000720
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000721 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000722 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000723 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000724 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000725 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000726 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000727 self.assertTrue(issubclass(sample, MutableSequence))
728 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000729 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
730 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000731
Eli Bendersky0716a572011-03-04 10:38:14 +0000732 def test_MutableSequence_mixins(self):
733 # Test the mixins of MutableSequence by creating a miminal concrete
734 # class inherited from it.
735 class MutableSequenceSubclass(MutableSequence):
736 def __init__(self):
737 self.lst = []
738
739 def __setitem__(self, index, value):
740 self.lst[index] = value
741
742 def __getitem__(self, index):
743 return self.lst[index]
744
745 def __len__(self):
746 return len(self.lst)
747
748 def __delitem__(self, index):
749 del self.lst[index]
750
751 def insert(self, index, value):
752 self.lst.insert(index, value)
753
754 mss = MutableSequenceSubclass()
755 mss.append(0)
756 mss.extend((1, 2, 3, 4))
757 self.assertEqual(len(mss), 5)
758 self.assertEqual(mss[3], 3)
759 mss.reverse()
760 self.assertEqual(mss[3], 1)
761 mss.pop()
762 self.assertEqual(len(mss), 4)
763 mss.remove(3)
764 self.assertEqual(len(mss), 3)
765 mss += (10, 20, 30)
766 self.assertEqual(len(mss), 6)
767 self.assertEqual(mss[-1], 30)
768 mss.clear()
769 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +0000770
771################################################################################
772### Counter
773################################################################################
774
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000775class TestCounter(unittest.TestCase):
776
777 def test_basics(self):
778 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000779 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
780 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +0000781 self.assertIsInstance(c, dict)
782 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000783 self.assertTrue(issubclass(Counter, dict))
784 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000785 self.assertEqual(len(c), 3)
786 self.assertEqual(sum(c.values()), 6)
787 self.assertEqual(sorted(c.values()), [1, 2, 3])
788 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
789 self.assertEqual(sorted(c), ['a', 'b', 'c'])
790 self.assertEqual(sorted(c.items()),
791 [('a', 3), ('b', 2), ('c', 1)])
792 self.assertEqual(c['b'], 2)
793 self.assertEqual(c['z'], 0)
794 self.assertEqual(c.__contains__('c'), True)
795 self.assertEqual(c.__contains__('z'), False)
796 self.assertEqual(c.get('b', 10), 2)
797 self.assertEqual(c.get('z', 10), 10)
798 self.assertEqual(c, dict(a=3, b=2, c=1))
799 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
800 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
801 for i in range(5):
802 self.assertEqual(c.most_common(i),
803 [('a', 3), ('b', 2), ('c', 1)][:i])
804 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
805 c['a'] += 1 # increment an existing value
806 c['b'] -= 2 # sub existing value to zero
807 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000808 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000809 c['d'] -= 2 # sub from a missing value
810 c['e'] = -5 # directly assign a missing value
811 c['f'] += 4 # add to a missing value
812 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
813 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
814 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000815 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000816 for i in range(3):
817 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000818 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000819 c.clear()
820 self.assertEqual(c, {})
821 self.assertEqual(repr(c), 'Counter()')
822 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
823 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000824 c.update(dict(a=5, b=3))
825 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000826 c.update(Counter('a' * 50 + 'b' * 30))
827 c.update() # test case with no args
828 c.__init__('a' * 500 + 'b' * 300)
829 c.__init__('cdc')
830 c.__init__()
831 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
832 self.assertEqual(c.setdefault('d', 5), 1)
833 self.assertEqual(c['d'], 1)
834 self.assertEqual(c.setdefault('e', 5), 5)
835 self.assertEqual(c['e'], 5)
836
837 def test_copying(self):
838 # Check that counters are copyable, deepcopyable, picklable, and
839 #have a repr/eval round-trip
840 words = Counter('which witch had which witches wrist watch'.split())
841 update_test = Counter()
842 update_test.update(words)
843 for i, dup in enumerate([
844 words.copy(),
845 copy.copy(words),
846 copy.deepcopy(words),
847 pickle.loads(pickle.dumps(words, 0)),
848 pickle.loads(pickle.dumps(words, 1)),
849 pickle.loads(pickle.dumps(words, 2)),
850 pickle.loads(pickle.dumps(words, -1)),
851 eval(repr(words)),
852 update_test,
853 Counter(words),
854 ]):
855 msg = (i, dup, words)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000856 self.assertTrue(dup is not words)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000857 self.assertEqual(dup, words)
858 self.assertEqual(len(dup), len(words))
859 self.assertEqual(type(dup), type(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000860
861 def test_conversions(self):
862 # Convert to: set, list, dict
863 s = 'she sells sea shells by the sea shore'
864 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
865 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
866 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
867 self.assertEqual(set(Counter(s)), set(s))
868
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000869 def test_invariant_for_the_in_operator(self):
870 c = Counter(a=10, b=-2, c=0)
871 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000872 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000873 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000874
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000875 def test_multiset_operations(self):
876 # Verify that adding a zero counter will strip zeros and negatives
877 c = Counter(a=10, b=-2, c=0) + Counter()
878 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000879
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000880 elements = 'abcd'
881 for i in range(1000):
882 # test random pairs of multisets
883 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000884 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000885 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000886 q.update(h=1, i=-1, j=0)
887 for counterop, numberop in [
888 (Counter.__add__, lambda x, y: max(0, x+y)),
889 (Counter.__sub__, lambda x, y: max(0, x-y)),
890 (Counter.__or__, lambda x, y: max(0,x,y)),
891 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000892 ]:
893 result = counterop(p, q)
894 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000895 self.assertEqual(numberop(p[x], q[x]), result[x],
896 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000897 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000898 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000899
900 elements = 'abcdef'
901 for i in range(100):
902 # verify that random multisets with no repeats are exactly like sets
903 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
904 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
905 for counterop, setop in [
906 (Counter.__sub__, set.__sub__),
907 (Counter.__or__, set.__or__),
908 (Counter.__and__, set.__and__),
909 ]:
910 counter_result = counterop(p, q)
911 set_result = setop(set(p.elements()), set(q.elements()))
912 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000913
Raymond Hettinger9c01e442010-04-03 10:32:58 +0000914 def test_subtract(self):
915 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
916 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
917 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
918 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
919 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
920 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
921 c = Counter('aaabbcd')
922 c.subtract('aaaabbcce')
923 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000924
Raymond Hettinger426e0522011-01-03 02:12:02 +0000925 def test_helper_function(self):
926 # two paths, one for real dicts and one for other mappings
927 elems = list('abracadabra')
928
929 d = dict()
930 _count_elements(d, elems)
931 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
932
933 m = OrderedDict()
934 _count_elements(m, elems)
935 self.assertEqual(m,
936 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
937
Raymond Hettinger499e1932011-02-23 07:56:53 +0000938
939################################################################################
940### OrderedDict
941################################################################################
942
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000943class TestOrderedDict(unittest.TestCase):
944
945 def test_init(self):
946 with self.assertRaises(TypeError):
947 OrderedDict([('a', 1), ('b', 2)], None) # too many args
948 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
949 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
950 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
951 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
952 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
953 c=3, e=5).items()), pairs) # mixed input
954
955 # make sure no positional args conflict with possible kwdargs
956 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
957 ['self'])
958
959 # Make sure that direct calls to __init__ do not clear previous contents
960 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
961 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
962 self.assertEqual(list(d.items()),
963 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
964
965 def test_update(self):
966 with self.assertRaises(TypeError):
967 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
968 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
969 od = OrderedDict()
970 od.update(dict(pairs))
971 self.assertEqual(sorted(od.items()), pairs) # dict input
972 od = OrderedDict()
973 od.update(**dict(pairs))
974 self.assertEqual(sorted(od.items()), pairs) # kwds input
975 od = OrderedDict()
976 od.update(pairs)
977 self.assertEqual(list(od.items()), pairs) # pairs input
978 od = OrderedDict()
979 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
980 self.assertEqual(list(od.items()), pairs) # mixed input
981
Mark Dickinsonb214e902010-07-11 18:53:06 +0000982 # Issue 9137: Named argument called 'other' or 'self'
983 # shouldn't be treated specially.
984 od = OrderedDict()
985 od.update(self=23)
986 self.assertEqual(list(od.items()), [('self', 23)])
987 od = OrderedDict()
988 od.update(other={})
989 self.assertEqual(list(od.items()), [('other', {})])
990 od = OrderedDict()
991 od.update(red=5, blue=6, other=7, self=8)
992 self.assertEqual(sorted(list(od.items())),
993 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
994
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000995 # Make sure that direct calls to update do not clear previous contents
996 # add that updates items are not moved to the end
997 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
998 d.update([('e', 5), ('f', 6)], g=7, d=4)
999 self.assertEqual(list(d.items()),
1000 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1001
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001002 def test_abc(self):
1003 self.assertIsInstance(OrderedDict(), MutableMapping)
1004 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1005
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001006 def test_clear(self):
1007 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1008 shuffle(pairs)
1009 od = OrderedDict(pairs)
1010 self.assertEqual(len(od), len(pairs))
1011 od.clear()
1012 self.assertEqual(len(od), 0)
1013
1014 def test_delitem(self):
1015 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1016 od = OrderedDict(pairs)
1017 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001018 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001019 with self.assertRaises(KeyError):
1020 del od['a']
1021 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1022
1023 def test_setitem(self):
1024 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1025 od['c'] = 10 # existing element
1026 od['f'] = 20 # new element
1027 self.assertEqual(list(od.items()),
1028 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1029
1030 def test_iterators(self):
1031 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1032 shuffle(pairs)
1033 od = OrderedDict(pairs)
1034 self.assertEqual(list(od), [t[0] for t in pairs])
1035 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1036 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1037 self.assertEqual(list(od.items()), pairs)
1038 self.assertEqual(list(reversed(od)),
1039 [t[0] for t in reversed(pairs)])
1040
1041 def test_popitem(self):
1042 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1043 shuffle(pairs)
1044 od = OrderedDict(pairs)
1045 while pairs:
1046 self.assertEqual(od.popitem(), pairs.pop())
1047 with self.assertRaises(KeyError):
1048 od.popitem()
1049 self.assertEqual(len(od), 0)
1050
1051 def test_pop(self):
1052 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1053 shuffle(pairs)
1054 od = OrderedDict(pairs)
1055 shuffle(pairs)
1056 while pairs:
1057 k, v = pairs.pop()
1058 self.assertEqual(od.pop(k), v)
1059 with self.assertRaises(KeyError):
1060 od.pop('xyz')
1061 self.assertEqual(len(od), 0)
1062 self.assertEqual(od.pop(k, 12345), 12345)
1063
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001064 # make sure pop still works when __missing__ is defined
1065 class Missing(OrderedDict):
1066 def __missing__(self, key):
1067 return 0
1068 m = Missing(a=1)
1069 self.assertEqual(m.pop('b', 5), 5)
1070 self.assertEqual(m.pop('a', 6), 1)
1071 self.assertEqual(m.pop('a', 6), 6)
1072 with self.assertRaises(KeyError):
1073 m.pop('a')
1074
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001075 def test_equality(self):
1076 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1077 shuffle(pairs)
1078 od1 = OrderedDict(pairs)
1079 od2 = OrderedDict(pairs)
1080 self.assertEqual(od1, od2) # same order implies equality
1081 pairs = pairs[2:] + pairs[:2]
1082 od2 = OrderedDict(pairs)
1083 self.assertNotEqual(od1, od2) # different order implies inequality
1084 # comparison to regular dict is not order sensitive
1085 self.assertEqual(od1, dict(od2))
1086 self.assertEqual(dict(od2), od1)
1087 # different length implied inequality
1088 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1089
1090 def test_copying(self):
1091 # Check that ordered dicts are copyable, deepcopyable, picklable,
1092 # and have a repr/eval round-trip
1093 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1094 od = OrderedDict(pairs)
1095 update_test = OrderedDict()
1096 update_test.update(od)
1097 for i, dup in enumerate([
1098 od.copy(),
1099 copy.copy(od),
1100 copy.deepcopy(od),
1101 pickle.loads(pickle.dumps(od, 0)),
1102 pickle.loads(pickle.dumps(od, 1)),
1103 pickle.loads(pickle.dumps(od, 2)),
1104 pickle.loads(pickle.dumps(od, 3)),
1105 pickle.loads(pickle.dumps(od, -1)),
1106 eval(repr(od)),
1107 update_test,
1108 OrderedDict(od),
1109 ]):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001110 self.assertTrue(dup is not od)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001111 self.assertEqual(dup, od)
1112 self.assertEqual(list(dup.items()), list(od.items()))
1113 self.assertEqual(len(dup), len(od))
1114 self.assertEqual(type(dup), type(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001115
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001116 def test_yaml_linkage(self):
1117 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1118 # In yaml, lists are native but tuples are not.
1119 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1120 od = OrderedDict(pairs)
1121 # yaml.dump(od) -->
1122 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001123 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001124
Raymond Hettingerb2121572009-03-03 22:50:04 +00001125 def test_reduce_not_too_fat(self):
1126 # do not save instance dictionary if not needed
1127 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1128 od = OrderedDict(pairs)
1129 self.assertEqual(len(od.__reduce__()), 2)
1130 od.x = 10
1131 self.assertEqual(len(od.__reduce__()), 3)
1132
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001133 def test_repr(self):
1134 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1135 self.assertEqual(repr(od),
1136 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1137 self.assertEqual(eval(repr(od)), od)
1138 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1139
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001140 def test_repr_recursive(self):
1141 # See issue #9826
1142 od = OrderedDict.fromkeys('abc')
1143 od['x'] = od
1144 self.assertEqual(repr(od),
1145 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1146
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001147 def test_setdefault(self):
1148 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1149 shuffle(pairs)
1150 od = OrderedDict(pairs)
1151 pair_order = list(od.items())
1152 self.assertEqual(od.setdefault('a', 10), 3)
1153 # make sure order didn't change
1154 self.assertEqual(list(od.items()), pair_order)
1155 self.assertEqual(od.setdefault('x', 10), 10)
1156 # make sure 'x' is added to the end
1157 self.assertEqual(list(od.items())[-1], ('x', 10))
1158
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001159 # make sure setdefault still works when __missing__ is defined
1160 class Missing(OrderedDict):
1161 def __missing__(self, key):
1162 return 0
1163 self.assertEqual(Missing().setdefault(5, 9), 9)
1164
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001165 def test_reinsert(self):
1166 # Given insert a, insert b, delete a, re-insert a,
1167 # verify that a is now later than b.
1168 od = OrderedDict()
1169 od['a'] = 1
1170 od['b'] = 2
1171 del od['a']
1172 od['a'] = 1
1173 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1174
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001175 def test_move_to_end(self):
1176 od = OrderedDict.fromkeys('abcde')
1177 self.assertEqual(list(od), list('abcde'))
1178 od.move_to_end('c')
1179 self.assertEqual(list(od), list('abdec'))
1180 od.move_to_end('c', 0)
1181 self.assertEqual(list(od), list('cabde'))
1182 od.move_to_end('c', 0)
1183 self.assertEqual(list(od), list('cabde'))
1184 od.move_to_end('e')
1185 self.assertEqual(list(od), list('cabde'))
1186 with self.assertRaises(KeyError):
1187 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001188
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001189 def test_sizeof(self):
1190 # Wimpy test: Just verify the reported size is larger than a regular dict
1191 d = dict(a=1)
1192 od = OrderedDict(**d)
1193 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1194
Raymond Hettinger32062e92011-01-01 22:38:00 +00001195 def test_override_update(self):
1196 # Verify that subclasses can override update() without breaking __init__()
1197 class MyOD(OrderedDict):
1198 def update(self, *args, **kwds):
1199 raise Exception()
1200 items = [('a', 1), ('c', 3), ('b', 2)]
1201 self.assertEqual(list(MyOD(items).items()), items)
1202
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001203class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1204 type2test = OrderedDict
1205
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001206 def test_popitem(self):
1207 d = self._empty_mapping()
1208 self.assertRaises(KeyError, d.popitem)
1209
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001210class MyOrderedDict(OrderedDict):
1211 pass
1212
1213class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1214 type2test = MyOrderedDict
1215
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001216 def test_popitem(self):
1217 d = self._empty_mapping()
1218 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001219
1220
Raymond Hettinger499e1932011-02-23 07:56:53 +00001221################################################################################
1222### Run tests
1223################################################################################
1224
Christian Heimes25bb7832008-01-11 16:17:00 +00001225import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001226
Guido van Rossumd8faa362007-04-27 19:54:29 +00001227def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001228 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001229 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001230 TestCollectionABCs, TestCounter, TestChainMap,
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001231 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001232 support.run_unittest(*test_classes)
1233 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001234
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001235
Guido van Rossumd8faa362007-04-27 19:54:29 +00001236if __name__ == "__main__":
1237 test_main(verbose=True)