blob: 4eaa091af48c49db73f4290b5078d923e681a9cb [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
14from collections.abc import Hashable, Iterable, Iterator
15from collections.abc import Sized, Container, Callable
16from collections.abc import Set, MutableSet
17from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
18from collections.abc import Sequence, MutableSequence
19from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000020
Georg Brandlc28e1fa2008-06-10 19:20:26 +000021TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +000022
23class TestNamedTuple(unittest.TestCase):
24
25 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000026 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000027 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +000028 self.assertEqual(Point.__slots__, ())
29 self.assertEqual(Point.__module__, __name__)
30 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +000031 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +000032
33 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
34 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
35 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
36
37 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
38 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
39 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +000040 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +000041 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
42
43 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +000044 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +000045
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +000046 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +000047 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +000048 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +000049 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +000050
Christian Heimesfaf2f632008-01-06 16:59:19 +000051 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
52 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
53
R. David Murray378c0cf2010-02-24 01:46:21 +000054 @unittest.skipIf(sys.flags.optimize >= 2,
55 "Docstrings are omitted with -O2 and above")
56 def test_factory_doc_attr(self):
57 Point = namedtuple('Point', 'x y')
58 self.assertEqual(Point.__doc__, 'Point(x, y)')
59
Benjamin Petersona86f2c02009-02-10 02:41:10 +000060 def test_name_fixer(self):
61 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +000062 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
63 [('abc', 'class'), ('abc', '_1')], # field has keyword
64 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
65 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
66 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
67 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +000068 ]:
69 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
70
Guido van Rossumd8faa362007-04-27 19:54:29 +000071 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000072 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000073 p = Point(11, 22)
74 self.assertEqual(p, Point(x=11, y=22))
75 self.assertEqual(p, Point(11, y=22))
76 self.assertEqual(p, Point(y=22, x=11))
77 self.assertEqual(p, Point(*(11, 22)))
78 self.assertEqual(p, Point(**dict(x=11, y=22)))
79 self.assertRaises(TypeError, Point, 1) # too few args
80 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
81 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
82 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
83 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +000084 self.assertNotIn('__dict__', dir(p)) # verify instance has no dict
85 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +000086 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +000087 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
88 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
89 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +000090
Guido van Rossum3d392eb2007-11-16 00:35:22 +000091 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +000092 p._replace(x=1, error=2)
93 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +000094 pass
95 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +000096 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +000097
Thomas Wouters1b7f8912007-09-19 03:06:30 +000098 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +000099 Point = namedtuple('Point', 'x, y')
100 p = Point(x=11, y=22)
101 self.assertEqual(repr(p), 'Point(x=11, y=22)')
102
103 # verify that fieldspec can be a non-string sequence
104 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000105 p = Point(x=11, y=22)
106 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000107
108 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000109 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000110 p = Point(11, 22)
111
Ezio Melottie9615932010-01-24 19:26:24 +0000112 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000113 self.assertEqual(p, (11, 22)) # matches a real tuple
114 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
115 self.assertEqual(list(p), [11, 22]) # coercable to a list
116 self.assertEqual(max(p), 22) # iterable
117 self.assertEqual(max(*p), 22) # star-able
118 x, y = p
119 self.assertEqual(p, (x, y)) # unpacks like a tuple
120 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
121 self.assertRaises(IndexError, p.__getitem__, 3)
122
123 self.assertEqual(p.x, x)
124 self.assertEqual(p.y, y)
125 self.assertRaises(AttributeError, eval, 'p.z', locals())
126
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000127 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000128 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000130 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000131 self.assertEqual(repr(Zero()), 'Zero()')
132 self.assertEqual(Zero()._asdict(), {})
133 self.assertEqual(Zero()._fields, ())
134
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000135 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000136 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000137 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000138 self.assertEqual(Dot(1).d, 1)
139 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
140 self.assertEqual(Dot(1)._asdict(), {'d':1})
141 self.assertEqual(Dot(1)._replace(d=999), (999,))
142 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000143
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000144 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000145 n = 254 # SyntaxError: more than 255 arguments:
146 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000147 names = list(set(''.join([random.choice(string.ascii_letters)
148 for j in range(10)]) for i in range(n)))
149 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000150 Big = namedtuple('Big', names)
151 b = Big(*range(n))
152 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000153 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000154 for pos, name in enumerate(names):
155 self.assertEqual(getattr(b, name), pos)
156 repr(b) # make sure repr() doesn't blow-up
157 d = b._asdict()
158 d_expected = dict(zip(names, range(n)))
159 self.assertEqual(d, d_expected)
160 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
161 b2_expected = list(range(n))
162 b2_expected[1] = 999
163 b2_expected[-5] = 42
164 self.assertEqual(b2, tuple(b2_expected))
165 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000166
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000167 def test_pickle(self):
168 p = TestNT(x=10, y=20, z=30)
169 for module in (pickle,):
170 loads = getattr(module, 'loads')
171 dumps = getattr(module, 'dumps')
172 for protocol in -1, 0, 1, 2:
173 q = loads(dumps(p, protocol))
174 self.assertEqual(p, q)
175 self.assertEqual(p._fields, q._fields)
176
177 def test_copy(self):
178 p = TestNT(x=10, y=20, z=30)
179 for copier in copy.copy, copy.deepcopy:
180 q = copier(p)
181 self.assertEqual(p, q)
182 self.assertEqual(p._fields, q._fields)
183
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000184 def test_name_conflicts(self):
185 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
186 # failed when used as field names. Test to make sure these now work.
187 T = namedtuple('T', 'itemgetter property self cls tuple')
188 t = T(1, 2, 3, 4, 5)
189 self.assertEqual(t, (1,2,3,4,5))
190 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
191 self.assertEqual(newt, (10,20,30,40,50))
192
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000193 # Broader test of all interesting names in a template
194 with support.captured_stdout() as template:
195 T = namedtuple('T', 'x', verbose=True)
196 words = set(re.findall('[A-Za-z]+', template.getvalue()))
197 words -= set(keyword.kwlist)
198 T = namedtuple('T', words)
199 # test __new__
200 values = tuple(range(len(words)))
201 t = T(*values)
202 self.assertEqual(t, values)
203 t = T(**dict(zip(T._fields, values)))
204 self.assertEqual(t, values)
205 # test _make
206 t = T._make(values)
207 self.assertEqual(t, values)
208 # exercise __repr__
209 repr(t)
210 # test _asdict
211 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
212 # test _replace
213 t = T._make(values)
214 newvalues = tuple(v*10 for v in values)
215 newt = t._replace(**dict(zip(T._fields, newvalues)))
216 self.assertEqual(newt, newvalues)
217 # test _fields
218 self.assertEqual(T._fields, tuple(words))
219 # test __getnewargs__
220 self.assertEqual(t.__getnewargs__(), values)
221
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000222 def test_repr(self):
223 with support.captured_stdout() as template:
224 A = namedtuple('A', 'x', verbose=True)
225 self.assertEqual(repr(A(1)), 'A(x=1)')
226 # repr should show the name of the subclass
227 class B(A):
228 pass
229 self.assertEqual(repr(B(1)), 'B(x=1)')
230
231
Raymond Hettingerae650182009-01-28 23:33:59 +0000232class ABCTestCase(unittest.TestCase):
233
234 def validate_abstract_methods(self, abc, *names):
235 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
236
237 # everything should work will all required methods are present
238 C = type('C', (abc,), methodstubs)
239 C()
240
241 # instantiation should fail if a required method is missing
242 for name in names:
243 stubs = methodstubs.copy()
244 del stubs[name]
245 C = type('C', (abc,), stubs)
246 self.assertRaises(TypeError, C, name)
247
Florent Xiclunace153f62010-03-08 15:34:35 +0000248 def validate_isinstance(self, abc, name):
249 stub = lambda s, *args: 0
250
251 C = type('C', (object,), {'__hash__': None})
252 setattr(C, name, stub)
253 self.assertIsInstance(C(), abc)
254 self.assertTrue(issubclass(C, abc))
255
256 C = type('C', (object,), {'__hash__': None})
257 self.assertNotIsInstance(C(), abc)
258 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000259
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000260 def validate_comparison(self, instance):
261 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
262 operators = {}
263 for op in ops:
264 name = '__' + op + '__'
265 operators[name] = getattr(operator, name)
266
267 class Other:
268 def __init__(self):
269 self.right_side = False
270 def __eq__(self, other):
271 self.right_side = True
272 return True
273 __lt__ = __eq__
274 __gt__ = __eq__
275 __le__ = __eq__
276 __ge__ = __eq__
277 __ne__ = __eq__
278 __ror__ = __eq__
279 __rand__ = __eq__
280 __rxor__ = __eq__
281 __rsub__ = __eq__
282
283 for name, op in operators.items():
284 if not hasattr(instance, name):
285 continue
286 other = Other()
287 op(instance, other)
288 self.assertTrue(other.right_side,'Right side not called for %s.%s'
289 % (type(instance), name))
290
Raymond Hettingerae650182009-01-28 23:33:59 +0000291class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000292
293 def test_Hashable(self):
294 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000295 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000296 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000297 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000298 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000299 # Check some hashables
300 samples = [None,
301 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000302 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000303 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000304 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000305 ]
306 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000307 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000308 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000309 self.assertRaises(TypeError, Hashable)
310 # Check direct subclassing
311 class H(Hashable):
312 def __hash__(self):
313 return super().__hash__()
314 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000315 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000316 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000317 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000318
319 def test_Iterable(self):
320 # Check some non-iterables
321 non_samples = [None, 42, 3.14, 1j]
322 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000323 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000324 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000325 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000326 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000327 tuple(), list(), set(), frozenset(), dict(),
328 dict().keys(), dict().items(), dict().values(),
329 (lambda: (yield))(),
330 (x for x in []),
331 ]
332 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000333 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000334 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000335 # Check direct subclassing
336 class I(Iterable):
337 def __iter__(self):
338 return super().__iter__()
339 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000340 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000341 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000342 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000343
344 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000345 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000346 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000347 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000348 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000349 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000350 iter(tuple()), iter(list()), iter(dict()),
351 iter(set()), iter(frozenset()),
352 iter(dict().keys()), iter(dict().items()),
353 iter(dict().values()),
354 (lambda: (yield))(),
355 (x for x in []),
356 ]
357 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000358 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000359 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000360 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
361
362 # Issue 10565
363 class NextOnly:
364 def __next__(self):
365 yield 1
366 raise StopIteration
367 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000368
369 def test_Sized(self):
370 non_samples = [None, 42, 3.14, 1j,
371 (lambda: (yield))(),
372 (x for x in []),
373 ]
374 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000375 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000376 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000377 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000378 tuple(), list(), set(), frozenset(), dict(),
379 dict().keys(), dict().items(), dict().values(),
380 ]
381 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000382 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000383 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000384 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000385 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000386
387 def test_Container(self):
388 non_samples = [None, 42, 3.14, 1j,
389 (lambda: (yield))(),
390 (x for x in []),
391 ]
392 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000393 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000394 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000395 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000396 tuple(), list(), set(), frozenset(), dict(),
397 dict().keys(), dict().items(),
398 ]
399 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000400 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000401 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000402 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000403 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000404
405 def test_Callable(self):
406 non_samples = [None, 42, 3.14, 1j,
407 "", b"", (), [], {}, set(),
408 (lambda: (yield))(),
409 (x for x in []),
410 ]
411 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000412 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000413 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000414 samples = [lambda: None,
415 type, int, object,
416 len,
417 list.append, [].append,
418 ]
419 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000420 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000421 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000422 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000423 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000424
425 def test_direct_subclassing(self):
426 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
427 class C(B):
428 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000429 self.assertTrue(issubclass(C, B))
430 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000431
432 def test_registration(self):
433 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
434 class C:
435 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000436 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000437 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000438 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000439
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000440class WithSet(MutableSet):
441
442 def __init__(self, it=()):
443 self.data = set(it)
444
445 def __len__(self):
446 return len(self.data)
447
448 def __iter__(self):
449 return iter(self.data)
450
451 def __contains__(self, item):
452 return item in self.data
453
454 def add(self, item):
455 self.data.add(item)
456
457 def discard(self, item):
458 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000459
Raymond Hettingerae650182009-01-28 23:33:59 +0000460class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000461
462 # XXX For now, we only test some virtual inheritance properties.
463 # We should also test the proper behavior of the collection ABCs
464 # as real base classes or mix-in classes.
465
466 def test_Set(self):
467 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000468 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000469 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000470 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000471 class MySet(Set):
472 def __contains__(self, x):
473 return False
474 def __len__(self):
475 return 0
476 def __iter__(self):
477 return iter([])
478 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000479
Benjamin Peterson41181742008-07-02 20:22:54 +0000480 def test_hash_Set(self):
481 class OneTwoThreeSet(Set):
482 def __init__(self):
483 self.contents = [1, 2, 3]
484 def __contains__(self, x):
485 return x in self.contents
486 def __len__(self):
487 return len(self.contents)
488 def __iter__(self):
489 return iter(self.contents)
490 def __hash__(self):
491 return self._hash()
492 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000493 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000494
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000495 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000496 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000497 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000498 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000499 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000500 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
501 'add', 'discard')
502
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000503 def test_issue_5647(self):
504 # MutableSet.__iand__ mutated the set during iteration
505 s = WithSet('abcd')
506 s &= WithSet('cdef') # This used to fail
507 self.assertEqual(set(s), set('cd'))
508
Raymond Hettingerae650182009-01-28 23:33:59 +0000509 def test_issue_4920(self):
510 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000511 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000512 __slots__=['__s']
513 def __init__(self,items=None):
514 if items is None:
515 items=[]
516 self.__s=set(items)
517 def __contains__(self,v):
518 return v in self.__s
519 def __iter__(self):
520 return iter(self.__s)
521 def __len__(self):
522 return len(self.__s)
523 def add(self,v):
524 result=v not in self.__s
525 self.__s.add(v)
526 return result
527 def discard(self,v):
528 result=v in self.__s
529 self.__s.discard(v)
530 return result
531 def __repr__(self):
532 return "MySet(%s)" % repr(list(self))
533 s = MySet([5,43,2,1])
534 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000535
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000536 def test_issue8750(self):
537 empty = WithSet()
538 full = WithSet(range(10))
539 s = WithSet(full)
540 s -= s
541 self.assertEqual(s, empty)
542 s = WithSet(full)
543 s ^= s
544 self.assertEqual(s, empty)
545 s = WithSet(full)
546 s &= s
547 self.assertEqual(s, full)
548 s |= s
549 self.assertEqual(s, full)
550
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000551 def test_Mapping(self):
552 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000553 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000554 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000555 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
556 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000557 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000558 def __len__(self):
559 return 0
560 def __getitem__(self, i):
561 raise IndexError
562 def __iter__(self):
563 return iter(())
564 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000565
566 def test_MutableMapping(self):
567 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000568 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000569 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000570 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
571 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000572
Raymond Hettinger9117c752010-08-22 07:44:24 +0000573 def test_MutableMapping_subclass(self):
574 # Test issue 9214
575 mymap = UserDict()
576 mymap['red'] = 5
577 self.assertIsInstance(mymap.keys(), Set)
578 self.assertIsInstance(mymap.keys(), KeysView)
579 self.assertIsInstance(mymap.items(), Set)
580 self.assertIsInstance(mymap.items(), ItemsView)
581
582 mymap = UserDict()
583 mymap['red'] = 5
584 z = mymap.keys() | {'orange'}
585 self.assertIsInstance(z, set)
586 list(z)
587 mymap['blue'] = 7 # Shouldn't affect 'z'
588 self.assertEqual(sorted(z), ['orange', 'red'])
589
590 mymap = UserDict()
591 mymap['red'] = 5
592 z = mymap.items() | {('orange', 3)}
593 self.assertIsInstance(z, set)
594 list(z)
595 mymap['blue'] = 7 # Shouldn't affect 'z'
596 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
597
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000598 def test_Sequence(self):
599 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000600 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000601 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000602 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000603 self.assertTrue(issubclass(range, Sequence))
604 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000605 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
606 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000607
Guido van Rossumd05eb002007-11-21 22:26:24 +0000608 def test_ByteString(self):
609 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000610 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000611 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000612 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000613 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000614 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000615 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000616 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000617
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000618 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000619 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000620 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000621 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000622 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000623 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000624 self.assertTrue(issubclass(sample, MutableSequence))
625 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000626 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
627 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000628
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000629class TestCounter(unittest.TestCase):
630
631 def test_basics(self):
632 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000633 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
634 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +0000635 self.assertIsInstance(c, dict)
636 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000637 self.assertTrue(issubclass(Counter, dict))
638 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000639 self.assertEqual(len(c), 3)
640 self.assertEqual(sum(c.values()), 6)
641 self.assertEqual(sorted(c.values()), [1, 2, 3])
642 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
643 self.assertEqual(sorted(c), ['a', 'b', 'c'])
644 self.assertEqual(sorted(c.items()),
645 [('a', 3), ('b', 2), ('c', 1)])
646 self.assertEqual(c['b'], 2)
647 self.assertEqual(c['z'], 0)
648 self.assertEqual(c.__contains__('c'), True)
649 self.assertEqual(c.__contains__('z'), False)
650 self.assertEqual(c.get('b', 10), 2)
651 self.assertEqual(c.get('z', 10), 10)
652 self.assertEqual(c, dict(a=3, b=2, c=1))
653 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
654 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
655 for i in range(5):
656 self.assertEqual(c.most_common(i),
657 [('a', 3), ('b', 2), ('c', 1)][:i])
658 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
659 c['a'] += 1 # increment an existing value
660 c['b'] -= 2 # sub existing value to zero
661 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000662 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000663 c['d'] -= 2 # sub from a missing value
664 c['e'] = -5 # directly assign a missing value
665 c['f'] += 4 # add to a missing value
666 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
667 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
668 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000669 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000670 for i in range(3):
671 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000672 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000673 c.clear()
674 self.assertEqual(c, {})
675 self.assertEqual(repr(c), 'Counter()')
676 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
677 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000678 c.update(dict(a=5, b=3))
679 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000680 c.update(Counter('a' * 50 + 'b' * 30))
681 c.update() # test case with no args
682 c.__init__('a' * 500 + 'b' * 300)
683 c.__init__('cdc')
684 c.__init__()
685 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
686 self.assertEqual(c.setdefault('d', 5), 1)
687 self.assertEqual(c['d'], 1)
688 self.assertEqual(c.setdefault('e', 5), 5)
689 self.assertEqual(c['e'], 5)
690
691 def test_copying(self):
692 # Check that counters are copyable, deepcopyable, picklable, and
693 #have a repr/eval round-trip
694 words = Counter('which witch had which witches wrist watch'.split())
695 update_test = Counter()
696 update_test.update(words)
697 for i, dup in enumerate([
698 words.copy(),
699 copy.copy(words),
700 copy.deepcopy(words),
701 pickle.loads(pickle.dumps(words, 0)),
702 pickle.loads(pickle.dumps(words, 1)),
703 pickle.loads(pickle.dumps(words, 2)),
704 pickle.loads(pickle.dumps(words, -1)),
705 eval(repr(words)),
706 update_test,
707 Counter(words),
708 ]):
709 msg = (i, dup, words)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000710 self.assertTrue(dup is not words)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000711 self.assertEqual(dup, words)
712 self.assertEqual(len(dup), len(words))
713 self.assertEqual(type(dup), type(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000714
715 def test_conversions(self):
716 # Convert to: set, list, dict
717 s = 'she sells sea shells by the sea shore'
718 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
719 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
720 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
721 self.assertEqual(set(Counter(s)), set(s))
722
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000723 def test_invariant_for_the_in_operator(self):
724 c = Counter(a=10, b=-2, c=0)
725 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000726 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000727 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000728
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000729 def test_multiset_operations(self):
730 # Verify that adding a zero counter will strip zeros and negatives
731 c = Counter(a=10, b=-2, c=0) + Counter()
732 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000733
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000734 elements = 'abcd'
735 for i in range(1000):
736 # test random pairs of multisets
737 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000738 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000739 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000740 q.update(h=1, i=-1, j=0)
741 for counterop, numberop in [
742 (Counter.__add__, lambda x, y: max(0, x+y)),
743 (Counter.__sub__, lambda x, y: max(0, x-y)),
744 (Counter.__or__, lambda x, y: max(0,x,y)),
745 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000746 ]:
747 result = counterop(p, q)
748 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000749 self.assertEqual(numberop(p[x], q[x]), result[x],
750 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000751 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000752 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000753
754 elements = 'abcdef'
755 for i in range(100):
756 # verify that random multisets with no repeats are exactly like sets
757 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
758 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
759 for counterop, setop in [
760 (Counter.__sub__, set.__sub__),
761 (Counter.__or__, set.__or__),
762 (Counter.__and__, set.__and__),
763 ]:
764 counter_result = counterop(p, q)
765 set_result = setop(set(p.elements()), set(q.elements()))
766 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000767
Raymond Hettinger9c01e442010-04-03 10:32:58 +0000768 def test_subtract(self):
769 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
770 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
771 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
772 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
773 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
774 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
775 c = Counter('aaabbcd')
776 c.subtract('aaaabbcce')
777 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000778
Raymond Hettinger426e0522011-01-03 02:12:02 +0000779 def test_helper_function(self):
780 # two paths, one for real dicts and one for other mappings
781 elems = list('abracadabra')
782
783 d = dict()
784 _count_elements(d, elems)
785 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
786
787 m = OrderedDict()
788 _count_elements(m, elems)
789 self.assertEqual(m,
790 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
791
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000792class TestOrderedDict(unittest.TestCase):
793
794 def test_init(self):
795 with self.assertRaises(TypeError):
796 OrderedDict([('a', 1), ('b', 2)], None) # too many args
797 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
798 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
799 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
800 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
801 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
802 c=3, e=5).items()), pairs) # mixed input
803
804 # make sure no positional args conflict with possible kwdargs
805 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
806 ['self'])
807
808 # Make sure that direct calls to __init__ do not clear previous contents
809 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
810 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
811 self.assertEqual(list(d.items()),
812 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
813
814 def test_update(self):
815 with self.assertRaises(TypeError):
816 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
817 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
818 od = OrderedDict()
819 od.update(dict(pairs))
820 self.assertEqual(sorted(od.items()), pairs) # dict input
821 od = OrderedDict()
822 od.update(**dict(pairs))
823 self.assertEqual(sorted(od.items()), pairs) # kwds input
824 od = OrderedDict()
825 od.update(pairs)
826 self.assertEqual(list(od.items()), pairs) # pairs input
827 od = OrderedDict()
828 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
829 self.assertEqual(list(od.items()), pairs) # mixed input
830
Mark Dickinsonb214e902010-07-11 18:53:06 +0000831 # Issue 9137: Named argument called 'other' or 'self'
832 # shouldn't be treated specially.
833 od = OrderedDict()
834 od.update(self=23)
835 self.assertEqual(list(od.items()), [('self', 23)])
836 od = OrderedDict()
837 od.update(other={})
838 self.assertEqual(list(od.items()), [('other', {})])
839 od = OrderedDict()
840 od.update(red=5, blue=6, other=7, self=8)
841 self.assertEqual(sorted(list(od.items())),
842 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
843
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000844 # Make sure that direct calls to update do not clear previous contents
845 # add that updates items are not moved to the end
846 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
847 d.update([('e', 5), ('f', 6)], g=7, d=4)
848 self.assertEqual(list(d.items()),
849 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
850
Raymond Hettinger345c49b2011-01-01 23:51:55 +0000851 def test_abc(self):
852 self.assertIsInstance(OrderedDict(), MutableMapping)
853 self.assertTrue(issubclass(OrderedDict, MutableMapping))
854
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000855 def test_clear(self):
856 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
857 shuffle(pairs)
858 od = OrderedDict(pairs)
859 self.assertEqual(len(od), len(pairs))
860 od.clear()
861 self.assertEqual(len(od), 0)
862
863 def test_delitem(self):
864 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
865 od = OrderedDict(pairs)
866 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +0000867 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000868 with self.assertRaises(KeyError):
869 del od['a']
870 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
871
872 def test_setitem(self):
873 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
874 od['c'] = 10 # existing element
875 od['f'] = 20 # new element
876 self.assertEqual(list(od.items()),
877 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
878
879 def test_iterators(self):
880 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
881 shuffle(pairs)
882 od = OrderedDict(pairs)
883 self.assertEqual(list(od), [t[0] for t in pairs])
884 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
885 self.assertEqual(list(od.values()), [t[1] for t in pairs])
886 self.assertEqual(list(od.items()), pairs)
887 self.assertEqual(list(reversed(od)),
888 [t[0] for t in reversed(pairs)])
889
890 def test_popitem(self):
891 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
892 shuffle(pairs)
893 od = OrderedDict(pairs)
894 while pairs:
895 self.assertEqual(od.popitem(), pairs.pop())
896 with self.assertRaises(KeyError):
897 od.popitem()
898 self.assertEqual(len(od), 0)
899
900 def test_pop(self):
901 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
902 shuffle(pairs)
903 od = OrderedDict(pairs)
904 shuffle(pairs)
905 while pairs:
906 k, v = pairs.pop()
907 self.assertEqual(od.pop(k), v)
908 with self.assertRaises(KeyError):
909 od.pop('xyz')
910 self.assertEqual(len(od), 0)
911 self.assertEqual(od.pop(k, 12345), 12345)
912
Raymond Hettinger345c49b2011-01-01 23:51:55 +0000913 # make sure pop still works when __missing__ is defined
914 class Missing(OrderedDict):
915 def __missing__(self, key):
916 return 0
917 m = Missing(a=1)
918 self.assertEqual(m.pop('b', 5), 5)
919 self.assertEqual(m.pop('a', 6), 1)
920 self.assertEqual(m.pop('a', 6), 6)
921 with self.assertRaises(KeyError):
922 m.pop('a')
923
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000924 def test_equality(self):
925 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
926 shuffle(pairs)
927 od1 = OrderedDict(pairs)
928 od2 = OrderedDict(pairs)
929 self.assertEqual(od1, od2) # same order implies equality
930 pairs = pairs[2:] + pairs[:2]
931 od2 = OrderedDict(pairs)
932 self.assertNotEqual(od1, od2) # different order implies inequality
933 # comparison to regular dict is not order sensitive
934 self.assertEqual(od1, dict(od2))
935 self.assertEqual(dict(od2), od1)
936 # different length implied inequality
937 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
938
939 def test_copying(self):
940 # Check that ordered dicts are copyable, deepcopyable, picklable,
941 # and have a repr/eval round-trip
942 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
943 od = OrderedDict(pairs)
944 update_test = OrderedDict()
945 update_test.update(od)
946 for i, dup in enumerate([
947 od.copy(),
948 copy.copy(od),
949 copy.deepcopy(od),
950 pickle.loads(pickle.dumps(od, 0)),
951 pickle.loads(pickle.dumps(od, 1)),
952 pickle.loads(pickle.dumps(od, 2)),
953 pickle.loads(pickle.dumps(od, 3)),
954 pickle.loads(pickle.dumps(od, -1)),
955 eval(repr(od)),
956 update_test,
957 OrderedDict(od),
958 ]):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000959 self.assertTrue(dup is not od)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000960 self.assertEqual(dup, od)
961 self.assertEqual(list(dup.items()), list(od.items()))
962 self.assertEqual(len(dup), len(od))
963 self.assertEqual(type(dup), type(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000964
Raymond Hettinger5b26fb52009-03-03 22:38:22 +0000965 def test_yaml_linkage(self):
966 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
967 # In yaml, lists are native but tuples are not.
968 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
969 od = OrderedDict(pairs)
970 # yaml.dump(od) -->
971 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000972 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +0000973
Raymond Hettingerb2121572009-03-03 22:50:04 +0000974 def test_reduce_not_too_fat(self):
975 # do not save instance dictionary if not needed
976 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
977 od = OrderedDict(pairs)
978 self.assertEqual(len(od.__reduce__()), 2)
979 od.x = 10
980 self.assertEqual(len(od.__reduce__()), 3)
981
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000982 def test_repr(self):
983 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
984 self.assertEqual(repr(od),
985 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
986 self.assertEqual(eval(repr(od)), od)
987 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
988
Raymond Hettingerdc08a142010-09-12 05:15:22 +0000989 def test_repr_recursive(self):
990 # See issue #9826
991 od = OrderedDict.fromkeys('abc')
992 od['x'] = od
993 self.assertEqual(repr(od),
994 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
995
Raymond Hettinger2d32f632009-03-02 21:24:57 +0000996 def test_setdefault(self):
997 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
998 shuffle(pairs)
999 od = OrderedDict(pairs)
1000 pair_order = list(od.items())
1001 self.assertEqual(od.setdefault('a', 10), 3)
1002 # make sure order didn't change
1003 self.assertEqual(list(od.items()), pair_order)
1004 self.assertEqual(od.setdefault('x', 10), 10)
1005 # make sure 'x' is added to the end
1006 self.assertEqual(list(od.items())[-1], ('x', 10))
1007
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001008 # make sure setdefault still works when __missing__ is defined
1009 class Missing(OrderedDict):
1010 def __missing__(self, key):
1011 return 0
1012 self.assertEqual(Missing().setdefault(5, 9), 9)
1013
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001014 def test_reinsert(self):
1015 # Given insert a, insert b, delete a, re-insert a,
1016 # verify that a is now later than b.
1017 od = OrderedDict()
1018 od['a'] = 1
1019 od['b'] = 2
1020 del od['a']
1021 od['a'] = 1
1022 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1023
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001024 def test_move_to_end(self):
1025 od = OrderedDict.fromkeys('abcde')
1026 self.assertEqual(list(od), list('abcde'))
1027 od.move_to_end('c')
1028 self.assertEqual(list(od), list('abdec'))
1029 od.move_to_end('c', 0)
1030 self.assertEqual(list(od), list('cabde'))
1031 od.move_to_end('c', 0)
1032 self.assertEqual(list(od), list('cabde'))
1033 od.move_to_end('e')
1034 self.assertEqual(list(od), list('cabde'))
1035 with self.assertRaises(KeyError):
1036 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001037
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001038 def test_sizeof(self):
1039 # Wimpy test: Just verify the reported size is larger than a regular dict
1040 d = dict(a=1)
1041 od = OrderedDict(**d)
1042 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1043
Raymond Hettinger32062e92011-01-01 22:38:00 +00001044 def test_override_update(self):
1045 # Verify that subclasses can override update() without breaking __init__()
1046 class MyOD(OrderedDict):
1047 def update(self, *args, **kwds):
1048 raise Exception()
1049 items = [('a', 1), ('c', 3), ('b', 2)]
1050 self.assertEqual(list(MyOD(items).items()), items)
1051
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001052class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1053 type2test = OrderedDict
1054
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001055 def test_popitem(self):
1056 d = self._empty_mapping()
1057 self.assertRaises(KeyError, d.popitem)
1058
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001059class MyOrderedDict(OrderedDict):
1060 pass
1061
1062class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1063 type2test = MyOrderedDict
1064
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001065 def test_popitem(self):
1066 d = self._empty_mapping()
1067 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001068
1069
Christian Heimes25bb7832008-01-11 16:17:00 +00001070import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001071
Guido van Rossumd8faa362007-04-27 19:54:29 +00001072def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001073 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001074 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001075 TestCollectionABCs, TestCounter,
1076 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001077 support.run_unittest(*test_classes)
1078 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001079
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001080
Guido van Rossumd8faa362007-04-27 19:54:29 +00001081if __name__ == "__main__":
1082 test_main(verbose=True)