blob: dfad78e00566d6a5bcd144524f291835f7e469c8 [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00003import unittest, doctest, operator
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -07004from test.support import TESTFN, forget, unlink
Raymond Hettinger2d32f632009-03-02 21:24:57 +00005import inspect
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Raymond Hettinger426e0522011-01-03 02:12:02 +00007from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger2d32f632009-03-02 21:24:57 +00008from test import mapping_tests
Georg Brandlc28e1fa2008-06-10 19:20:26 +00009import pickle, copy
Raymond Hettinger2d32f632009-03-02 21:24:57 +000010from random import randrange, shuffle
Raymond Hettinger499b2ee2009-05-27 01:53:46 +000011import keyword
12import re
R. David Murray378c0cf2010-02-24 01:46:21 +000013import sys
Raymond Hettinger57d1a882011-02-23 00:46:28 +000014from collections import UserDict
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000015from collections import ChainMap
Raymond Hettinger57d1a882011-02-23 00:46:28 +000016from collections.abc import Hashable, Iterable, Iterator
17from collections.abc import Sized, Container, Callable
18from collections.abc import Set, MutableSet
19from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
20from collections.abc import Sequence, MutableSequence
21from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000022
Raymond Hettinger499e1932011-02-23 07:56:53 +000023
24################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000025### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000026################################################################################
27
28class TestChainMap(unittest.TestCase):
29
30 def test_basics(self):
31 c = ChainMap()
32 c['a'] = 1
33 c['b'] = 2
34 d = c.new_child()
35 d['b'] = 20
36 d['c'] = 30
37 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
38 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
39 self.assertEqual(len(d), 3) # check len
40 for key in 'abc': # check contains
41 self.assertIn(key, d)
42 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
43 self.assertEqual(d.get(k, 100), v)
44
45 del d['b'] # unmask a value
46 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
47 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
48 self.assertEqual(len(d), 3) # check len
49 for key in 'abc': # check contains
50 self.assertIn(key, d)
51 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
52 self.assertEqual(d.get(k, 100), v)
53 self.assertIn(repr(d), [ # check repr
54 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
55 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
56 ])
57
58 for e in d.copy(), copy.copy(d): # check shallow copies
59 self.assertEqual(d, e)
60 self.assertEqual(d.maps, e.maps)
61 self.assertIsNot(d, e)
62 self.assertIsNot(d.maps[0], e.maps[0])
63 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
64 self.assertIs(m1, m2)
65
66 for e in [pickle.loads(pickle.dumps(d)),
67 copy.deepcopy(d),
68 eval(repr(d))
69 ]: # check deep copies
70 self.assertEqual(d, e)
71 self.assertEqual(d.maps, e.maps)
72 self.assertIsNot(d, e)
73 for m1, m2 in zip(d.maps, e.maps):
74 self.assertIsNot(m1, m2, e)
75
Raymond Hettingerd0321312011-02-26 06:53:58 +000076 f = d.new_child()
77 f['b'] = 5
78 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
79 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
80 self.assertEqual(f['b'], 5) # find first in chain
81 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +000082
83 def test_contructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +000084 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +000085 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
86
Raymond Hettingerd0321312011-02-26 06:53:58 +000087 def test_bool(self):
88 self.assertFalse(ChainMap())
89 self.assertFalse(ChainMap({}, {}))
90 self.assertTrue(ChainMap({1:2}, {}))
91 self.assertTrue(ChainMap({}, {1:2}))
92
Raymond Hettinger499e1932011-02-23 07:56:53 +000093 def test_missing(self):
94 class DefaultChainMap(ChainMap):
95 def __missing__(self, key):
96 return 999
97 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
98 for k, v in dict(a=1, b=2, c=30, d=999).items():
99 self.assertEqual(d[k], v) # check __getitem__ w/missing
100 for k, v in dict(a=1, b=2, c=30, d=77).items():
101 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
102 for k, v in dict(a=True, b=True, c=True, d=False).items():
103 self.assertEqual(k in d, v) # check __contains__ w/missing
104 self.assertEqual(d.pop('a', 1001), 1, d)
105 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
106 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
107 with self.assertRaises(KeyError):
108 d.popitem()
109
110 def test_dict_coercion(self):
111 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
112 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
113 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
114
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000115 def test_new_child(self):
116 'Tests for changes for issue #16613.'
117 c = ChainMap()
118 c['a'] = 1
119 c['b'] = 2
120 m = {'b':20, 'c': 30}
121 d = c.new_child(m)
122 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
123 self.assertIs(m, d.maps[0])
124
125 # Use a different map than a dict
126 class lowerdict(dict):
127 def __getitem__(self, key):
128 if isinstance(key, str):
129 key = key.lower()
130 return dict.__getitem__(self, key)
131 def __contains__(self, key):
132 if isinstance(key, str):
133 key = key.lower()
134 return dict.__contains__(self, key)
135
136 c = ChainMap()
137 c['a'] = 1
138 c['b'] = 2
139 m = lowerdict(b=20, c=30)
140 d = c.new_child(m)
141 self.assertIs(m, d.maps[0])
142 for key in 'abc': # check contains
143 self.assertIn(key, d)
144 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
145 self.assertEqual(d.get(k, 100), v)
146
Raymond Hettinger499e1932011-02-23 07:56:53 +0000147
148################################################################################
149### Named Tuples
150################################################################################
151
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000152TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000153
154class TestNamedTuple(unittest.TestCase):
155
156 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000157 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000158 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000159 self.assertEqual(Point.__slots__, ())
160 self.assertEqual(Point.__module__, __name__)
161 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000162 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettinger2ebea412011-03-23 12:52:23 -0700163 self.assertIn('class Point(tuple)', Point._source)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000164
165 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
166 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
167 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
168
169 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
170 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
171 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000172 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000173 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
174
175 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000176 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000177
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000178 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000179 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000180 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000181 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000182
Christian Heimesfaf2f632008-01-06 16:59:19 +0000183 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
184 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
185
R. David Murray378c0cf2010-02-24 01:46:21 +0000186 @unittest.skipIf(sys.flags.optimize >= 2,
187 "Docstrings are omitted with -O2 and above")
188 def test_factory_doc_attr(self):
189 Point = namedtuple('Point', 'x y')
190 self.assertEqual(Point.__doc__, 'Point(x, y)')
191
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000192 def test_name_fixer(self):
193 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000194 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
195 [('abc', 'class'), ('abc', '_1')], # field has keyword
196 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
197 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
198 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
199 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000200 ]:
201 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
202
Guido van Rossumd8faa362007-04-27 19:54:29 +0000203 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000204 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000205 p = Point(11, 22)
206 self.assertEqual(p, Point(x=11, y=22))
207 self.assertEqual(p, Point(11, y=22))
208 self.assertEqual(p, Point(y=22, x=11))
209 self.assertEqual(p, Point(*(11, 22)))
210 self.assertEqual(p, Point(**dict(x=11, y=22)))
211 self.assertRaises(TypeError, Point, 1) # too few args
212 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
213 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
214 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
215 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000216 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000217 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000218 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
219 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
220 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Raymond Hettinger3d890572011-06-02 23:40:24 -0700221 self.assertEqual(vars(p), p._asdict()) # verify that vars() works
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000222
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000223 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000224 p._replace(x=1, error=2)
225 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000226 pass
227 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000228 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000229
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000230 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000231 Point = namedtuple('Point', 'x, y')
232 p = Point(x=11, y=22)
233 self.assertEqual(repr(p), 'Point(x=11, y=22)')
234
235 # verify that fieldspec can be a non-string sequence
236 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000237 p = Point(x=11, y=22)
238 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000239
240 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000241 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000242 p = Point(11, 22)
243
Ezio Melottie9615932010-01-24 19:26:24 +0000244 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000245 self.assertEqual(p, (11, 22)) # matches a real tuple
246 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
247 self.assertEqual(list(p), [11, 22]) # coercable to a list
248 self.assertEqual(max(p), 22) # iterable
249 self.assertEqual(max(*p), 22) # star-able
250 x, y = p
251 self.assertEqual(p, (x, y)) # unpacks like a tuple
252 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
253 self.assertRaises(IndexError, p.__getitem__, 3)
254
255 self.assertEqual(p.x, x)
256 self.assertEqual(p.y, y)
257 self.assertRaises(AttributeError, eval, 'p.z', locals())
258
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000259 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000260 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000261 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000262 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000263 self.assertEqual(repr(Zero()), 'Zero()')
264 self.assertEqual(Zero()._asdict(), {})
265 self.assertEqual(Zero()._fields, ())
266
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000267 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000268 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000269 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000270 self.assertEqual(Dot(1).d, 1)
271 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
272 self.assertEqual(Dot(1)._asdict(), {'d':1})
273 self.assertEqual(Dot(1)._replace(d=999), (999,))
274 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000275
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000276 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000277 n = 254 # SyntaxError: more than 255 arguments:
278 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000279 names = list(set(''.join([random.choice(string.ascii_letters)
280 for j in range(10)]) for i in range(n)))
281 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000282 Big = namedtuple('Big', names)
283 b = Big(*range(n))
284 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000285 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000286 for pos, name in enumerate(names):
287 self.assertEqual(getattr(b, name), pos)
288 repr(b) # make sure repr() doesn't blow-up
289 d = b._asdict()
290 d_expected = dict(zip(names, range(n)))
291 self.assertEqual(d, d_expected)
292 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
293 b2_expected = list(range(n))
294 b2_expected[1] = 999
295 b2_expected[-5] = 42
296 self.assertEqual(b2, tuple(b2_expected))
297 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000298
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000299 def test_pickle(self):
300 p = TestNT(x=10, y=20, z=30)
301 for module in (pickle,):
302 loads = getattr(module, 'loads')
303 dumps = getattr(module, 'dumps')
304 for protocol in -1, 0, 1, 2:
305 q = loads(dumps(p, protocol))
306 self.assertEqual(p, q)
307 self.assertEqual(p._fields, q._fields)
308
309 def test_copy(self):
310 p = TestNT(x=10, y=20, z=30)
311 for copier in copy.copy, copy.deepcopy:
312 q = copier(p)
313 self.assertEqual(p, q)
314 self.assertEqual(p._fields, q._fields)
315
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000316 def test_name_conflicts(self):
317 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
318 # failed when used as field names. Test to make sure these now work.
319 T = namedtuple('T', 'itemgetter property self cls tuple')
320 t = T(1, 2, 3, 4, 5)
321 self.assertEqual(t, (1,2,3,4,5))
322 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
323 self.assertEqual(newt, (10,20,30,40,50))
324
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000325 # Broader test of all interesting names in a template
326 with support.captured_stdout() as template:
327 T = namedtuple('T', 'x', verbose=True)
328 words = set(re.findall('[A-Za-z]+', template.getvalue()))
329 words -= set(keyword.kwlist)
330 T = namedtuple('T', words)
331 # test __new__
332 values = tuple(range(len(words)))
333 t = T(*values)
334 self.assertEqual(t, values)
335 t = T(**dict(zip(T._fields, values)))
336 self.assertEqual(t, values)
337 # test _make
338 t = T._make(values)
339 self.assertEqual(t, values)
340 # exercise __repr__
341 repr(t)
342 # test _asdict
343 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
344 # test _replace
345 t = T._make(values)
346 newvalues = tuple(v*10 for v in values)
347 newt = t._replace(**dict(zip(T._fields, newvalues)))
348 self.assertEqual(newt, newvalues)
349 # test _fields
350 self.assertEqual(T._fields, tuple(words))
351 # test __getnewargs__
352 self.assertEqual(t.__getnewargs__(), values)
353
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000354 def test_repr(self):
355 with support.captured_stdout() as template:
356 A = namedtuple('A', 'x', verbose=True)
357 self.assertEqual(repr(A(1)), 'A(x=1)')
358 # repr should show the name of the subclass
359 class B(A):
360 pass
361 self.assertEqual(repr(B(1)), 'B(x=1)')
362
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700363 def test_source(self):
364 # verify that _source can be run through exec()
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700365 tmp = namedtuple('NTColor', 'red green blue')
366 globals().pop('NTColor', None) # remove artifacts from other tests
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700367 exec(tmp._source, globals())
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700368 self.assertIn('NTColor', globals())
369 c = NTColor(10, 20, 30)
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700370 self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700371 self.assertEqual(NTColor._fields, ('red', 'green', 'blue'))
372 globals().pop('NTColor', None) # clean-up after this test
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700373
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000374
Raymond Hettinger499e1932011-02-23 07:56:53 +0000375################################################################################
376### Abstract Base Classes
377################################################################################
378
Raymond Hettingerae650182009-01-28 23:33:59 +0000379class ABCTestCase(unittest.TestCase):
380
381 def validate_abstract_methods(self, abc, *names):
382 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
383
384 # everything should work will all required methods are present
385 C = type('C', (abc,), methodstubs)
386 C()
387
388 # instantiation should fail if a required method is missing
389 for name in names:
390 stubs = methodstubs.copy()
391 del stubs[name]
392 C = type('C', (abc,), stubs)
393 self.assertRaises(TypeError, C, name)
394
Florent Xiclunace153f62010-03-08 15:34:35 +0000395 def validate_isinstance(self, abc, name):
396 stub = lambda s, *args: 0
397
398 C = type('C', (object,), {'__hash__': None})
399 setattr(C, name, stub)
400 self.assertIsInstance(C(), abc)
401 self.assertTrue(issubclass(C, abc))
402
403 C = type('C', (object,), {'__hash__': None})
404 self.assertNotIsInstance(C(), abc)
405 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000406
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000407 def validate_comparison(self, instance):
408 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
409 operators = {}
410 for op in ops:
411 name = '__' + op + '__'
412 operators[name] = getattr(operator, name)
413
414 class Other:
415 def __init__(self):
416 self.right_side = False
417 def __eq__(self, other):
418 self.right_side = True
419 return True
420 __lt__ = __eq__
421 __gt__ = __eq__
422 __le__ = __eq__
423 __ge__ = __eq__
424 __ne__ = __eq__
425 __ror__ = __eq__
426 __rand__ = __eq__
427 __rxor__ = __eq__
428 __rsub__ = __eq__
429
430 for name, op in operators.items():
431 if not hasattr(instance, name):
432 continue
433 other = Other()
434 op(instance, other)
435 self.assertTrue(other.right_side,'Right side not called for %s.%s'
436 % (type(instance), name))
437
Raymond Hettingerae650182009-01-28 23:33:59 +0000438class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000439
440 def test_Hashable(self):
441 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000442 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000443 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000444 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000445 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000446 # Check some hashables
447 samples = [None,
448 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000449 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000450 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000451 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000452 ]
453 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000454 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000455 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000456 self.assertRaises(TypeError, Hashable)
457 # Check direct subclassing
458 class H(Hashable):
459 def __hash__(self):
460 return super().__hash__()
461 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000462 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000463 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000464 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000465
466 def test_Iterable(self):
467 # Check some non-iterables
468 non_samples = [None, 42, 3.14, 1j]
469 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000470 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000471 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000472 # Check some iterables
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 (lambda: (yield))(),
477 (x for x in []),
478 ]
479 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000480 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000481 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000482 # Check direct subclassing
483 class I(Iterable):
484 def __iter__(self):
485 return super().__iter__()
486 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000487 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000488 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000489 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000490
491 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000492 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000493 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000494 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000495 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000496 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000497 iter(tuple()), iter(list()), iter(dict()),
498 iter(set()), iter(frozenset()),
499 iter(dict().keys()), iter(dict().items()),
500 iter(dict().values()),
501 (lambda: (yield))(),
502 (x for x in []),
503 ]
504 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000505 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000506 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000507 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
508
509 # Issue 10565
510 class NextOnly:
511 def __next__(self):
512 yield 1
513 raise StopIteration
514 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000515
516 def test_Sized(self):
517 non_samples = [None, 42, 3.14, 1j,
518 (lambda: (yield))(),
519 (x for x in []),
520 ]
521 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000522 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000523 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000524 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000525 tuple(), list(), set(), frozenset(), dict(),
526 dict().keys(), dict().items(), dict().values(),
527 ]
528 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000529 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000530 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000531 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000532 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000533
534 def test_Container(self):
535 non_samples = [None, 42, 3.14, 1j,
536 (lambda: (yield))(),
537 (x for x in []),
538 ]
539 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000540 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000541 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000542 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000543 tuple(), list(), set(), frozenset(), dict(),
544 dict().keys(), dict().items(),
545 ]
546 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000547 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000548 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000549 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000550 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000551
552 def test_Callable(self):
553 non_samples = [None, 42, 3.14, 1j,
554 "", b"", (), [], {}, set(),
555 (lambda: (yield))(),
556 (x for x in []),
557 ]
558 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000559 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000560 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000561 samples = [lambda: None,
562 type, int, object,
563 len,
564 list.append, [].append,
565 ]
566 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000567 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000568 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000569 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000570 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000571
572 def test_direct_subclassing(self):
573 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
574 class C(B):
575 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000576 self.assertTrue(issubclass(C, B))
577 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000578
579 def test_registration(self):
580 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
581 class C:
582 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000583 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000584 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000585 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000586
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000587class WithSet(MutableSet):
588
589 def __init__(self, it=()):
590 self.data = set(it)
591
592 def __len__(self):
593 return len(self.data)
594
595 def __iter__(self):
596 return iter(self.data)
597
598 def __contains__(self, item):
599 return item in self.data
600
601 def add(self, item):
602 self.data.add(item)
603
604 def discard(self, item):
605 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000606
Raymond Hettingerae650182009-01-28 23:33:59 +0000607class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000608
609 # XXX For now, we only test some virtual inheritance properties.
610 # We should also test the proper behavior of the collection ABCs
611 # as real base classes or mix-in classes.
612
613 def test_Set(self):
614 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000615 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000616 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000617 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000618 class MySet(Set):
619 def __contains__(self, x):
620 return False
621 def __len__(self):
622 return 0
623 def __iter__(self):
624 return iter([])
625 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000626
Benjamin Peterson41181742008-07-02 20:22:54 +0000627 def test_hash_Set(self):
628 class OneTwoThreeSet(Set):
629 def __init__(self):
630 self.contents = [1, 2, 3]
631 def __contains__(self, x):
632 return x in self.contents
633 def __len__(self):
634 return len(self.contents)
635 def __iter__(self):
636 return iter(self.contents)
637 def __hash__(self):
638 return self._hash()
639 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000640 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000641
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000642 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000643 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000644 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000645 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000646 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000647 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
648 'add', 'discard')
649
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000650 def test_issue_5647(self):
651 # MutableSet.__iand__ mutated the set during iteration
652 s = WithSet('abcd')
653 s &= WithSet('cdef') # This used to fail
654 self.assertEqual(set(s), set('cd'))
655
Raymond Hettingerae650182009-01-28 23:33:59 +0000656 def test_issue_4920(self):
657 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000658 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000659 __slots__=['__s']
660 def __init__(self,items=None):
661 if items is None:
662 items=[]
663 self.__s=set(items)
664 def __contains__(self,v):
665 return v in self.__s
666 def __iter__(self):
667 return iter(self.__s)
668 def __len__(self):
669 return len(self.__s)
670 def add(self,v):
671 result=v not in self.__s
672 self.__s.add(v)
673 return result
674 def discard(self,v):
675 result=v in self.__s
676 self.__s.discard(v)
677 return result
678 def __repr__(self):
679 return "MySet(%s)" % repr(list(self))
680 s = MySet([5,43,2,1])
681 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000682
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000683 def test_issue8750(self):
684 empty = WithSet()
685 full = WithSet(range(10))
686 s = WithSet(full)
687 s -= s
688 self.assertEqual(s, empty)
689 s = WithSet(full)
690 s ^= s
691 self.assertEqual(s, empty)
692 s = WithSet(full)
693 s &= s
694 self.assertEqual(s, full)
695 s |= s
696 self.assertEqual(s, full)
697
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200698 def test_issue16373(self):
699 # Recursion error comparing comparable and noncomparable
700 # Set instances
701 class MyComparableSet(Set):
702 def __contains__(self, x):
703 return False
704 def __len__(self):
705 return 0
706 def __iter__(self):
707 return iter([])
708 class MyNonComparableSet(Set):
709 def __contains__(self, x):
710 return False
711 def __len__(self):
712 return 0
713 def __iter__(self):
714 return iter([])
715 def __le__(self, x):
716 return NotImplemented
717 def __lt__(self, x):
718 return NotImplemented
719
720 cs = MyComparableSet()
721 ncs = MyNonComparableSet()
722 with self.assertRaises(TypeError):
723 ncs < cs
724 with self.assertRaises(TypeError):
725 ncs <= cs
726 with self.assertRaises(TypeError):
727 cs > ncs
728 with self.assertRaises(TypeError):
729 cs >= ncs
730
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000731 def test_Mapping(self):
732 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000733 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000734 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000735 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
736 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000737 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000738 def __len__(self):
739 return 0
740 def __getitem__(self, i):
741 raise IndexError
742 def __iter__(self):
743 return iter(())
744 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000745
746 def test_MutableMapping(self):
747 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000748 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000749 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000750 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
751 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000752
Raymond Hettinger9117c752010-08-22 07:44:24 +0000753 def test_MutableMapping_subclass(self):
754 # Test issue 9214
755 mymap = UserDict()
756 mymap['red'] = 5
757 self.assertIsInstance(mymap.keys(), Set)
758 self.assertIsInstance(mymap.keys(), KeysView)
759 self.assertIsInstance(mymap.items(), Set)
760 self.assertIsInstance(mymap.items(), ItemsView)
761
762 mymap = UserDict()
763 mymap['red'] = 5
764 z = mymap.keys() | {'orange'}
765 self.assertIsInstance(z, set)
766 list(z)
767 mymap['blue'] = 7 # Shouldn't affect 'z'
768 self.assertEqual(sorted(z), ['orange', 'red'])
769
770 mymap = UserDict()
771 mymap['red'] = 5
772 z = mymap.items() | {('orange', 3)}
773 self.assertIsInstance(z, set)
774 list(z)
775 mymap['blue'] = 7 # Shouldn't affect 'z'
776 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
777
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000778 def test_Sequence(self):
779 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000780 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000781 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000782 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000783 self.assertTrue(issubclass(range, Sequence))
784 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000785 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
786 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000787
Guido van Rossumd05eb002007-11-21 22:26:24 +0000788 def test_ByteString(self):
789 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000790 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000791 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000792 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000793 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000794 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000795 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000796 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000797
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000798 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000799 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000800 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000801 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000802 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000803 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000804 self.assertTrue(issubclass(sample, MutableSequence))
805 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000806 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
807 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000808
Eli Bendersky0716a572011-03-04 10:38:14 +0000809 def test_MutableSequence_mixins(self):
810 # Test the mixins of MutableSequence by creating a miminal concrete
811 # class inherited from it.
812 class MutableSequenceSubclass(MutableSequence):
813 def __init__(self):
814 self.lst = []
815
816 def __setitem__(self, index, value):
817 self.lst[index] = value
818
819 def __getitem__(self, index):
820 return self.lst[index]
821
822 def __len__(self):
823 return len(self.lst)
824
825 def __delitem__(self, index):
826 del self.lst[index]
827
828 def insert(self, index, value):
829 self.lst.insert(index, value)
830
831 mss = MutableSequenceSubclass()
832 mss.append(0)
833 mss.extend((1, 2, 3, 4))
834 self.assertEqual(len(mss), 5)
835 self.assertEqual(mss[3], 3)
836 mss.reverse()
837 self.assertEqual(mss[3], 1)
838 mss.pop()
839 self.assertEqual(len(mss), 4)
840 mss.remove(3)
841 self.assertEqual(len(mss), 3)
842 mss += (10, 20, 30)
843 self.assertEqual(len(mss), 6)
844 self.assertEqual(mss[-1], 30)
845 mss.clear()
846 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +0000847
848################################################################################
849### Counter
850################################################################################
851
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000852class TestCounter(unittest.TestCase):
853
854 def test_basics(self):
855 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000856 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
857 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +0000858 self.assertIsInstance(c, dict)
859 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000860 self.assertTrue(issubclass(Counter, dict))
861 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000862 self.assertEqual(len(c), 3)
863 self.assertEqual(sum(c.values()), 6)
864 self.assertEqual(sorted(c.values()), [1, 2, 3])
865 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
866 self.assertEqual(sorted(c), ['a', 'b', 'c'])
867 self.assertEqual(sorted(c.items()),
868 [('a', 3), ('b', 2), ('c', 1)])
869 self.assertEqual(c['b'], 2)
870 self.assertEqual(c['z'], 0)
871 self.assertEqual(c.__contains__('c'), True)
872 self.assertEqual(c.__contains__('z'), False)
873 self.assertEqual(c.get('b', 10), 2)
874 self.assertEqual(c.get('z', 10), 10)
875 self.assertEqual(c, dict(a=3, b=2, c=1))
876 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
877 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
878 for i in range(5):
879 self.assertEqual(c.most_common(i),
880 [('a', 3), ('b', 2), ('c', 1)][:i])
881 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
882 c['a'] += 1 # increment an existing value
883 c['b'] -= 2 # sub existing value to zero
884 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000885 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000886 c['d'] -= 2 # sub from a missing value
887 c['e'] = -5 # directly assign a missing value
888 c['f'] += 4 # add to a missing value
889 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
890 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
891 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000892 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000893 for i in range(3):
894 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +0000895 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000896 c.clear()
897 self.assertEqual(c, {})
898 self.assertEqual(repr(c), 'Counter()')
899 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
900 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000901 c.update(dict(a=5, b=3))
902 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000903 c.update(Counter('a' * 50 + 'b' * 30))
904 c.update() # test case with no args
905 c.__init__('a' * 500 + 'b' * 300)
906 c.__init__('cdc')
907 c.__init__()
908 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
909 self.assertEqual(c.setdefault('d', 5), 1)
910 self.assertEqual(c['d'], 1)
911 self.assertEqual(c.setdefault('e', 5), 5)
912 self.assertEqual(c['e'], 5)
913
914 def test_copying(self):
915 # Check that counters are copyable, deepcopyable, picklable, and
916 #have a repr/eval round-trip
917 words = Counter('which witch had which witches wrist watch'.split())
918 update_test = Counter()
919 update_test.update(words)
920 for i, dup in enumerate([
921 words.copy(),
922 copy.copy(words),
923 copy.deepcopy(words),
924 pickle.loads(pickle.dumps(words, 0)),
925 pickle.loads(pickle.dumps(words, 1)),
926 pickle.loads(pickle.dumps(words, 2)),
927 pickle.loads(pickle.dumps(words, -1)),
928 eval(repr(words)),
929 update_test,
930 Counter(words),
931 ]):
932 msg = (i, dup, words)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000933 self.assertTrue(dup is not words)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000934 self.assertEqual(dup, words)
935 self.assertEqual(len(dup), len(words))
936 self.assertEqual(type(dup), type(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000937
Raymond Hettinger1c746c22011-04-15 13:16:46 -0700938 def test_copy_subclass(self):
939 class MyCounter(Counter):
940 pass
941 c = MyCounter('slartibartfast')
942 d = c.copy()
943 self.assertEqual(d, c)
944 self.assertEqual(len(d), len(c))
945 self.assertEqual(type(d), type(c))
946
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000947 def test_conversions(self):
948 # Convert to: set, list, dict
949 s = 'she sells sea shells by the sea shore'
950 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
951 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
952 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
953 self.assertEqual(set(Counter(s)), set(s))
954
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000955 def test_invariant_for_the_in_operator(self):
956 c = Counter(a=10, b=-2, c=0)
957 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000958 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000959 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000960
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000961 def test_multiset_operations(self):
962 # Verify that adding a zero counter will strip zeros and negatives
963 c = Counter(a=10, b=-2, c=0) + Counter()
964 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000965
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000966 elements = 'abcd'
967 for i in range(1000):
968 # test random pairs of multisets
969 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000970 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000971 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000972 q.update(h=1, i=-1, j=0)
973 for counterop, numberop in [
974 (Counter.__add__, lambda x, y: max(0, x+y)),
975 (Counter.__sub__, lambda x, y: max(0, x-y)),
976 (Counter.__or__, lambda x, y: max(0,x,y)),
977 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000978 ]:
979 result = counterop(p, q)
980 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000981 self.assertEqual(numberop(p[x], q[x]), result[x],
982 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000983 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000984 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000985
986 elements = 'abcdef'
987 for i in range(100):
988 # verify that random multisets with no repeats are exactly like sets
989 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
990 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
991 for counterop, setop in [
992 (Counter.__sub__, set.__sub__),
993 (Counter.__or__, set.__or__),
994 (Counter.__and__, set.__and__),
995 ]:
996 counter_result = counterop(p, q)
997 set_result = setop(set(p.elements()), set(q.elements()))
998 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000999
Raymond Hettingerbecd5682011-10-19 13:40:37 -07001000 def test_inplace_operations(self):
1001 elements = 'abcd'
1002 for i in range(1000):
1003 # test random pairs of multisets
1004 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1005 p.update(e=1, f=-1, g=0)
1006 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1007 q.update(h=1, i=-1, j=0)
1008 for inplace_op, regular_op in [
1009 (Counter.__iadd__, Counter.__add__),
1010 (Counter.__isub__, Counter.__sub__),
1011 (Counter.__ior__, Counter.__or__),
1012 (Counter.__iand__, Counter.__and__),
1013 ]:
1014 c = p.copy()
1015 c_id = id(c)
1016 regular_result = regular_op(c, q)
1017 inplace_result = inplace_op(c, q)
1018 self.assertEqual(inplace_result, regular_result)
1019 self.assertEqual(id(inplace_result), c_id)
1020
Raymond Hettinger9c01e442010-04-03 10:32:58 +00001021 def test_subtract(self):
1022 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1023 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
1024 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1025 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1026 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
1027 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1028 c = Counter('aaabbcd')
1029 c.subtract('aaaabbcce')
1030 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001031
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07001032 def test_unary(self):
1033 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1034 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
1035 self.assertEqual(dict(-c), dict(a=5))
1036
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07001037 def test_repr_nonsortable(self):
1038 c = Counter(a=2, b=None)
1039 r = repr(c)
1040 self.assertIn("'a': 2", r)
1041 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07001042
Raymond Hettinger426e0522011-01-03 02:12:02 +00001043 def test_helper_function(self):
1044 # two paths, one for real dicts and one for other mappings
1045 elems = list('abracadabra')
1046
1047 d = dict()
1048 _count_elements(d, elems)
1049 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1050
1051 m = OrderedDict()
1052 _count_elements(m, elems)
1053 self.assertEqual(m,
1054 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
1055
Raymond Hettinger499e1932011-02-23 07:56:53 +00001056
1057################################################################################
1058### OrderedDict
1059################################################################################
1060
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001061class TestOrderedDict(unittest.TestCase):
1062
1063 def test_init(self):
1064 with self.assertRaises(TypeError):
1065 OrderedDict([('a', 1), ('b', 2)], None) # too many args
1066 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1067 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
1068 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
1069 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
1070 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
1071 c=3, e=5).items()), pairs) # mixed input
1072
1073 # make sure no positional args conflict with possible kwdargs
1074 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
1075 ['self'])
1076
1077 # Make sure that direct calls to __init__ do not clear previous contents
1078 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1079 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
1080 self.assertEqual(list(d.items()),
1081 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1082
1083 def test_update(self):
1084 with self.assertRaises(TypeError):
1085 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
1086 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1087 od = OrderedDict()
1088 od.update(dict(pairs))
1089 self.assertEqual(sorted(od.items()), pairs) # dict input
1090 od = OrderedDict()
1091 od.update(**dict(pairs))
1092 self.assertEqual(sorted(od.items()), pairs) # kwds input
1093 od = OrderedDict()
1094 od.update(pairs)
1095 self.assertEqual(list(od.items()), pairs) # pairs input
1096 od = OrderedDict()
1097 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1098 self.assertEqual(list(od.items()), pairs) # mixed input
1099
Mark Dickinsonb214e902010-07-11 18:53:06 +00001100 # Issue 9137: Named argument called 'other' or 'self'
1101 # shouldn't be treated specially.
1102 od = OrderedDict()
1103 od.update(self=23)
1104 self.assertEqual(list(od.items()), [('self', 23)])
1105 od = OrderedDict()
1106 od.update(other={})
1107 self.assertEqual(list(od.items()), [('other', {})])
1108 od = OrderedDict()
1109 od.update(red=5, blue=6, other=7, self=8)
1110 self.assertEqual(sorted(list(od.items())),
1111 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
1112
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001113 # Make sure that direct calls to update do not clear previous contents
1114 # add that updates items are not moved to the end
1115 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1116 d.update([('e', 5), ('f', 6)], g=7, d=4)
1117 self.assertEqual(list(d.items()),
1118 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1119
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001120 def test_abc(self):
1121 self.assertIsInstance(OrderedDict(), MutableMapping)
1122 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1123
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001124 def test_clear(self):
1125 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1126 shuffle(pairs)
1127 od = OrderedDict(pairs)
1128 self.assertEqual(len(od), len(pairs))
1129 od.clear()
1130 self.assertEqual(len(od), 0)
1131
1132 def test_delitem(self):
1133 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1134 od = OrderedDict(pairs)
1135 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001136 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001137 with self.assertRaises(KeyError):
1138 del od['a']
1139 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1140
1141 def test_setitem(self):
1142 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1143 od['c'] = 10 # existing element
1144 od['f'] = 20 # new element
1145 self.assertEqual(list(od.items()),
1146 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1147
1148 def test_iterators(self):
1149 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1150 shuffle(pairs)
1151 od = OrderedDict(pairs)
1152 self.assertEqual(list(od), [t[0] for t in pairs])
1153 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1154 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1155 self.assertEqual(list(od.items()), pairs)
1156 self.assertEqual(list(reversed(od)),
1157 [t[0] for t in reversed(pairs)])
1158
1159 def test_popitem(self):
1160 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1161 shuffle(pairs)
1162 od = OrderedDict(pairs)
1163 while pairs:
1164 self.assertEqual(od.popitem(), pairs.pop())
1165 with self.assertRaises(KeyError):
1166 od.popitem()
1167 self.assertEqual(len(od), 0)
1168
1169 def test_pop(self):
1170 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1171 shuffle(pairs)
1172 od = OrderedDict(pairs)
1173 shuffle(pairs)
1174 while pairs:
1175 k, v = pairs.pop()
1176 self.assertEqual(od.pop(k), v)
1177 with self.assertRaises(KeyError):
1178 od.pop('xyz')
1179 self.assertEqual(len(od), 0)
1180 self.assertEqual(od.pop(k, 12345), 12345)
1181
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001182 # make sure pop still works when __missing__ is defined
1183 class Missing(OrderedDict):
1184 def __missing__(self, key):
1185 return 0
1186 m = Missing(a=1)
1187 self.assertEqual(m.pop('b', 5), 5)
1188 self.assertEqual(m.pop('a', 6), 1)
1189 self.assertEqual(m.pop('a', 6), 6)
1190 with self.assertRaises(KeyError):
1191 m.pop('a')
1192
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001193 def test_equality(self):
1194 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1195 shuffle(pairs)
1196 od1 = OrderedDict(pairs)
1197 od2 = OrderedDict(pairs)
1198 self.assertEqual(od1, od2) # same order implies equality
1199 pairs = pairs[2:] + pairs[:2]
1200 od2 = OrderedDict(pairs)
1201 self.assertNotEqual(od1, od2) # different order implies inequality
1202 # comparison to regular dict is not order sensitive
1203 self.assertEqual(od1, dict(od2))
1204 self.assertEqual(dict(od2), od1)
1205 # different length implied inequality
1206 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1207
1208 def test_copying(self):
1209 # Check that ordered dicts are copyable, deepcopyable, picklable,
1210 # and have a repr/eval round-trip
1211 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1212 od = OrderedDict(pairs)
1213 update_test = OrderedDict()
1214 update_test.update(od)
1215 for i, dup in enumerate([
1216 od.copy(),
1217 copy.copy(od),
1218 copy.deepcopy(od),
1219 pickle.loads(pickle.dumps(od, 0)),
1220 pickle.loads(pickle.dumps(od, 1)),
1221 pickle.loads(pickle.dumps(od, 2)),
1222 pickle.loads(pickle.dumps(od, 3)),
1223 pickle.loads(pickle.dumps(od, -1)),
1224 eval(repr(od)),
1225 update_test,
1226 OrderedDict(od),
1227 ]):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001228 self.assertTrue(dup is not od)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001229 self.assertEqual(dup, od)
1230 self.assertEqual(list(dup.items()), list(od.items()))
1231 self.assertEqual(len(dup), len(od))
1232 self.assertEqual(type(dup), type(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001233
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001234 def test_yaml_linkage(self):
1235 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1236 # In yaml, lists are native but tuples are not.
1237 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1238 od = OrderedDict(pairs)
1239 # yaml.dump(od) -->
1240 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001241 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001242
Raymond Hettingerb2121572009-03-03 22:50:04 +00001243 def test_reduce_not_too_fat(self):
1244 # do not save instance dictionary if not needed
1245 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1246 od = OrderedDict(pairs)
1247 self.assertEqual(len(od.__reduce__()), 2)
1248 od.x = 10
1249 self.assertEqual(len(od.__reduce__()), 3)
1250
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001251 def test_repr(self):
1252 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1253 self.assertEqual(repr(od),
1254 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1255 self.assertEqual(eval(repr(od)), od)
1256 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1257
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001258 def test_repr_recursive(self):
1259 # See issue #9826
1260 od = OrderedDict.fromkeys('abc')
1261 od['x'] = od
1262 self.assertEqual(repr(od),
1263 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1264
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001265 def test_setdefault(self):
1266 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1267 shuffle(pairs)
1268 od = OrderedDict(pairs)
1269 pair_order = list(od.items())
1270 self.assertEqual(od.setdefault('a', 10), 3)
1271 # make sure order didn't change
1272 self.assertEqual(list(od.items()), pair_order)
1273 self.assertEqual(od.setdefault('x', 10), 10)
1274 # make sure 'x' is added to the end
1275 self.assertEqual(list(od.items())[-1], ('x', 10))
1276
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001277 # make sure setdefault still works when __missing__ is defined
1278 class Missing(OrderedDict):
1279 def __missing__(self, key):
1280 return 0
1281 self.assertEqual(Missing().setdefault(5, 9), 9)
1282
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001283 def test_reinsert(self):
1284 # Given insert a, insert b, delete a, re-insert a,
1285 # verify that a is now later than b.
1286 od = OrderedDict()
1287 od['a'] = 1
1288 od['b'] = 2
1289 del od['a']
1290 od['a'] = 1
1291 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1292
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001293 def test_move_to_end(self):
1294 od = OrderedDict.fromkeys('abcde')
1295 self.assertEqual(list(od), list('abcde'))
1296 od.move_to_end('c')
1297 self.assertEqual(list(od), list('abdec'))
1298 od.move_to_end('c', 0)
1299 self.assertEqual(list(od), list('cabde'))
1300 od.move_to_end('c', 0)
1301 self.assertEqual(list(od), list('cabde'))
1302 od.move_to_end('e')
1303 self.assertEqual(list(od), list('cabde'))
1304 with self.assertRaises(KeyError):
1305 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001306
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001307 def test_sizeof(self):
1308 # Wimpy test: Just verify the reported size is larger than a regular dict
1309 d = dict(a=1)
1310 od = OrderedDict(**d)
1311 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1312
Raymond Hettinger32062e92011-01-01 22:38:00 +00001313 def test_override_update(self):
1314 # Verify that subclasses can override update() without breaking __init__()
1315 class MyOD(OrderedDict):
1316 def update(self, *args, **kwds):
1317 raise Exception()
1318 items = [('a', 1), ('c', 3), ('b', 2)]
1319 self.assertEqual(list(MyOD(items).items()), items)
1320
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001321class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1322 type2test = OrderedDict
1323
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001324 def test_popitem(self):
1325 d = self._empty_mapping()
1326 self.assertRaises(KeyError, d.popitem)
1327
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001328class MyOrderedDict(OrderedDict):
1329 pass
1330
1331class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1332 type2test = MyOrderedDict
1333
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001334 def test_popitem(self):
1335 d = self._empty_mapping()
1336 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001337
1338
Raymond Hettinger499e1932011-02-23 07:56:53 +00001339################################################################################
1340### Run tests
1341################################################################################
1342
Christian Heimes25bb7832008-01-11 16:17:00 +00001343import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001344
Guido van Rossumd8faa362007-04-27 19:54:29 +00001345def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001346 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001347 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001348 TestCollectionABCs, TestCounter, TestChainMap,
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001349 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001350 support.run_unittest(*test_classes)
1351 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001352
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001353
Guido van Rossumd8faa362007-04-27 19:54:29 +00001354if __name__ == "__main__":
1355 test_main(verbose=True)