blob: 5c73d7816bcea7ca4b2c6daa89ba55e54ef0815a [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
75 d.new_child()
76 d['b'] = 5
77 self.assertEqual(d.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
78 self.assertEqual(d.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
79 self.assertEqual(d['b'], 5) # find first in chain
80 self.assertEqual(d.parents['b'], 2) # look beyond maps[0]
81
82 def test_contructor(self):
83 self.assertEqual(ChainedContext().maps, [{}]) # no-args --> one new dict
84 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
85
86 def test_missing(self):
87 class DefaultChainMap(ChainMap):
88 def __missing__(self, key):
89 return 999
90 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
91 for k, v in dict(a=1, b=2, c=30, d=999).items():
92 self.assertEqual(d[k], v) # check __getitem__ w/missing
93 for k, v in dict(a=1, b=2, c=30, d=77).items():
94 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
95 for k, v in dict(a=True, b=True, c=True, d=False).items():
96 self.assertEqual(k in d, v) # check __contains__ w/missing
97 self.assertEqual(d.pop('a', 1001), 1, d)
98 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
99 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
100 with self.assertRaises(KeyError):
101 d.popitem()
102
103 def test_dict_coercion(self):
104 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
105 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
106 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
107
108
109################################################################################
110### Named Tuples
111################################################################################
112
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000113TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000114
115class TestNamedTuple(unittest.TestCase):
116
117 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000118 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000119 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000120 self.assertEqual(Point.__slots__, ())
121 self.assertEqual(Point.__module__, __name__)
122 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000123 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000124
125 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
126 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
127 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
128
129 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
130 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
131 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000132 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000133 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
134
135 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000136 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000137
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000138 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000139 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000140 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000141 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000142
Christian Heimesfaf2f632008-01-06 16:59:19 +0000143 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
144 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
145
R. David Murray378c0cf2010-02-24 01:46:21 +0000146 @unittest.skipIf(sys.flags.optimize >= 2,
147 "Docstrings are omitted with -O2 and above")
148 def test_factory_doc_attr(self):
149 Point = namedtuple('Point', 'x y')
150 self.assertEqual(Point.__doc__, 'Point(x, y)')
151
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000152 def test_name_fixer(self):
153 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000154 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
155 [('abc', 'class'), ('abc', '_1')], # field has keyword
156 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
157 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
158 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
159 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000160 ]:
161 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
162
Guido van Rossumd8faa362007-04-27 19:54:29 +0000163 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000164 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000165 p = Point(11, 22)
166 self.assertEqual(p, Point(x=11, y=22))
167 self.assertEqual(p, Point(11, y=22))
168 self.assertEqual(p, Point(y=22, x=11))
169 self.assertEqual(p, Point(*(11, 22)))
170 self.assertEqual(p, Point(**dict(x=11, y=22)))
171 self.assertRaises(TypeError, Point, 1) # too few args
172 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
173 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
174 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
175 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000176 self.assertNotIn('__dict__', dir(p)) # verify instance has no dict
177 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000178 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000179 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
180 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
181 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000182
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000183 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000184 p._replace(x=1, error=2)
185 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000186 pass
187 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000188 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000189
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000190 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000191 Point = namedtuple('Point', 'x, y')
192 p = Point(x=11, y=22)
193 self.assertEqual(repr(p), 'Point(x=11, y=22)')
194
195 # verify that fieldspec can be a non-string sequence
196 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000197 p = Point(x=11, y=22)
198 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000199
200 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000201 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000202 p = Point(11, 22)
203
Ezio Melottie9615932010-01-24 19:26:24 +0000204 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000205 self.assertEqual(p, (11, 22)) # matches a real tuple
206 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
207 self.assertEqual(list(p), [11, 22]) # coercable to a list
208 self.assertEqual(max(p), 22) # iterable
209 self.assertEqual(max(*p), 22) # star-able
210 x, y = p
211 self.assertEqual(p, (x, y)) # unpacks like a tuple
212 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
213 self.assertRaises(IndexError, p.__getitem__, 3)
214
215 self.assertEqual(p.x, x)
216 self.assertEqual(p.y, y)
217 self.assertRaises(AttributeError, eval, 'p.z', locals())
218
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000219 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000220 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000221 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000222 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000223 self.assertEqual(repr(Zero()), 'Zero()')
224 self.assertEqual(Zero()._asdict(), {})
225 self.assertEqual(Zero()._fields, ())
226
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000227 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000228 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000229 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000230 self.assertEqual(Dot(1).d, 1)
231 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
232 self.assertEqual(Dot(1)._asdict(), {'d':1})
233 self.assertEqual(Dot(1)._replace(d=999), (999,))
234 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000235
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000236 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000237 n = 254 # SyntaxError: more than 255 arguments:
238 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000239 names = list(set(''.join([random.choice(string.ascii_letters)
240 for j in range(10)]) for i in range(n)))
241 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000242 Big = namedtuple('Big', names)
243 b = Big(*range(n))
244 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000245 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000246 for pos, name in enumerate(names):
247 self.assertEqual(getattr(b, name), pos)
248 repr(b) # make sure repr() doesn't blow-up
249 d = b._asdict()
250 d_expected = dict(zip(names, range(n)))
251 self.assertEqual(d, d_expected)
252 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
253 b2_expected = list(range(n))
254 b2_expected[1] = 999
255 b2_expected[-5] = 42
256 self.assertEqual(b2, tuple(b2_expected))
257 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000258
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000259 def test_pickle(self):
260 p = TestNT(x=10, y=20, z=30)
261 for module in (pickle,):
262 loads = getattr(module, 'loads')
263 dumps = getattr(module, 'dumps')
264 for protocol in -1, 0, 1, 2:
265 q = loads(dumps(p, protocol))
266 self.assertEqual(p, q)
267 self.assertEqual(p._fields, q._fields)
268
269 def test_copy(self):
270 p = TestNT(x=10, y=20, z=30)
271 for copier in copy.copy, copy.deepcopy:
272 q = copier(p)
273 self.assertEqual(p, q)
274 self.assertEqual(p._fields, q._fields)
275
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000276 def test_name_conflicts(self):
277 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
278 # failed when used as field names. Test to make sure these now work.
279 T = namedtuple('T', 'itemgetter property self cls tuple')
280 t = T(1, 2, 3, 4, 5)
281 self.assertEqual(t, (1,2,3,4,5))
282 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
283 self.assertEqual(newt, (10,20,30,40,50))
284
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000285 # Broader test of all interesting names in a template
286 with support.captured_stdout() as template:
287 T = namedtuple('T', 'x', verbose=True)
288 words = set(re.findall('[A-Za-z]+', template.getvalue()))
289 words -= set(keyword.kwlist)
290 T = namedtuple('T', words)
291 # test __new__
292 values = tuple(range(len(words)))
293 t = T(*values)
294 self.assertEqual(t, values)
295 t = T(**dict(zip(T._fields, values)))
296 self.assertEqual(t, values)
297 # test _make
298 t = T._make(values)
299 self.assertEqual(t, values)
300 # exercise __repr__
301 repr(t)
302 # test _asdict
303 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
304 # test _replace
305 t = T._make(values)
306 newvalues = tuple(v*10 for v in values)
307 newt = t._replace(**dict(zip(T._fields, newvalues)))
308 self.assertEqual(newt, newvalues)
309 # test _fields
310 self.assertEqual(T._fields, tuple(words))
311 # test __getnewargs__
312 self.assertEqual(t.__getnewargs__(), values)
313
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000314 def test_repr(self):
315 with support.captured_stdout() as template:
316 A = namedtuple('A', 'x', verbose=True)
317 self.assertEqual(repr(A(1)), 'A(x=1)')
318 # repr should show the name of the subclass
319 class B(A):
320 pass
321 self.assertEqual(repr(B(1)), 'B(x=1)')
322
323
Raymond Hettinger499e1932011-02-23 07:56:53 +0000324################################################################################
325### Abstract Base Classes
326################################################################################
327
Raymond Hettingerae650182009-01-28 23:33:59 +0000328class ABCTestCase(unittest.TestCase):
329
330 def validate_abstract_methods(self, abc, *names):
331 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
332
333 # everything should work will all required methods are present
334 C = type('C', (abc,), methodstubs)
335 C()
336
337 # instantiation should fail if a required method is missing
338 for name in names:
339 stubs = methodstubs.copy()
340 del stubs[name]
341 C = type('C', (abc,), stubs)
342 self.assertRaises(TypeError, C, name)
343
Florent Xiclunace153f62010-03-08 15:34:35 +0000344 def validate_isinstance(self, abc, name):
345 stub = lambda s, *args: 0
346
347 C = type('C', (object,), {'__hash__': None})
348 setattr(C, name, stub)
349 self.assertIsInstance(C(), abc)
350 self.assertTrue(issubclass(C, abc))
351
352 C = type('C', (object,), {'__hash__': None})
353 self.assertNotIsInstance(C(), abc)
354 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000355
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000356 def validate_comparison(self, instance):
357 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
358 operators = {}
359 for op in ops:
360 name = '__' + op + '__'
361 operators[name] = getattr(operator, name)
362
363 class Other:
364 def __init__(self):
365 self.right_side = False
366 def __eq__(self, other):
367 self.right_side = True
368 return True
369 __lt__ = __eq__
370 __gt__ = __eq__
371 __le__ = __eq__
372 __ge__ = __eq__
373 __ne__ = __eq__
374 __ror__ = __eq__
375 __rand__ = __eq__
376 __rxor__ = __eq__
377 __rsub__ = __eq__
378
379 for name, op in operators.items():
380 if not hasattr(instance, name):
381 continue
382 other = Other()
383 op(instance, other)
384 self.assertTrue(other.right_side,'Right side not called for %s.%s'
385 % (type(instance), name))
386
Raymond Hettingerae650182009-01-28 23:33:59 +0000387class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000388
389 def test_Hashable(self):
390 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000391 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000392 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000393 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000394 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000395 # Check some hashables
396 samples = [None,
397 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000398 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000399 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000400 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000401 ]
402 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000403 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000404 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000405 self.assertRaises(TypeError, Hashable)
406 # Check direct subclassing
407 class H(Hashable):
408 def __hash__(self):
409 return super().__hash__()
410 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000411 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000412 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000413 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000414
415 def test_Iterable(self):
416 # Check some non-iterables
417 non_samples = [None, 42, 3.14, 1j]
418 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000419 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000420 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000421 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000422 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000423 tuple(), list(), set(), frozenset(), dict(),
424 dict().keys(), dict().items(), dict().values(),
425 (lambda: (yield))(),
426 (x for x in []),
427 ]
428 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000429 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000430 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000431 # Check direct subclassing
432 class I(Iterable):
433 def __iter__(self):
434 return super().__iter__()
435 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000436 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000437 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000438 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000439
440 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000441 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000442 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000443 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000444 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000445 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000446 iter(tuple()), iter(list()), iter(dict()),
447 iter(set()), iter(frozenset()),
448 iter(dict().keys()), iter(dict().items()),
449 iter(dict().values()),
450 (lambda: (yield))(),
451 (x for x in []),
452 ]
453 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000454 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000455 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000456 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
457
458 # Issue 10565
459 class NextOnly:
460 def __next__(self):
461 yield 1
462 raise StopIteration
463 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000464
465 def test_Sized(self):
466 non_samples = [None, 42, 3.14, 1j,
467 (lambda: (yield))(),
468 (x for x in []),
469 ]
470 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000471 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000472 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000473 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000474 tuple(), list(), set(), frozenset(), dict(),
475 dict().keys(), dict().items(), dict().values(),
476 ]
477 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000478 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000479 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000480 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000481 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000482
483 def test_Container(self):
484 non_samples = [None, 42, 3.14, 1j,
485 (lambda: (yield))(),
486 (x for x in []),
487 ]
488 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000489 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000490 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000491 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000492 tuple(), list(), set(), frozenset(), dict(),
493 dict().keys(), dict().items(),
494 ]
495 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000496 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000497 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000498 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000499 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000500
501 def test_Callable(self):
502 non_samples = [None, 42, 3.14, 1j,
503 "", b"", (), [], {}, set(),
504 (lambda: (yield))(),
505 (x for x in []),
506 ]
507 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000508 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000509 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000510 samples = [lambda: None,
511 type, int, object,
512 len,
513 list.append, [].append,
514 ]
515 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000516 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000517 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000518 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000519 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000520
521 def test_direct_subclassing(self):
522 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
523 class C(B):
524 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000525 self.assertTrue(issubclass(C, B))
526 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000527
528 def test_registration(self):
529 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
530 class C:
531 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000532 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000533 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000534 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000535
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000536class WithSet(MutableSet):
537
538 def __init__(self, it=()):
539 self.data = set(it)
540
541 def __len__(self):
542 return len(self.data)
543
544 def __iter__(self):
545 return iter(self.data)
546
547 def __contains__(self, item):
548 return item in self.data
549
550 def add(self, item):
551 self.data.add(item)
552
553 def discard(self, item):
554 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000555
Raymond Hettingerae650182009-01-28 23:33:59 +0000556class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000557
558 # XXX For now, we only test some virtual inheritance properties.
559 # We should also test the proper behavior of the collection ABCs
560 # as real base classes or mix-in classes.
561
562 def test_Set(self):
563 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000564 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000565 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000566 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000567 class MySet(Set):
568 def __contains__(self, x):
569 return False
570 def __len__(self):
571 return 0
572 def __iter__(self):
573 return iter([])
574 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000575
Benjamin Peterson41181742008-07-02 20:22:54 +0000576 def test_hash_Set(self):
577 class OneTwoThreeSet(Set):
578 def __init__(self):
579 self.contents = [1, 2, 3]
580 def __contains__(self, x):
581 return x in self.contents
582 def __len__(self):
583 return len(self.contents)
584 def __iter__(self):
585 return iter(self.contents)
586 def __hash__(self):
587 return self._hash()
588 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000589 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000590
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000591 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000592 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000593 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000594 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000595 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000596 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
597 'add', 'discard')
598
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000599 def test_issue_5647(self):
600 # MutableSet.__iand__ mutated the set during iteration
601 s = WithSet('abcd')
602 s &= WithSet('cdef') # This used to fail
603 self.assertEqual(set(s), set('cd'))
604
Raymond Hettingerae650182009-01-28 23:33:59 +0000605 def test_issue_4920(self):
606 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000607 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000608 __slots__=['__s']
609 def __init__(self,items=None):
610 if items is None:
611 items=[]
612 self.__s=set(items)
613 def __contains__(self,v):
614 return v in self.__s
615 def __iter__(self):
616 return iter(self.__s)
617 def __len__(self):
618 return len(self.__s)
619 def add(self,v):
620 result=v not in self.__s
621 self.__s.add(v)
622 return result
623 def discard(self,v):
624 result=v in self.__s
625 self.__s.discard(v)
626 return result
627 def __repr__(self):
628 return "MySet(%s)" % repr(list(self))
629 s = MySet([5,43,2,1])
630 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000631
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000632 def test_issue8750(self):
633 empty = WithSet()
634 full = WithSet(range(10))
635 s = WithSet(full)
636 s -= s
637 self.assertEqual(s, empty)
638 s = WithSet(full)
639 s ^= s
640 self.assertEqual(s, empty)
641 s = WithSet(full)
642 s &= s
643 self.assertEqual(s, full)
644 s |= s
645 self.assertEqual(s, full)
646
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000647 def test_Mapping(self):
648 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000649 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000650 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000651 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
652 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000653 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000654 def __len__(self):
655 return 0
656 def __getitem__(self, i):
657 raise IndexError
658 def __iter__(self):
659 return iter(())
660 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000661
662 def test_MutableMapping(self):
663 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000664 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000665 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000666 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
667 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000668
Raymond Hettinger9117c752010-08-22 07:44:24 +0000669 def test_MutableMapping_subclass(self):
670 # Test issue 9214
671 mymap = UserDict()
672 mymap['red'] = 5
673 self.assertIsInstance(mymap.keys(), Set)
674 self.assertIsInstance(mymap.keys(), KeysView)
675 self.assertIsInstance(mymap.items(), Set)
676 self.assertIsInstance(mymap.items(), ItemsView)
677
678 mymap = UserDict()
679 mymap['red'] = 5
680 z = mymap.keys() | {'orange'}
681 self.assertIsInstance(z, set)
682 list(z)
683 mymap['blue'] = 7 # Shouldn't affect 'z'
684 self.assertEqual(sorted(z), ['orange', 'red'])
685
686 mymap = UserDict()
687 mymap['red'] = 5
688 z = mymap.items() | {('orange', 3)}
689 self.assertIsInstance(z, set)
690 list(z)
691 mymap['blue'] = 7 # Shouldn't affect 'z'
692 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
693
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000694 def test_Sequence(self):
695 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000696 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000697 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000698 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000699 self.assertTrue(issubclass(range, Sequence))
700 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000701 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
702 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000703
Guido van Rossumd05eb002007-11-21 22:26:24 +0000704 def test_ByteString(self):
705 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000706 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000707 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000708 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000709 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000710 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000711 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000712 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000713
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000714 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000715 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000716 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000717 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000718 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000719 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000720 self.assertTrue(issubclass(sample, MutableSequence))
721 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000722 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
723 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000724
Raymond Hettinger499e1932011-02-23 07:56:53 +0000725
726################################################################################
727### Counter
728################################################################################
729
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000730class TestCounter(unittest.TestCase):
731
732 def test_basics(self):
733 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000734 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
735 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +0000736 self.assertIsInstance(c, dict)
737 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000738 self.assertTrue(issubclass(Counter, dict))
739 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000740 self.assertEqual(len(c), 3)
741 self.assertEqual(sum(c.values()), 6)
742 self.assertEqual(sorted(c.values()), [1, 2, 3])
743 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
744 self.assertEqual(sorted(c), ['a', 'b', 'c'])
745 self.assertEqual(sorted(c.items()),
746 [('a', 3), ('b', 2), ('c', 1)])
747 self.assertEqual(c['b'], 2)
748 self.assertEqual(c['z'], 0)
749 self.assertEqual(c.__contains__('c'), True)
750 self.assertEqual(c.__contains__('z'), False)
751 self.assertEqual(c.get('b', 10), 2)
752 self.assertEqual(c.get('z', 10), 10)
753 self.assertEqual(c, dict(a=3, b=2, c=1))
754 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
755 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
756 for i in range(5):
757 self.assertEqual(c.most_common(i),
758 [('a', 3), ('b', 2), ('c', 1)][:i])
759 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
760 c['a'] += 1 # increment an existing value
761 c['b'] -= 2 # sub existing value to zero
762 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000763 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000764 c['d'] -= 2 # sub from a missing value
765 c['e'] = -5 # directly assign a missing value
766 c['f'] += 4 # add to a missing value
767 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
768 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
769 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000770 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000771 for i in range(3):
772 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000773 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000774 c.clear()
775 self.assertEqual(c, {})
776 self.assertEqual(repr(c), 'Counter()')
777 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
778 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000779 c.update(dict(a=5, b=3))
780 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000781 c.update(Counter('a' * 50 + 'b' * 30))
782 c.update() # test case with no args
783 c.__init__('a' * 500 + 'b' * 300)
784 c.__init__('cdc')
785 c.__init__()
786 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
787 self.assertEqual(c.setdefault('d', 5), 1)
788 self.assertEqual(c['d'], 1)
789 self.assertEqual(c.setdefault('e', 5), 5)
790 self.assertEqual(c['e'], 5)
791
792 def test_copying(self):
793 # Check that counters are copyable, deepcopyable, picklable, and
794 #have a repr/eval round-trip
795 words = Counter('which witch had which witches wrist watch'.split())
796 update_test = Counter()
797 update_test.update(words)
798 for i, dup in enumerate([
799 words.copy(),
800 copy.copy(words),
801 copy.deepcopy(words),
802 pickle.loads(pickle.dumps(words, 0)),
803 pickle.loads(pickle.dumps(words, 1)),
804 pickle.loads(pickle.dumps(words, 2)),
805 pickle.loads(pickle.dumps(words, -1)),
806 eval(repr(words)),
807 update_test,
808 Counter(words),
809 ]):
810 msg = (i, dup, words)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000811 self.assertTrue(dup is not words)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000812 self.assertEqual(dup, words)
813 self.assertEqual(len(dup), len(words))
814 self.assertEqual(type(dup), type(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000815
816 def test_conversions(self):
817 # Convert to: set, list, dict
818 s = 'she sells sea shells by the sea shore'
819 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
820 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
821 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
822 self.assertEqual(set(Counter(s)), set(s))
823
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000824 def test_invariant_for_the_in_operator(self):
825 c = Counter(a=10, b=-2, c=0)
826 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000827 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000828 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000829
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000830 def test_multiset_operations(self):
831 # Verify that adding a zero counter will strip zeros and negatives
832 c = Counter(a=10, b=-2, c=0) + Counter()
833 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000834
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000835 elements = 'abcd'
836 for i in range(1000):
837 # test random pairs of multisets
838 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000839 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000840 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000841 q.update(h=1, i=-1, j=0)
842 for counterop, numberop in [
843 (Counter.__add__, lambda x, y: max(0, x+y)),
844 (Counter.__sub__, lambda x, y: max(0, x-y)),
845 (Counter.__or__, lambda x, y: max(0,x,y)),
846 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000847 ]:
848 result = counterop(p, q)
849 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000850 self.assertEqual(numberop(p[x], q[x]), result[x],
851 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000852 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000853 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000854
855 elements = 'abcdef'
856 for i in range(100):
857 # verify that random multisets with no repeats are exactly like sets
858 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
859 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
860 for counterop, setop in [
861 (Counter.__sub__, set.__sub__),
862 (Counter.__or__, set.__or__),
863 (Counter.__and__, set.__and__),
864 ]:
865 counter_result = counterop(p, q)
866 set_result = setop(set(p.elements()), set(q.elements()))
867 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000868
Raymond Hettinger9c01e442010-04-03 10:32:58 +0000869 def test_subtract(self):
870 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
871 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
872 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
873 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
874 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
875 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
876 c = Counter('aaabbcd')
877 c.subtract('aaaabbcce')
878 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000879
Raymond Hettinger426e0522011-01-03 02:12:02 +0000880 def test_helper_function(self):
881 # two paths, one for real dicts and one for other mappings
882 elems = list('abracadabra')
883
884 d = dict()
885 _count_elements(d, elems)
886 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
887
888 m = OrderedDict()
889 _count_elements(m, elems)
890 self.assertEqual(m,
891 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
892
Raymond Hettinger499e1932011-02-23 07:56:53 +0000893
894################################################################################
895### OrderedDict
896################################################################################
897
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000898class TestOrderedDict(unittest.TestCase):
899
900 def test_init(self):
901 with self.assertRaises(TypeError):
902 OrderedDict([('a', 1), ('b', 2)], None) # too many args
903 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
904 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
905 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
906 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
907 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
908 c=3, e=5).items()), pairs) # mixed input
909
910 # make sure no positional args conflict with possible kwdargs
911 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
912 ['self'])
913
914 # Make sure that direct calls to __init__ do not clear previous contents
915 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
916 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
917 self.assertEqual(list(d.items()),
918 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
919
920 def test_update(self):
921 with self.assertRaises(TypeError):
922 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
923 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
924 od = OrderedDict()
925 od.update(dict(pairs))
926 self.assertEqual(sorted(od.items()), pairs) # dict input
927 od = OrderedDict()
928 od.update(**dict(pairs))
929 self.assertEqual(sorted(od.items()), pairs) # kwds input
930 od = OrderedDict()
931 od.update(pairs)
932 self.assertEqual(list(od.items()), pairs) # pairs input
933 od = OrderedDict()
934 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
935 self.assertEqual(list(od.items()), pairs) # mixed input
936
Mark Dickinsonb214e902010-07-11 18:53:06 +0000937 # Issue 9137: Named argument called 'other' or 'self'
938 # shouldn't be treated specially.
939 od = OrderedDict()
940 od.update(self=23)
941 self.assertEqual(list(od.items()), [('self', 23)])
942 od = OrderedDict()
943 od.update(other={})
944 self.assertEqual(list(od.items()), [('other', {})])
945 od = OrderedDict()
946 od.update(red=5, blue=6, other=7, self=8)
947 self.assertEqual(sorted(list(od.items())),
948 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
949
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000950 # Make sure that direct calls to update do not clear previous contents
951 # add that updates items are not moved to the end
952 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
953 d.update([('e', 5), ('f', 6)], g=7, d=4)
954 self.assertEqual(list(d.items()),
955 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
956
Raymond Hettinger345c49b2011-01-01 23:51:55 +0000957 def test_abc(self):
958 self.assertIsInstance(OrderedDict(), MutableMapping)
959 self.assertTrue(issubclass(OrderedDict, MutableMapping))
960
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000961 def test_clear(self):
962 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
963 shuffle(pairs)
964 od = OrderedDict(pairs)
965 self.assertEqual(len(od), len(pairs))
966 od.clear()
967 self.assertEqual(len(od), 0)
968
969 def test_delitem(self):
970 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
971 od = OrderedDict(pairs)
972 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +0000973 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000974 with self.assertRaises(KeyError):
975 del od['a']
976 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
977
978 def test_setitem(self):
979 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
980 od['c'] = 10 # existing element
981 od['f'] = 20 # new element
982 self.assertEqual(list(od.items()),
983 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
984
985 def test_iterators(self):
986 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
987 shuffle(pairs)
988 od = OrderedDict(pairs)
989 self.assertEqual(list(od), [t[0] for t in pairs])
990 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
991 self.assertEqual(list(od.values()), [t[1] for t in pairs])
992 self.assertEqual(list(od.items()), pairs)
993 self.assertEqual(list(reversed(od)),
994 [t[0] for t in reversed(pairs)])
995
996 def test_popitem(self):
997 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
998 shuffle(pairs)
999 od = OrderedDict(pairs)
1000 while pairs:
1001 self.assertEqual(od.popitem(), pairs.pop())
1002 with self.assertRaises(KeyError):
1003 od.popitem()
1004 self.assertEqual(len(od), 0)
1005
1006 def test_pop(self):
1007 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1008 shuffle(pairs)
1009 od = OrderedDict(pairs)
1010 shuffle(pairs)
1011 while pairs:
1012 k, v = pairs.pop()
1013 self.assertEqual(od.pop(k), v)
1014 with self.assertRaises(KeyError):
1015 od.pop('xyz')
1016 self.assertEqual(len(od), 0)
1017 self.assertEqual(od.pop(k, 12345), 12345)
1018
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001019 # make sure pop still works when __missing__ is defined
1020 class Missing(OrderedDict):
1021 def __missing__(self, key):
1022 return 0
1023 m = Missing(a=1)
1024 self.assertEqual(m.pop('b', 5), 5)
1025 self.assertEqual(m.pop('a', 6), 1)
1026 self.assertEqual(m.pop('a', 6), 6)
1027 with self.assertRaises(KeyError):
1028 m.pop('a')
1029
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001030 def test_equality(self):
1031 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1032 shuffle(pairs)
1033 od1 = OrderedDict(pairs)
1034 od2 = OrderedDict(pairs)
1035 self.assertEqual(od1, od2) # same order implies equality
1036 pairs = pairs[2:] + pairs[:2]
1037 od2 = OrderedDict(pairs)
1038 self.assertNotEqual(od1, od2) # different order implies inequality
1039 # comparison to regular dict is not order sensitive
1040 self.assertEqual(od1, dict(od2))
1041 self.assertEqual(dict(od2), od1)
1042 # different length implied inequality
1043 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1044
1045 def test_copying(self):
1046 # Check that ordered dicts are copyable, deepcopyable, picklable,
1047 # and have a repr/eval round-trip
1048 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1049 od = OrderedDict(pairs)
1050 update_test = OrderedDict()
1051 update_test.update(od)
1052 for i, dup in enumerate([
1053 od.copy(),
1054 copy.copy(od),
1055 copy.deepcopy(od),
1056 pickle.loads(pickle.dumps(od, 0)),
1057 pickle.loads(pickle.dumps(od, 1)),
1058 pickle.loads(pickle.dumps(od, 2)),
1059 pickle.loads(pickle.dumps(od, 3)),
1060 pickle.loads(pickle.dumps(od, -1)),
1061 eval(repr(od)),
1062 update_test,
1063 OrderedDict(od),
1064 ]):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001065 self.assertTrue(dup is not od)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001066 self.assertEqual(dup, od)
1067 self.assertEqual(list(dup.items()), list(od.items()))
1068 self.assertEqual(len(dup), len(od))
1069 self.assertEqual(type(dup), type(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001070
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001071 def test_yaml_linkage(self):
1072 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1073 # In yaml, lists are native but tuples are not.
1074 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1075 od = OrderedDict(pairs)
1076 # yaml.dump(od) -->
1077 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001078 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001079
Raymond Hettingerb2121572009-03-03 22:50:04 +00001080 def test_reduce_not_too_fat(self):
1081 # do not save instance dictionary if not needed
1082 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1083 od = OrderedDict(pairs)
1084 self.assertEqual(len(od.__reduce__()), 2)
1085 od.x = 10
1086 self.assertEqual(len(od.__reduce__()), 3)
1087
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001088 def test_repr(self):
1089 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1090 self.assertEqual(repr(od),
1091 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1092 self.assertEqual(eval(repr(od)), od)
1093 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1094
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001095 def test_repr_recursive(self):
1096 # See issue #9826
1097 od = OrderedDict.fromkeys('abc')
1098 od['x'] = od
1099 self.assertEqual(repr(od),
1100 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1101
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001102 def test_setdefault(self):
1103 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1104 shuffle(pairs)
1105 od = OrderedDict(pairs)
1106 pair_order = list(od.items())
1107 self.assertEqual(od.setdefault('a', 10), 3)
1108 # make sure order didn't change
1109 self.assertEqual(list(od.items()), pair_order)
1110 self.assertEqual(od.setdefault('x', 10), 10)
1111 # make sure 'x' is added to the end
1112 self.assertEqual(list(od.items())[-1], ('x', 10))
1113
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001114 # make sure setdefault still works when __missing__ is defined
1115 class Missing(OrderedDict):
1116 def __missing__(self, key):
1117 return 0
1118 self.assertEqual(Missing().setdefault(5, 9), 9)
1119
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001120 def test_reinsert(self):
1121 # Given insert a, insert b, delete a, re-insert a,
1122 # verify that a is now later than b.
1123 od = OrderedDict()
1124 od['a'] = 1
1125 od['b'] = 2
1126 del od['a']
1127 od['a'] = 1
1128 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1129
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001130 def test_move_to_end(self):
1131 od = OrderedDict.fromkeys('abcde')
1132 self.assertEqual(list(od), list('abcde'))
1133 od.move_to_end('c')
1134 self.assertEqual(list(od), list('abdec'))
1135 od.move_to_end('c', 0)
1136 self.assertEqual(list(od), list('cabde'))
1137 od.move_to_end('c', 0)
1138 self.assertEqual(list(od), list('cabde'))
1139 od.move_to_end('e')
1140 self.assertEqual(list(od), list('cabde'))
1141 with self.assertRaises(KeyError):
1142 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001143
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001144 def test_sizeof(self):
1145 # Wimpy test: Just verify the reported size is larger than a regular dict
1146 d = dict(a=1)
1147 od = OrderedDict(**d)
1148 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1149
Raymond Hettinger32062e92011-01-01 22:38:00 +00001150 def test_override_update(self):
1151 # Verify that subclasses can override update() without breaking __init__()
1152 class MyOD(OrderedDict):
1153 def update(self, *args, **kwds):
1154 raise Exception()
1155 items = [('a', 1), ('c', 3), ('b', 2)]
1156 self.assertEqual(list(MyOD(items).items()), items)
1157
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001158class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1159 type2test = OrderedDict
1160
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001161 def test_popitem(self):
1162 d = self._empty_mapping()
1163 self.assertRaises(KeyError, d.popitem)
1164
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001165class MyOrderedDict(OrderedDict):
1166 pass
1167
1168class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1169 type2test = MyOrderedDict
1170
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001171 def test_popitem(self):
1172 d = self._empty_mapping()
1173 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001174
1175
Raymond Hettinger499e1932011-02-23 07:56:53 +00001176################################################################################
1177### Run tests
1178################################################################################
1179
Christian Heimes25bb7832008-01-11 16:17:00 +00001180import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001181
Guido van Rossumd8faa362007-04-27 19:54:29 +00001182def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001183 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001184 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001185 TestCollectionABCs, TestCounter,
1186 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001187 support.run_unittest(*test_classes)
1188 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001189
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001190
Guido van Rossumd8faa362007-04-27 19:54:29 +00001191if __name__ == "__main__":
1192 test_main(verbose=True)