blob: df1c63c833bcc53228a463d173d4b84207a4b2b3 [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
Serhiy Storchakabad12572014-12-15 14:03:42 +020066 # check deep copies
67 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
68 e = pickle.loads(pickle.dumps(d, proto))
69 self.assertEqual(d, e)
70 self.assertEqual(d.maps, e.maps)
71 self.assertIsNot(d, e)
72 for m1, m2 in zip(d.maps, e.maps):
73 self.assertIsNot(m1, m2, e)
74 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +000075 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +020076 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +000077 self.assertEqual(d, e)
78 self.assertEqual(d.maps, e.maps)
79 self.assertIsNot(d, e)
80 for m1, m2 in zip(d.maps, e.maps):
81 self.assertIsNot(m1, m2, e)
82
Raymond Hettingerd0321312011-02-26 06:53:58 +000083 f = d.new_child()
84 f['b'] = 5
85 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
86 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
87 self.assertEqual(f['b'], 5) # find first in chain
88 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +000089
90 def test_contructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +000091 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +000092 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
93
Raymond Hettingerd0321312011-02-26 06:53:58 +000094 def test_bool(self):
95 self.assertFalse(ChainMap())
96 self.assertFalse(ChainMap({}, {}))
97 self.assertTrue(ChainMap({1:2}, {}))
98 self.assertTrue(ChainMap({}, {1:2}))
99
Raymond Hettinger499e1932011-02-23 07:56:53 +0000100 def test_missing(self):
101 class DefaultChainMap(ChainMap):
102 def __missing__(self, key):
103 return 999
104 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
105 for k, v in dict(a=1, b=2, c=30, d=999).items():
106 self.assertEqual(d[k], v) # check __getitem__ w/missing
107 for k, v in dict(a=1, b=2, c=30, d=77).items():
108 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
109 for k, v in dict(a=True, b=True, c=True, d=False).items():
110 self.assertEqual(k in d, v) # check __contains__ w/missing
111 self.assertEqual(d.pop('a', 1001), 1, d)
112 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
113 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
114 with self.assertRaises(KeyError):
115 d.popitem()
116
117 def test_dict_coercion(self):
118 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
119 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
120 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
121
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000122 def test_new_child(self):
123 'Tests for changes for issue #16613.'
124 c = ChainMap()
125 c['a'] = 1
126 c['b'] = 2
127 m = {'b':20, 'c': 30}
128 d = c.new_child(m)
129 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
130 self.assertIs(m, d.maps[0])
131
132 # Use a different map than a dict
133 class lowerdict(dict):
134 def __getitem__(self, key):
135 if isinstance(key, str):
136 key = key.lower()
137 return dict.__getitem__(self, key)
138 def __contains__(self, key):
139 if isinstance(key, str):
140 key = key.lower()
141 return dict.__contains__(self, key)
142
143 c = ChainMap()
144 c['a'] = 1
145 c['b'] = 2
146 m = lowerdict(b=20, c=30)
147 d = c.new_child(m)
148 self.assertIs(m, d.maps[0])
149 for key in 'abc': # check contains
150 self.assertIn(key, d)
151 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
152 self.assertEqual(d.get(k, 100), v)
153
Raymond Hettinger499e1932011-02-23 07:56:53 +0000154
155################################################################################
156### Named Tuples
157################################################################################
158
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000159TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000160
161class TestNamedTuple(unittest.TestCase):
162
163 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000164 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000165 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000166 self.assertEqual(Point.__slots__, ())
167 self.assertEqual(Point.__module__, __name__)
168 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000169 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettinger2ebea412011-03-23 12:52:23 -0700170 self.assertIn('class Point(tuple)', Point._source)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000171
172 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
173 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
174 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
175
176 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
177 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
178 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000179 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000180 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
181
182 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000183 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000184
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000185 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000186 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000187 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000188 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000189
Christian Heimesfaf2f632008-01-06 16:59:19 +0000190 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
191 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
192
R. David Murray378c0cf2010-02-24 01:46:21 +0000193 @unittest.skipIf(sys.flags.optimize >= 2,
194 "Docstrings are omitted with -O2 and above")
195 def test_factory_doc_attr(self):
196 Point = namedtuple('Point', 'x y')
197 self.assertEqual(Point.__doc__, 'Point(x, y)')
198
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000199 def test_name_fixer(self):
200 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000201 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
202 [('abc', 'class'), ('abc', '_1')], # field has keyword
203 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
204 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
205 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
206 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000207 ]:
208 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
209
Guido van Rossumd8faa362007-04-27 19:54:29 +0000210 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000211 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000212 p = Point(11, 22)
213 self.assertEqual(p, Point(x=11, y=22))
214 self.assertEqual(p, Point(11, y=22))
215 self.assertEqual(p, Point(y=22, x=11))
216 self.assertEqual(p, Point(*(11, 22)))
217 self.assertEqual(p, Point(**dict(x=11, y=22)))
218 self.assertRaises(TypeError, Point, 1) # too few args
219 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
220 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
221 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
222 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000223 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000224 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000225 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
226 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
Raymond Hettinger163e9822013-05-18 00:05:20 -0700227 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
228 self.assertEqual(vars(p), p._asdict()) # verify that vars() works
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000229
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000230 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000231 p._replace(x=1, error=2)
232 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000233 pass
234 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000235 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000236
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000237 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000238 Point = namedtuple('Point', 'x, y')
239 p = Point(x=11, y=22)
240 self.assertEqual(repr(p), 'Point(x=11, y=22)')
241
242 # verify that fieldspec can be a non-string sequence
243 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000244 p = Point(x=11, y=22)
245 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000246
247 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000248 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000249 p = Point(11, 22)
250
Ezio Melottie9615932010-01-24 19:26:24 +0000251 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000252 self.assertEqual(p, (11, 22)) # matches a real tuple
253 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
254 self.assertEqual(list(p), [11, 22]) # coercable to a list
255 self.assertEqual(max(p), 22) # iterable
256 self.assertEqual(max(*p), 22) # star-able
257 x, y = p
258 self.assertEqual(p, (x, y)) # unpacks like a tuple
259 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
260 self.assertRaises(IndexError, p.__getitem__, 3)
261
262 self.assertEqual(p.x, x)
263 self.assertEqual(p.y, y)
264 self.assertRaises(AttributeError, eval, 'p.z', locals())
265
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000266 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000267 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000268 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000269 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000270 self.assertEqual(repr(Zero()), 'Zero()')
271 self.assertEqual(Zero()._asdict(), {})
272 self.assertEqual(Zero()._fields, ())
273
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000274 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000275 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000276 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000277 self.assertEqual(Dot(1).d, 1)
278 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
279 self.assertEqual(Dot(1)._asdict(), {'d':1})
280 self.assertEqual(Dot(1)._replace(d=999), (999,))
281 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000282
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000283 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000284 n = 254 # SyntaxError: more than 255 arguments:
285 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000286 names = list(set(''.join([random.choice(string.ascii_letters)
287 for j in range(10)]) for i in range(n)))
288 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000289 Big = namedtuple('Big', names)
290 b = Big(*range(n))
291 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000292 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000293 for pos, name in enumerate(names):
294 self.assertEqual(getattr(b, name), pos)
295 repr(b) # make sure repr() doesn't blow-up
296 d = b._asdict()
297 d_expected = dict(zip(names, range(n)))
298 self.assertEqual(d, d_expected)
299 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
300 b2_expected = list(range(n))
301 b2_expected[1] = 999
302 b2_expected[-5] = 42
303 self.assertEqual(b2, tuple(b2_expected))
304 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000305
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000306 def test_pickle(self):
307 p = TestNT(x=10, y=20, z=30)
308 for module in (pickle,):
309 loads = getattr(module, 'loads')
310 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500311 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000312 q = loads(dumps(p, protocol))
313 self.assertEqual(p, q)
314 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700315 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000316
317 def test_copy(self):
318 p = TestNT(x=10, y=20, z=30)
319 for copier in copy.copy, copy.deepcopy:
320 q = copier(p)
321 self.assertEqual(p, q)
322 self.assertEqual(p._fields, q._fields)
323
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000324 def test_name_conflicts(self):
325 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
326 # failed when used as field names. Test to make sure these now work.
327 T = namedtuple('T', 'itemgetter property self cls tuple')
328 t = T(1, 2, 3, 4, 5)
329 self.assertEqual(t, (1,2,3,4,5))
330 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
331 self.assertEqual(newt, (10,20,30,40,50))
332
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000333 # Broader test of all interesting names in a template
334 with support.captured_stdout() as template:
335 T = namedtuple('T', 'x', verbose=True)
336 words = set(re.findall('[A-Za-z]+', template.getvalue()))
337 words -= set(keyword.kwlist)
338 T = namedtuple('T', words)
339 # test __new__
340 values = tuple(range(len(words)))
341 t = T(*values)
342 self.assertEqual(t, values)
343 t = T(**dict(zip(T._fields, values)))
344 self.assertEqual(t, values)
345 # test _make
346 t = T._make(values)
347 self.assertEqual(t, values)
348 # exercise __repr__
349 repr(t)
350 # test _asdict
351 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
352 # test _replace
353 t = T._make(values)
354 newvalues = tuple(v*10 for v in values)
355 newt = t._replace(**dict(zip(T._fields, newvalues)))
356 self.assertEqual(newt, newvalues)
357 # test _fields
358 self.assertEqual(T._fields, tuple(words))
359 # test __getnewargs__
360 self.assertEqual(t.__getnewargs__(), values)
361
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000362 def test_repr(self):
363 with support.captured_stdout() as template:
364 A = namedtuple('A', 'x', verbose=True)
365 self.assertEqual(repr(A(1)), 'A(x=1)')
366 # repr should show the name of the subclass
367 class B(A):
368 pass
369 self.assertEqual(repr(B(1)), 'B(x=1)')
370
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700371 def test_source(self):
372 # verify that _source can be run through exec()
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700373 tmp = namedtuple('NTColor', 'red green blue')
374 globals().pop('NTColor', None) # remove artifacts from other tests
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700375 exec(tmp._source, globals())
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700376 self.assertIn('NTColor', globals())
377 c = NTColor(10, 20, 30)
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700378 self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700379 self.assertEqual(NTColor._fields, ('red', 'green', 'blue'))
380 globals().pop('NTColor', None) # clean-up after this test
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700381
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000382
Raymond Hettinger499e1932011-02-23 07:56:53 +0000383################################################################################
384### Abstract Base Classes
385################################################################################
386
Raymond Hettingerae650182009-01-28 23:33:59 +0000387class ABCTestCase(unittest.TestCase):
388
389 def validate_abstract_methods(self, abc, *names):
390 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
391
392 # everything should work will all required methods are present
393 C = type('C', (abc,), methodstubs)
394 C()
395
396 # instantiation should fail if a required method is missing
397 for name in names:
398 stubs = methodstubs.copy()
399 del stubs[name]
400 C = type('C', (abc,), stubs)
401 self.assertRaises(TypeError, C, name)
402
Florent Xiclunace153f62010-03-08 15:34:35 +0000403 def validate_isinstance(self, abc, name):
404 stub = lambda s, *args: 0
405
406 C = type('C', (object,), {'__hash__': None})
407 setattr(C, name, stub)
408 self.assertIsInstance(C(), abc)
409 self.assertTrue(issubclass(C, abc))
410
411 C = type('C', (object,), {'__hash__': None})
412 self.assertNotIsInstance(C(), abc)
413 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000414
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000415 def validate_comparison(self, instance):
416 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
417 operators = {}
418 for op in ops:
419 name = '__' + op + '__'
420 operators[name] = getattr(operator, name)
421
422 class Other:
423 def __init__(self):
424 self.right_side = False
425 def __eq__(self, other):
426 self.right_side = True
427 return True
428 __lt__ = __eq__
429 __gt__ = __eq__
430 __le__ = __eq__
431 __ge__ = __eq__
432 __ne__ = __eq__
433 __ror__ = __eq__
434 __rand__ = __eq__
435 __rxor__ = __eq__
436 __rsub__ = __eq__
437
438 for name, op in operators.items():
439 if not hasattr(instance, name):
440 continue
441 other = Other()
442 op(instance, other)
443 self.assertTrue(other.right_side,'Right side not called for %s.%s'
444 % (type(instance), name))
445
Raymond Hettingerae650182009-01-28 23:33:59 +0000446class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000447
448 def test_Hashable(self):
449 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000450 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000451 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000452 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000453 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000454 # Check some hashables
455 samples = [None,
456 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000457 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000458 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000459 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000460 ]
461 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000462 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000463 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000464 self.assertRaises(TypeError, Hashable)
465 # Check direct subclassing
466 class H(Hashable):
467 def __hash__(self):
468 return super().__hash__()
469 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000470 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000471 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000472 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000473
474 def test_Iterable(self):
475 # Check some non-iterables
476 non_samples = [None, 42, 3.14, 1j]
477 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000478 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000479 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000480 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000481 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000482 tuple(), list(), set(), frozenset(), dict(),
483 dict().keys(), dict().items(), dict().values(),
484 (lambda: (yield))(),
485 (x for x in []),
486 ]
487 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000488 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000489 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000490 # Check direct subclassing
491 class I(Iterable):
492 def __iter__(self):
493 return super().__iter__()
494 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000495 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000496 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000497 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000498
499 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000500 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000501 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000502 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000503 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000504 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000505 iter(tuple()), iter(list()), iter(dict()),
506 iter(set()), iter(frozenset()),
507 iter(dict().keys()), iter(dict().items()),
508 iter(dict().values()),
509 (lambda: (yield))(),
510 (x for x in []),
511 ]
512 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000513 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000514 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000515 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
516
517 # Issue 10565
518 class NextOnly:
519 def __next__(self):
520 yield 1
521 raise StopIteration
522 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000523
524 def test_Sized(self):
525 non_samples = [None, 42, 3.14, 1j,
526 (lambda: (yield))(),
527 (x for x in []),
528 ]
529 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000530 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000531 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000532 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000533 tuple(), list(), set(), frozenset(), dict(),
534 dict().keys(), dict().items(), dict().values(),
535 ]
536 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000537 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000538 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000539 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000540 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000541
542 def test_Container(self):
543 non_samples = [None, 42, 3.14, 1j,
544 (lambda: (yield))(),
545 (x for x in []),
546 ]
547 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000548 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000549 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000550 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000551 tuple(), list(), set(), frozenset(), dict(),
552 dict().keys(), dict().items(),
553 ]
554 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000555 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000556 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000557 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000558 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000559
560 def test_Callable(self):
561 non_samples = [None, 42, 3.14, 1j,
562 "", b"", (), [], {}, set(),
563 (lambda: (yield))(),
564 (x for x in []),
565 ]
566 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000567 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000568 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000569 samples = [lambda: None,
570 type, int, object,
571 len,
572 list.append, [].append,
573 ]
574 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000575 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000576 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000577 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000578 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000579
580 def test_direct_subclassing(self):
581 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
582 class C(B):
583 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000584 self.assertTrue(issubclass(C, B))
585 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000586
587 def test_registration(self):
588 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
589 class C:
590 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000591 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000592 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000593 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000594
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000595class WithSet(MutableSet):
596
597 def __init__(self, it=()):
598 self.data = set(it)
599
600 def __len__(self):
601 return len(self.data)
602
603 def __iter__(self):
604 return iter(self.data)
605
606 def __contains__(self, item):
607 return item in self.data
608
609 def add(self, item):
610 self.data.add(item)
611
612 def discard(self, item):
613 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000614
Raymond Hettingerae650182009-01-28 23:33:59 +0000615class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000616
617 # XXX For now, we only test some virtual inheritance properties.
618 # We should also test the proper behavior of the collection ABCs
619 # as real base classes or mix-in classes.
620
621 def test_Set(self):
622 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000623 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000624 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000625 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000626 class MySet(Set):
627 def __contains__(self, x):
628 return False
629 def __len__(self):
630 return 0
631 def __iter__(self):
632 return iter([])
633 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000634
Benjamin Peterson41181742008-07-02 20:22:54 +0000635 def test_hash_Set(self):
636 class OneTwoThreeSet(Set):
637 def __init__(self):
638 self.contents = [1, 2, 3]
639 def __contains__(self, x):
640 return x in self.contents
641 def __len__(self):
642 return len(self.contents)
643 def __iter__(self):
644 return iter(self.contents)
645 def __hash__(self):
646 return self._hash()
647 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000648 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000649
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000650 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000651 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000652 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000653 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000654 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000655 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
656 'add', 'discard')
657
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000658 def test_issue_5647(self):
659 # MutableSet.__iand__ mutated the set during iteration
660 s = WithSet('abcd')
661 s &= WithSet('cdef') # This used to fail
662 self.assertEqual(set(s), set('cd'))
663
Raymond Hettingerae650182009-01-28 23:33:59 +0000664 def test_issue_4920(self):
665 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000666 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000667 __slots__=['__s']
668 def __init__(self,items=None):
669 if items is None:
670 items=[]
671 self.__s=set(items)
672 def __contains__(self,v):
673 return v in self.__s
674 def __iter__(self):
675 return iter(self.__s)
676 def __len__(self):
677 return len(self.__s)
678 def add(self,v):
679 result=v not in self.__s
680 self.__s.add(v)
681 return result
682 def discard(self,v):
683 result=v in self.__s
684 self.__s.discard(v)
685 return result
686 def __repr__(self):
687 return "MySet(%s)" % repr(list(self))
688 s = MySet([5,43,2,1])
689 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000690
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000691 def test_issue8750(self):
692 empty = WithSet()
693 full = WithSet(range(10))
694 s = WithSet(full)
695 s -= s
696 self.assertEqual(s, empty)
697 s = WithSet(full)
698 s ^= s
699 self.assertEqual(s, empty)
700 s = WithSet(full)
701 s &= s
702 self.assertEqual(s, full)
703 s |= s
704 self.assertEqual(s, full)
705
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200706 def test_issue16373(self):
707 # Recursion error comparing comparable and noncomparable
708 # Set instances
709 class MyComparableSet(Set):
710 def __contains__(self, x):
711 return False
712 def __len__(self):
713 return 0
714 def __iter__(self):
715 return iter([])
716 class MyNonComparableSet(Set):
717 def __contains__(self, x):
718 return False
719 def __len__(self):
720 return 0
721 def __iter__(self):
722 return iter([])
723 def __le__(self, x):
724 return NotImplemented
725 def __lt__(self, x):
726 return NotImplemented
727
728 cs = MyComparableSet()
729 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700730 self.assertFalse(ncs < cs)
731 self.assertTrue(ncs <= cs)
732 self.assertFalse(ncs > cs)
733 self.assertTrue(ncs >= cs)
734
735 def assertSameSet(self, s1, s2):
736 # coerce both to a real set then check equality
737 self.assertSetEqual(set(s1), set(s2))
738
739 def test_Set_interoperability_with_real_sets(self):
740 # Issue: 8743
741 class ListSet(Set):
742 def __init__(self, elements=()):
743 self.data = []
744 for elem in elements:
745 if elem not in self.data:
746 self.data.append(elem)
747 def __contains__(self, elem):
748 return elem in self.data
749 def __iter__(self):
750 return iter(self.data)
751 def __len__(self):
752 return len(self.data)
753 def __repr__(self):
754 return 'Set({!r})'.format(self.data)
755
756 r1 = set('abc')
757 r2 = set('bcd')
758 r3 = set('abcde')
759 f1 = ListSet('abc')
760 f2 = ListSet('bcd')
761 f3 = ListSet('abcde')
762 l1 = list('abccba')
763 l2 = list('bcddcb')
764 l3 = list('abcdeedcba')
765
766 target = r1 & r2
767 self.assertSameSet(f1 & f2, target)
768 self.assertSameSet(f1 & r2, target)
769 self.assertSameSet(r2 & f1, target)
770 self.assertSameSet(f1 & l2, target)
771
772 target = r1 | r2
773 self.assertSameSet(f1 | f2, target)
774 self.assertSameSet(f1 | r2, target)
775 self.assertSameSet(r2 | f1, target)
776 self.assertSameSet(f1 | l2, target)
777
778 fwd_target = r1 - r2
779 rev_target = r2 - r1
780 self.assertSameSet(f1 - f2, fwd_target)
781 self.assertSameSet(f2 - f1, rev_target)
782 self.assertSameSet(f1 - r2, fwd_target)
783 self.assertSameSet(f2 - r1, rev_target)
784 self.assertSameSet(r1 - f2, fwd_target)
785 self.assertSameSet(r2 - f1, rev_target)
786 self.assertSameSet(f1 - l2, fwd_target)
787 self.assertSameSet(f2 - l1, rev_target)
788
789 target = r1 ^ r2
790 self.assertSameSet(f1 ^ f2, target)
791 self.assertSameSet(f1 ^ r2, target)
792 self.assertSameSet(r2 ^ f1, target)
793 self.assertSameSet(f1 ^ l2, target)
794
795 # Don't change the following to use assertLess or other
796 # "more specific" unittest assertions. The current
797 # assertTrue/assertFalse style makes the pattern of test
798 # case combinations clear and allows us to know for sure
799 # the exact operator being invoked.
800
801 # proper subset
802 self.assertTrue(f1 < f3)
803 self.assertFalse(f1 < f1)
804 self.assertFalse(f1 < f2)
805 self.assertTrue(r1 < f3)
806 self.assertFalse(r1 < f1)
807 self.assertFalse(r1 < f2)
808 self.assertTrue(r1 < r3)
809 self.assertFalse(r1 < r1)
810 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200811 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700812 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200813 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700814 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200815 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700816 f1 < l2
817
818 # any subset
819 self.assertTrue(f1 <= f3)
820 self.assertTrue(f1 <= f1)
821 self.assertFalse(f1 <= f2)
822 self.assertTrue(r1 <= f3)
823 self.assertTrue(r1 <= f1)
824 self.assertFalse(r1 <= f2)
825 self.assertTrue(r1 <= r3)
826 self.assertTrue(r1 <= r1)
827 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200828 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700829 f1 <= l3
830 with self.assertRaises(TypeError):
831 f1 <= l1
832 with self.assertRaises(TypeError):
833 f1 <= l2
834
835 # proper superset
836 self.assertTrue(f3 > f1)
837 self.assertFalse(f1 > f1)
838 self.assertFalse(f2 > f1)
839 self.assertTrue(r3 > r1)
840 self.assertFalse(f1 > r1)
841 self.assertFalse(f2 > r1)
842 self.assertTrue(r3 > r1)
843 self.assertFalse(r1 > r1)
844 self.assertFalse(r2 > r1)
845 with self.assertRaises(TypeError):
846 f1 > l3
847 with self.assertRaises(TypeError):
848 f1 > l1
849 with self.assertRaises(TypeError):
850 f1 > l2
851
852 # any superset
853 self.assertTrue(f3 >= f1)
854 self.assertTrue(f1 >= f1)
855 self.assertFalse(f2 >= f1)
856 self.assertTrue(r3 >= r1)
857 self.assertTrue(f1 >= r1)
858 self.assertFalse(f2 >= r1)
859 self.assertTrue(r3 >= r1)
860 self.assertTrue(r1 >= r1)
861 self.assertFalse(r2 >= r1)
862 with self.assertRaises(TypeError):
863 f1 >= l3
864 with self.assertRaises(TypeError):
865 f1 >=l1
866 with self.assertRaises(TypeError):
867 f1 >= l2
868
869 # equality
870 self.assertTrue(f1 == f1)
871 self.assertTrue(r1 == f1)
872 self.assertTrue(f1 == r1)
873 self.assertFalse(f1 == f3)
874 self.assertFalse(r1 == f3)
875 self.assertFalse(f1 == r3)
876 self.assertFalse(f1 == l3)
877 self.assertFalse(f1 == l1)
878 self.assertFalse(f1 == l2)
879
880 # inequality
881 self.assertFalse(f1 != f1)
882 self.assertFalse(r1 != f1)
883 self.assertFalse(f1 != r1)
884 self.assertTrue(f1 != f3)
885 self.assertTrue(r1 != f3)
886 self.assertTrue(f1 != r3)
887 self.assertTrue(f1 != l3)
888 self.assertTrue(f1 != l1)
889 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200890
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000891 def test_Mapping(self):
892 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000893 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000894 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000895 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
896 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000897 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000898 def __len__(self):
899 return 0
900 def __getitem__(self, i):
901 raise IndexError
902 def __iter__(self):
903 return iter(())
904 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000905
906 def test_MutableMapping(self):
907 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000908 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000909 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000910 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
911 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000912
Raymond Hettinger9117c752010-08-22 07:44:24 +0000913 def test_MutableMapping_subclass(self):
914 # Test issue 9214
915 mymap = UserDict()
916 mymap['red'] = 5
917 self.assertIsInstance(mymap.keys(), Set)
918 self.assertIsInstance(mymap.keys(), KeysView)
919 self.assertIsInstance(mymap.items(), Set)
920 self.assertIsInstance(mymap.items(), ItemsView)
921
922 mymap = UserDict()
923 mymap['red'] = 5
924 z = mymap.keys() | {'orange'}
925 self.assertIsInstance(z, set)
926 list(z)
927 mymap['blue'] = 7 # Shouldn't affect 'z'
928 self.assertEqual(sorted(z), ['orange', 'red'])
929
930 mymap = UserDict()
931 mymap['red'] = 5
932 z = mymap.items() | {('orange', 3)}
933 self.assertIsInstance(z, set)
934 list(z)
935 mymap['blue'] = 7 # Shouldn't affect 'z'
936 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
937
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000938 def test_Sequence(self):
939 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000940 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000941 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000942 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000943 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +1000944 self.assertIsInstance(memoryview(b""), Sequence)
945 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000946 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000947 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
948 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000949
Guido van Rossumd05eb002007-11-21 22:26:24 +0000950 def test_ByteString(self):
951 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000952 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000953 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000954 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000955 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000956 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000957 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000958 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000959
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000960 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000961 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000962 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000963 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000964 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000965 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000966 self.assertTrue(issubclass(sample, MutableSequence))
967 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000968 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
969 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000970
Eli Bendersky0716a572011-03-04 10:38:14 +0000971 def test_MutableSequence_mixins(self):
972 # Test the mixins of MutableSequence by creating a miminal concrete
973 # class inherited from it.
974 class MutableSequenceSubclass(MutableSequence):
975 def __init__(self):
976 self.lst = []
977
978 def __setitem__(self, index, value):
979 self.lst[index] = value
980
981 def __getitem__(self, index):
982 return self.lst[index]
983
984 def __len__(self):
985 return len(self.lst)
986
987 def __delitem__(self, index):
988 del self.lst[index]
989
990 def insert(self, index, value):
991 self.lst.insert(index, value)
992
993 mss = MutableSequenceSubclass()
994 mss.append(0)
995 mss.extend((1, 2, 3, 4))
996 self.assertEqual(len(mss), 5)
997 self.assertEqual(mss[3], 3)
998 mss.reverse()
999 self.assertEqual(mss[3], 1)
1000 mss.pop()
1001 self.assertEqual(len(mss), 4)
1002 mss.remove(3)
1003 self.assertEqual(len(mss), 3)
1004 mss += (10, 20, 30)
1005 self.assertEqual(len(mss), 6)
1006 self.assertEqual(mss[-1], 30)
1007 mss.clear()
1008 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001009
1010################################################################################
1011### Counter
1012################################################################################
1013
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001014class CounterSubclassWithSetItem(Counter):
1015 # Test a counter subclass that overrides __setitem__
1016 def __init__(self, *args, **kwds):
1017 self.called = False
1018 Counter.__init__(self, *args, **kwds)
1019 def __setitem__(self, key, value):
1020 self.called = True
1021 Counter.__setitem__(self, key, value)
1022
1023class CounterSubclassWithGet(Counter):
1024 # Test a counter subclass that overrides get()
1025 def __init__(self, *args, **kwds):
1026 self.called = False
1027 Counter.__init__(self, *args, **kwds)
1028 def get(self, key, default):
1029 self.called = True
1030 return Counter.get(self, key, default)
1031
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001032class TestCounter(unittest.TestCase):
1033
1034 def test_basics(self):
1035 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001036 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1037 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001038 self.assertIsInstance(c, dict)
1039 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001040 self.assertTrue(issubclass(Counter, dict))
1041 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001042 self.assertEqual(len(c), 3)
1043 self.assertEqual(sum(c.values()), 6)
1044 self.assertEqual(sorted(c.values()), [1, 2, 3])
1045 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
1046 self.assertEqual(sorted(c), ['a', 'b', 'c'])
1047 self.assertEqual(sorted(c.items()),
1048 [('a', 3), ('b', 2), ('c', 1)])
1049 self.assertEqual(c['b'], 2)
1050 self.assertEqual(c['z'], 0)
1051 self.assertEqual(c.__contains__('c'), True)
1052 self.assertEqual(c.__contains__('z'), False)
1053 self.assertEqual(c.get('b', 10), 2)
1054 self.assertEqual(c.get('z', 10), 10)
1055 self.assertEqual(c, dict(a=3, b=2, c=1))
1056 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1057 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1058 for i in range(5):
1059 self.assertEqual(c.most_common(i),
1060 [('a', 3), ('b', 2), ('c', 1)][:i])
1061 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
1062 c['a'] += 1 # increment an existing value
1063 c['b'] -= 2 # sub existing value to zero
1064 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001065 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001066 c['d'] -= 2 # sub from a missing value
1067 c['e'] = -5 # directly assign a missing value
1068 c['f'] += 4 # add to a missing value
1069 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
1070 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
1071 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001072 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001073 for i in range(3):
1074 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001075 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001076 c.clear()
1077 self.assertEqual(c, {})
1078 self.assertEqual(repr(c), 'Counter()')
1079 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1080 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001081 c.update(dict(a=5, b=3))
1082 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001083 c.update(Counter('a' * 50 + 'b' * 30))
1084 c.update() # test case with no args
1085 c.__init__('a' * 500 + 'b' * 300)
1086 c.__init__('cdc')
1087 c.__init__()
1088 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1089 self.assertEqual(c.setdefault('d', 5), 1)
1090 self.assertEqual(c['d'], 1)
1091 self.assertEqual(c.setdefault('e', 5), 5)
1092 self.assertEqual(c['e'], 5)
1093
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001094 def test_init(self):
1095 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1096 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1097 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1098 self.assertRaises(TypeError, Counter, 42)
1099 self.assertRaises(TypeError, Counter, (), ())
1100 self.assertRaises(TypeError, Counter.__init__)
1101
1102 def test_update(self):
1103 c = Counter()
1104 c.update(self=42)
1105 self.assertEqual(list(c.items()), [('self', 42)])
1106 c = Counter()
1107 c.update(iterable=42)
1108 self.assertEqual(list(c.items()), [('iterable', 42)])
1109 c = Counter()
1110 c.update(iterable=None)
1111 self.assertEqual(list(c.items()), [('iterable', None)])
1112 self.assertRaises(TypeError, Counter().update, 42)
1113 self.assertRaises(TypeError, Counter().update, {}, {})
1114 self.assertRaises(TypeError, Counter.update)
1115
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001116 def test_copying(self):
1117 # Check that counters are copyable, deepcopyable, picklable, and
1118 #have a repr/eval round-trip
1119 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02001120 def check(dup):
1121 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1122 self.assertIsNot(dup, words, msg)
1123 self.assertEqual(dup, words)
1124 check(words.copy())
1125 check(copy.copy(words))
1126 check(copy.deepcopy(words))
1127 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1128 with self.subTest(proto=proto):
1129 check(pickle.loads(pickle.dumps(words, proto)))
1130 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001131 update_test = Counter()
1132 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001133 check(update_test)
1134 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001135
Raymond Hettinger1c746c22011-04-15 13:16:46 -07001136 def test_copy_subclass(self):
1137 class MyCounter(Counter):
1138 pass
1139 c = MyCounter('slartibartfast')
1140 d = c.copy()
1141 self.assertEqual(d, c)
1142 self.assertEqual(len(d), len(c))
1143 self.assertEqual(type(d), type(c))
1144
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001145 def test_conversions(self):
1146 # Convert to: set, list, dict
1147 s = 'she sells sea shells by the sea shore'
1148 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
1149 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
1150 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
1151 self.assertEqual(set(Counter(s)), set(s))
1152
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001153 def test_invariant_for_the_in_operator(self):
1154 c = Counter(a=10, b=-2, c=0)
1155 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001156 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001157 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001158
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001159 def test_multiset_operations(self):
1160 # Verify that adding a zero counter will strip zeros and negatives
1161 c = Counter(a=10, b=-2, c=0) + Counter()
1162 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001163
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001164 elements = 'abcd'
1165 for i in range(1000):
1166 # test random pairs of multisets
1167 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001168 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001169 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001170 q.update(h=1, i=-1, j=0)
1171 for counterop, numberop in [
1172 (Counter.__add__, lambda x, y: max(0, x+y)),
1173 (Counter.__sub__, lambda x, y: max(0, x-y)),
1174 (Counter.__or__, lambda x, y: max(0,x,y)),
1175 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001176 ]:
1177 result = counterop(p, q)
1178 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001179 self.assertEqual(numberop(p[x], q[x]), result[x],
1180 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001181 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001182 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001183
1184 elements = 'abcdef'
1185 for i in range(100):
1186 # verify that random multisets with no repeats are exactly like sets
1187 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1188 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1189 for counterop, setop in [
1190 (Counter.__sub__, set.__sub__),
1191 (Counter.__or__, set.__or__),
1192 (Counter.__and__, set.__and__),
1193 ]:
1194 counter_result = counterop(p, q)
1195 set_result = setop(set(p.elements()), set(q.elements()))
1196 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001197
Raymond Hettingerbecd5682011-10-19 13:40:37 -07001198 def test_inplace_operations(self):
1199 elements = 'abcd'
1200 for i in range(1000):
1201 # test random pairs of multisets
1202 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1203 p.update(e=1, f=-1, g=0)
1204 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1205 q.update(h=1, i=-1, j=0)
1206 for inplace_op, regular_op in [
1207 (Counter.__iadd__, Counter.__add__),
1208 (Counter.__isub__, Counter.__sub__),
1209 (Counter.__ior__, Counter.__or__),
1210 (Counter.__iand__, Counter.__and__),
1211 ]:
1212 c = p.copy()
1213 c_id = id(c)
1214 regular_result = regular_op(c, q)
1215 inplace_result = inplace_op(c, q)
1216 self.assertEqual(inplace_result, regular_result)
1217 self.assertEqual(id(inplace_result), c_id)
1218
Raymond Hettinger9c01e442010-04-03 10:32:58 +00001219 def test_subtract(self):
1220 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1221 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
1222 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1223 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1224 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
1225 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1226 c = Counter('aaabbcd')
1227 c.subtract('aaaabbcce')
1228 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001229
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001230 c = Counter()
1231 c.subtract(self=42)
1232 self.assertEqual(list(c.items()), [('self', -42)])
1233 c = Counter()
1234 c.subtract(iterable=42)
1235 self.assertEqual(list(c.items()), [('iterable', -42)])
1236 self.assertRaises(TypeError, Counter().subtract, 42)
1237 self.assertRaises(TypeError, Counter().subtract, {}, {})
1238 self.assertRaises(TypeError, Counter.subtract)
1239
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07001240 def test_unary(self):
1241 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1242 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
1243 self.assertEqual(dict(-c), dict(a=5))
1244
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07001245 def test_repr_nonsortable(self):
1246 c = Counter(a=2, b=None)
1247 r = repr(c)
1248 self.assertIn("'a': 2", r)
1249 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07001250
Raymond Hettinger426e0522011-01-03 02:12:02 +00001251 def test_helper_function(self):
1252 # two paths, one for real dicts and one for other mappings
1253 elems = list('abracadabra')
1254
1255 d = dict()
1256 _count_elements(d, elems)
1257 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1258
1259 m = OrderedDict()
1260 _count_elements(m, elems)
1261 self.assertEqual(m,
1262 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
1263
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001264 # test fidelity to the pure python version
1265 c = CounterSubclassWithSetItem('abracadabra')
1266 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001267 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001268 c = CounterSubclassWithGet('abracadabra')
1269 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001270 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001271
Raymond Hettinger499e1932011-02-23 07:56:53 +00001272
1273################################################################################
1274### OrderedDict
1275################################################################################
1276
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001277class TestOrderedDict(unittest.TestCase):
1278
1279 def test_init(self):
1280 with self.assertRaises(TypeError):
1281 OrderedDict([('a', 1), ('b', 2)], None) # too many args
1282 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1283 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
1284 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
1285 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
1286 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
1287 c=3, e=5).items()), pairs) # mixed input
1288
1289 # make sure no positional args conflict with possible kwdargs
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001290 self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
1291 self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
1292 self.assertRaises(TypeError, OrderedDict, 42)
1293 self.assertRaises(TypeError, OrderedDict, (), ())
1294 self.assertRaises(TypeError, OrderedDict.__init__)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001295
1296 # Make sure that direct calls to __init__ do not clear previous contents
1297 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1298 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
1299 self.assertEqual(list(d.items()),
1300 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1301
1302 def test_update(self):
1303 with self.assertRaises(TypeError):
1304 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
1305 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1306 od = OrderedDict()
1307 od.update(dict(pairs))
1308 self.assertEqual(sorted(od.items()), pairs) # dict input
1309 od = OrderedDict()
1310 od.update(**dict(pairs))
1311 self.assertEqual(sorted(od.items()), pairs) # kwds input
1312 od = OrderedDict()
1313 od.update(pairs)
1314 self.assertEqual(list(od.items()), pairs) # pairs input
1315 od = OrderedDict()
1316 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1317 self.assertEqual(list(od.items()), pairs) # mixed input
1318
Mark Dickinsonb214e902010-07-11 18:53:06 +00001319 # Issue 9137: Named argument called 'other' or 'self'
1320 # shouldn't be treated specially.
1321 od = OrderedDict()
1322 od.update(self=23)
1323 self.assertEqual(list(od.items()), [('self', 23)])
1324 od = OrderedDict()
1325 od.update(other={})
1326 self.assertEqual(list(od.items()), [('other', {})])
1327 od = OrderedDict()
1328 od.update(red=5, blue=6, other=7, self=8)
1329 self.assertEqual(sorted(list(od.items())),
1330 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
1331
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001332 # Make sure that direct calls to update do not clear previous contents
1333 # add that updates items are not moved to the end
1334 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1335 d.update([('e', 5), ('f', 6)], g=7, d=4)
1336 self.assertEqual(list(d.items()),
1337 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1338
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001339 self.assertRaises(TypeError, OrderedDict().update, 42)
1340 self.assertRaises(TypeError, OrderedDict().update, (), ())
1341 self.assertRaises(TypeError, OrderedDict.update)
1342
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001343 def test_abc(self):
1344 self.assertIsInstance(OrderedDict(), MutableMapping)
1345 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1346
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001347 def test_clear(self):
1348 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1349 shuffle(pairs)
1350 od = OrderedDict(pairs)
1351 self.assertEqual(len(od), len(pairs))
1352 od.clear()
1353 self.assertEqual(len(od), 0)
1354
1355 def test_delitem(self):
1356 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1357 od = OrderedDict(pairs)
1358 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001359 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001360 with self.assertRaises(KeyError):
1361 del od['a']
1362 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1363
1364 def test_setitem(self):
1365 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1366 od['c'] = 10 # existing element
1367 od['f'] = 20 # new element
1368 self.assertEqual(list(od.items()),
1369 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1370
1371 def test_iterators(self):
1372 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1373 shuffle(pairs)
1374 od = OrderedDict(pairs)
1375 self.assertEqual(list(od), [t[0] for t in pairs])
1376 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1377 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1378 self.assertEqual(list(od.items()), pairs)
1379 self.assertEqual(list(reversed(od)),
1380 [t[0] for t in reversed(pairs)])
1381
1382 def test_popitem(self):
1383 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1384 shuffle(pairs)
1385 od = OrderedDict(pairs)
1386 while pairs:
1387 self.assertEqual(od.popitem(), pairs.pop())
1388 with self.assertRaises(KeyError):
1389 od.popitem()
1390 self.assertEqual(len(od), 0)
1391
1392 def test_pop(self):
1393 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1394 shuffle(pairs)
1395 od = OrderedDict(pairs)
1396 shuffle(pairs)
1397 while pairs:
1398 k, v = pairs.pop()
1399 self.assertEqual(od.pop(k), v)
1400 with self.assertRaises(KeyError):
1401 od.pop('xyz')
1402 self.assertEqual(len(od), 0)
1403 self.assertEqual(od.pop(k, 12345), 12345)
1404
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001405 # make sure pop still works when __missing__ is defined
1406 class Missing(OrderedDict):
1407 def __missing__(self, key):
1408 return 0
1409 m = Missing(a=1)
1410 self.assertEqual(m.pop('b', 5), 5)
1411 self.assertEqual(m.pop('a', 6), 1)
1412 self.assertEqual(m.pop('a', 6), 6)
1413 with self.assertRaises(KeyError):
1414 m.pop('a')
1415
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001416 def test_equality(self):
1417 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1418 shuffle(pairs)
1419 od1 = OrderedDict(pairs)
1420 od2 = OrderedDict(pairs)
1421 self.assertEqual(od1, od2) # same order implies equality
1422 pairs = pairs[2:] + pairs[:2]
1423 od2 = OrderedDict(pairs)
1424 self.assertNotEqual(od1, od2) # different order implies inequality
1425 # comparison to regular dict is not order sensitive
1426 self.assertEqual(od1, dict(od2))
1427 self.assertEqual(dict(od2), od1)
1428 # different length implied inequality
1429 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1430
1431 def test_copying(self):
1432 # Check that ordered dicts are copyable, deepcopyable, picklable,
1433 # and have a repr/eval round-trip
1434 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1435 od = OrderedDict(pairs)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001436 def check(dup):
1437 msg = "\ncopy: %s\nod: %s" % (dup, od)
1438 self.assertIsNot(dup, od, msg)
1439 self.assertEqual(dup, od)
1440 check(od.copy())
1441 check(copy.copy(od))
1442 check(copy.deepcopy(od))
1443 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1444 with self.subTest(proto=proto):
1445 check(pickle.loads(pickle.dumps(od, proto)))
1446 check(eval(repr(od)))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001447 update_test = OrderedDict()
1448 update_test.update(od)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001449 check(update_test)
1450 check(OrderedDict(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001451
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001452 def test_yaml_linkage(self):
1453 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1454 # In yaml, lists are native but tuples are not.
1455 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1456 od = OrderedDict(pairs)
1457 # yaml.dump(od) -->
1458 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001459 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001460
Raymond Hettingerb2121572009-03-03 22:50:04 +00001461 def test_reduce_not_too_fat(self):
1462 # do not save instance dictionary if not needed
1463 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1464 od = OrderedDict(pairs)
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001465 self.assertIsNone(od.__reduce__()[2])
Raymond Hettingerb2121572009-03-03 22:50:04 +00001466 od.x = 10
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001467 self.assertIsNotNone(od.__reduce__()[2])
1468
1469 def test_pickle_recursive(self):
1470 od = OrderedDict()
1471 od[1] = od
1472 for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
1473 dup = pickle.loads(pickle.dumps(od, proto))
1474 self.assertIsNot(dup, od)
1475 self.assertEqual(list(dup.keys()), [1])
1476 self.assertIs(dup[1], dup)
Raymond Hettingerb2121572009-03-03 22:50:04 +00001477
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001478 def test_repr(self):
1479 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1480 self.assertEqual(repr(od),
1481 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1482 self.assertEqual(eval(repr(od)), od)
1483 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1484
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001485 def test_repr_recursive(self):
1486 # See issue #9826
1487 od = OrderedDict.fromkeys('abc')
1488 od['x'] = od
1489 self.assertEqual(repr(od),
1490 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1491
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001492 def test_setdefault(self):
1493 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1494 shuffle(pairs)
1495 od = OrderedDict(pairs)
1496 pair_order = list(od.items())
1497 self.assertEqual(od.setdefault('a', 10), 3)
1498 # make sure order didn't change
1499 self.assertEqual(list(od.items()), pair_order)
1500 self.assertEqual(od.setdefault('x', 10), 10)
1501 # make sure 'x' is added to the end
1502 self.assertEqual(list(od.items())[-1], ('x', 10))
1503
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001504 # make sure setdefault still works when __missing__ is defined
1505 class Missing(OrderedDict):
1506 def __missing__(self, key):
1507 return 0
1508 self.assertEqual(Missing().setdefault(5, 9), 9)
1509
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001510 def test_reinsert(self):
1511 # Given insert a, insert b, delete a, re-insert a,
1512 # verify that a is now later than b.
1513 od = OrderedDict()
1514 od['a'] = 1
1515 od['b'] = 2
1516 del od['a']
1517 od['a'] = 1
1518 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1519
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001520 def test_move_to_end(self):
1521 od = OrderedDict.fromkeys('abcde')
1522 self.assertEqual(list(od), list('abcde'))
1523 od.move_to_end('c')
1524 self.assertEqual(list(od), list('abdec'))
1525 od.move_to_end('c', 0)
1526 self.assertEqual(list(od), list('cabde'))
1527 od.move_to_end('c', 0)
1528 self.assertEqual(list(od), list('cabde'))
1529 od.move_to_end('e')
1530 self.assertEqual(list(od), list('cabde'))
1531 with self.assertRaises(KeyError):
1532 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001533
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001534 def test_sizeof(self):
1535 # Wimpy test: Just verify the reported size is larger than a regular dict
1536 d = dict(a=1)
1537 od = OrderedDict(**d)
1538 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1539
Raymond Hettinger32062e92011-01-01 22:38:00 +00001540 def test_override_update(self):
1541 # Verify that subclasses can override update() without breaking __init__()
1542 class MyOD(OrderedDict):
1543 def update(self, *args, **kwds):
1544 raise Exception()
1545 items = [('a', 1), ('c', 3), ('b', 2)]
1546 self.assertEqual(list(MyOD(items).items()), items)
1547
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001548class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1549 type2test = OrderedDict
1550
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001551 def test_popitem(self):
1552 d = self._empty_mapping()
1553 self.assertRaises(KeyError, d.popitem)
1554
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001555class MyOrderedDict(OrderedDict):
1556 pass
1557
1558class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1559 type2test = MyOrderedDict
1560
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001561 def test_popitem(self):
1562 d = self._empty_mapping()
1563 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001564
1565
Raymond Hettinger499e1932011-02-23 07:56:53 +00001566################################################################################
1567### Run tests
1568################################################################################
1569
Christian Heimes25bb7832008-01-11 16:17:00 +00001570import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001571
Guido van Rossumd8faa362007-04-27 19:54:29 +00001572def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001573 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001574 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001575 TestCollectionABCs, TestCounter, TestChainMap,
Serhiy Storchakaa86700a2014-11-27 17:45:44 +02001576 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001577 support.run_unittest(*test_classes)
1578 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001579
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001580
Guido van Rossumd8faa362007-04-27 19:54:29 +00001581if __name__ == "__main__":
1582 test_main(verbose=True)