blob: 958fb6282453fe1adb8c809a11d6c033ea06c11d [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 Hettinger32ea1652015-03-21 01:37:37 -070016from collections import deque
Raymond Hettinger57d1a882011-02-23 00:46:28 +000017from collections.abc import Hashable, Iterable, Iterator
18from collections.abc import Sized, Container, Callable
19from collections.abc import Set, MutableSet
20from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
21from collections.abc import Sequence, MutableSequence
22from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000023
Raymond Hettinger499e1932011-02-23 07:56:53 +000024
25################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000026### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000027################################################################################
28
29class TestChainMap(unittest.TestCase):
30
31 def test_basics(self):
32 c = ChainMap()
33 c['a'] = 1
34 c['b'] = 2
35 d = c.new_child()
36 d['b'] = 20
37 d['c'] = 30
38 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
39 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
40 self.assertEqual(len(d), 3) # check len
41 for key in 'abc': # check contains
42 self.assertIn(key, d)
43 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
44 self.assertEqual(d.get(k, 100), v)
45
46 del d['b'] # unmask a value
47 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
48 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
49 self.assertEqual(len(d), 3) # check len
50 for key in 'abc': # check contains
51 self.assertIn(key, d)
52 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
53 self.assertEqual(d.get(k, 100), v)
54 self.assertIn(repr(d), [ # check repr
55 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
56 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
57 ])
58
59 for e in d.copy(), copy.copy(d): # check shallow copies
60 self.assertEqual(d, e)
61 self.assertEqual(d.maps, e.maps)
62 self.assertIsNot(d, e)
63 self.assertIsNot(d.maps[0], e.maps[0])
64 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
65 self.assertIs(m1, m2)
66
Serhiy Storchakabad12572014-12-15 14:03:42 +020067 # check deep copies
68 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
69 e = pickle.loads(pickle.dumps(d, proto))
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 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +000076 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +020077 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +000078 self.assertEqual(d, e)
79 self.assertEqual(d.maps, e.maps)
80 self.assertIsNot(d, e)
81 for m1, m2 in zip(d.maps, e.maps):
82 self.assertIsNot(m1, m2, e)
83
Raymond Hettingerd0321312011-02-26 06:53:58 +000084 f = d.new_child()
85 f['b'] = 5
86 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
87 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
88 self.assertEqual(f['b'], 5) # find first in chain
89 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +000090
91 def test_contructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +000092 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +000093 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
94
Raymond Hettingerd0321312011-02-26 06:53:58 +000095 def test_bool(self):
96 self.assertFalse(ChainMap())
97 self.assertFalse(ChainMap({}, {}))
98 self.assertTrue(ChainMap({1:2}, {}))
99 self.assertTrue(ChainMap({}, {1:2}))
100
Raymond Hettinger499e1932011-02-23 07:56:53 +0000101 def test_missing(self):
102 class DefaultChainMap(ChainMap):
103 def __missing__(self, key):
104 return 999
105 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
106 for k, v in dict(a=1, b=2, c=30, d=999).items():
107 self.assertEqual(d[k], v) # check __getitem__ w/missing
108 for k, v in dict(a=1, b=2, c=30, d=77).items():
109 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
110 for k, v in dict(a=True, b=True, c=True, d=False).items():
111 self.assertEqual(k in d, v) # check __contains__ w/missing
112 self.assertEqual(d.pop('a', 1001), 1, d)
113 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
114 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
115 with self.assertRaises(KeyError):
116 d.popitem()
117
118 def test_dict_coercion(self):
119 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
120 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
121 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
122
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000123 def test_new_child(self):
124 'Tests for changes for issue #16613.'
125 c = ChainMap()
126 c['a'] = 1
127 c['b'] = 2
128 m = {'b':20, 'c': 30}
129 d = c.new_child(m)
130 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
131 self.assertIs(m, d.maps[0])
132
133 # Use a different map than a dict
134 class lowerdict(dict):
135 def __getitem__(self, key):
136 if isinstance(key, str):
137 key = key.lower()
138 return dict.__getitem__(self, key)
139 def __contains__(self, key):
140 if isinstance(key, str):
141 key = key.lower()
142 return dict.__contains__(self, key)
143
144 c = ChainMap()
145 c['a'] = 1
146 c['b'] = 2
147 m = lowerdict(b=20, c=30)
148 d = c.new_child(m)
149 self.assertIs(m, d.maps[0])
150 for key in 'abc': # check contains
151 self.assertIn(key, d)
152 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
153 self.assertEqual(d.get(k, 100), v)
154
Raymond Hettinger499e1932011-02-23 07:56:53 +0000155
156################################################################################
157### Named Tuples
158################################################################################
159
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000160TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000161
162class TestNamedTuple(unittest.TestCase):
163
164 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000165 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000166 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000167 self.assertEqual(Point.__slots__, ())
168 self.assertEqual(Point.__module__, __name__)
169 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000170 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettinger2ebea412011-03-23 12:52:23 -0700171 self.assertIn('class Point(tuple)', Point._source)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000172
173 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
174 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
175 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
176
177 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
178 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
179 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000180 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000181 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
182
183 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000184 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000185
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000186 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000187 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000188 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000189 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000190
Christian Heimesfaf2f632008-01-06 16:59:19 +0000191 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
192 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
193
R. David Murray378c0cf2010-02-24 01:46:21 +0000194 @unittest.skipIf(sys.flags.optimize >= 2,
195 "Docstrings are omitted with -O2 and above")
196 def test_factory_doc_attr(self):
197 Point = namedtuple('Point', 'x y')
198 self.assertEqual(Point.__doc__, 'Point(x, y)')
199
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000200 def test_name_fixer(self):
201 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000202 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
203 [('abc', 'class'), ('abc', '_1')], # field has keyword
204 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
205 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
206 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
207 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000208 ]:
209 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
210
Guido van Rossumd8faa362007-04-27 19:54:29 +0000211 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000212 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000213 p = Point(11, 22)
214 self.assertEqual(p, Point(x=11, y=22))
215 self.assertEqual(p, Point(11, y=22))
216 self.assertEqual(p, Point(y=22, x=11))
217 self.assertEqual(p, Point(*(11, 22)))
218 self.assertEqual(p, Point(**dict(x=11, y=22)))
219 self.assertRaises(TypeError, Point, 1) # too few args
220 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
221 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
222 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
223 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000224 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000225 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000226 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
227 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
Raymond Hettinger163e9822013-05-18 00:05:20 -0700228 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
229 self.assertEqual(vars(p), p._asdict()) # verify that vars() works
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000230
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000231 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000232 p._replace(x=1, error=2)
233 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000234 pass
235 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000236 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000237
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000238 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000239 Point = namedtuple('Point', 'x, y')
240 p = Point(x=11, y=22)
241 self.assertEqual(repr(p), 'Point(x=11, y=22)')
242
243 # verify that fieldspec can be a non-string sequence
244 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000245 p = Point(x=11, y=22)
246 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000247
248 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000249 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000250 p = Point(11, 22)
251
Ezio Melottie9615932010-01-24 19:26:24 +0000252 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000253 self.assertEqual(p, (11, 22)) # matches a real tuple
254 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
255 self.assertEqual(list(p), [11, 22]) # coercable to a list
256 self.assertEqual(max(p), 22) # iterable
257 self.assertEqual(max(*p), 22) # star-able
258 x, y = p
259 self.assertEqual(p, (x, y)) # unpacks like a tuple
260 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
261 self.assertRaises(IndexError, p.__getitem__, 3)
262
263 self.assertEqual(p.x, x)
264 self.assertEqual(p.y, y)
265 self.assertRaises(AttributeError, eval, 'p.z', locals())
266
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000267 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000268 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000269 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000270 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000271 self.assertEqual(repr(Zero()), 'Zero()')
272 self.assertEqual(Zero()._asdict(), {})
273 self.assertEqual(Zero()._fields, ())
274
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000275 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000276 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000277 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000278 self.assertEqual(Dot(1).d, 1)
279 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
280 self.assertEqual(Dot(1)._asdict(), {'d':1})
281 self.assertEqual(Dot(1)._replace(d=999), (999,))
282 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000283
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000284 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000285 n = 254 # SyntaxError: more than 255 arguments:
286 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000287 names = list(set(''.join([random.choice(string.ascii_letters)
288 for j in range(10)]) for i in range(n)))
289 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000290 Big = namedtuple('Big', names)
291 b = Big(*range(n))
292 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000293 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000294 for pos, name in enumerate(names):
295 self.assertEqual(getattr(b, name), pos)
296 repr(b) # make sure repr() doesn't blow-up
297 d = b._asdict()
298 d_expected = dict(zip(names, range(n)))
299 self.assertEqual(d, d_expected)
300 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
301 b2_expected = list(range(n))
302 b2_expected[1] = 999
303 b2_expected[-5] = 42
304 self.assertEqual(b2, tuple(b2_expected))
305 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000306
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000307 def test_pickle(self):
308 p = TestNT(x=10, y=20, z=30)
309 for module in (pickle,):
310 loads = getattr(module, 'loads')
311 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500312 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000313 q = loads(dumps(p, protocol))
314 self.assertEqual(p, q)
315 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700316 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000317
318 def test_copy(self):
319 p = TestNT(x=10, y=20, z=30)
320 for copier in copy.copy, copy.deepcopy:
321 q = copier(p)
322 self.assertEqual(p, q)
323 self.assertEqual(p._fields, q._fields)
324
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000325 def test_name_conflicts(self):
326 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
327 # failed when used as field names. Test to make sure these now work.
328 T = namedtuple('T', 'itemgetter property self cls tuple')
329 t = T(1, 2, 3, 4, 5)
330 self.assertEqual(t, (1,2,3,4,5))
331 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
332 self.assertEqual(newt, (10,20,30,40,50))
333
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000334 # Broader test of all interesting names in a template
335 with support.captured_stdout() as template:
336 T = namedtuple('T', 'x', verbose=True)
337 words = set(re.findall('[A-Za-z]+', template.getvalue()))
338 words -= set(keyword.kwlist)
339 T = namedtuple('T', words)
340 # test __new__
341 values = tuple(range(len(words)))
342 t = T(*values)
343 self.assertEqual(t, values)
344 t = T(**dict(zip(T._fields, values)))
345 self.assertEqual(t, values)
346 # test _make
347 t = T._make(values)
348 self.assertEqual(t, values)
349 # exercise __repr__
350 repr(t)
351 # test _asdict
352 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
353 # test _replace
354 t = T._make(values)
355 newvalues = tuple(v*10 for v in values)
356 newt = t._replace(**dict(zip(T._fields, newvalues)))
357 self.assertEqual(newt, newvalues)
358 # test _fields
359 self.assertEqual(T._fields, tuple(words))
360 # test __getnewargs__
361 self.assertEqual(t.__getnewargs__(), values)
362
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000363 def test_repr(self):
364 with support.captured_stdout() as template:
365 A = namedtuple('A', 'x', verbose=True)
366 self.assertEqual(repr(A(1)), 'A(x=1)')
367 # repr should show the name of the subclass
368 class B(A):
369 pass
370 self.assertEqual(repr(B(1)), 'B(x=1)')
371
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700372 def test_source(self):
373 # verify that _source can be run through exec()
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700374 tmp = namedtuple('NTColor', 'red green blue')
375 globals().pop('NTColor', None) # remove artifacts from other tests
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700376 exec(tmp._source, globals())
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700377 self.assertIn('NTColor', globals())
378 c = NTColor(10, 20, 30)
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700379 self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700380 self.assertEqual(NTColor._fields, ('red', 'green', 'blue'))
381 globals().pop('NTColor', None) # clean-up after this test
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700382
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000383
Raymond Hettinger499e1932011-02-23 07:56:53 +0000384################################################################################
385### Abstract Base Classes
386################################################################################
387
Raymond Hettingerae650182009-01-28 23:33:59 +0000388class ABCTestCase(unittest.TestCase):
389
390 def validate_abstract_methods(self, abc, *names):
391 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
392
393 # everything should work will all required methods are present
394 C = type('C', (abc,), methodstubs)
395 C()
396
397 # instantiation should fail if a required method is missing
398 for name in names:
399 stubs = methodstubs.copy()
400 del stubs[name]
401 C = type('C', (abc,), stubs)
402 self.assertRaises(TypeError, C, name)
403
Florent Xiclunace153f62010-03-08 15:34:35 +0000404 def validate_isinstance(self, abc, name):
405 stub = lambda s, *args: 0
406
407 C = type('C', (object,), {'__hash__': None})
408 setattr(C, name, stub)
409 self.assertIsInstance(C(), abc)
410 self.assertTrue(issubclass(C, abc))
411
412 C = type('C', (object,), {'__hash__': None})
413 self.assertNotIsInstance(C(), abc)
414 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000415
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000416 def validate_comparison(self, instance):
417 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
418 operators = {}
419 for op in ops:
420 name = '__' + op + '__'
421 operators[name] = getattr(operator, name)
422
423 class Other:
424 def __init__(self):
425 self.right_side = False
426 def __eq__(self, other):
427 self.right_side = True
428 return True
429 __lt__ = __eq__
430 __gt__ = __eq__
431 __le__ = __eq__
432 __ge__ = __eq__
433 __ne__ = __eq__
434 __ror__ = __eq__
435 __rand__ = __eq__
436 __rxor__ = __eq__
437 __rsub__ = __eq__
438
439 for name, op in operators.items():
440 if not hasattr(instance, name):
441 continue
442 other = Other()
443 op(instance, other)
444 self.assertTrue(other.right_side,'Right side not called for %s.%s'
445 % (type(instance), name))
446
Raymond Hettingerae650182009-01-28 23:33:59 +0000447class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000448
449 def test_Hashable(self):
450 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000451 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000452 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000453 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000454 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000455 # Check some hashables
456 samples = [None,
457 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000458 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000459 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000460 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000461 ]
462 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000463 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000464 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000465 self.assertRaises(TypeError, Hashable)
466 # Check direct subclassing
467 class H(Hashable):
468 def __hash__(self):
469 return super().__hash__()
470 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000471 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000472 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000473 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000474
475 def test_Iterable(self):
476 # Check some non-iterables
477 non_samples = [None, 42, 3.14, 1j]
478 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000479 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000480 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000481 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000482 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000483 tuple(), list(), set(), frozenset(), dict(),
484 dict().keys(), dict().items(), dict().values(),
485 (lambda: (yield))(),
486 (x for x in []),
487 ]
488 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000489 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000490 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000491 # Check direct subclassing
492 class I(Iterable):
493 def __iter__(self):
494 return super().__iter__()
495 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000496 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000497 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000498 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000499
500 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000501 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000502 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000503 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000504 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000505 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000506 iter(tuple()), iter(list()), iter(dict()),
507 iter(set()), iter(frozenset()),
508 iter(dict().keys()), iter(dict().items()),
509 iter(dict().values()),
510 (lambda: (yield))(),
511 (x for x in []),
512 ]
513 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000514 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000515 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000516 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
517
518 # Issue 10565
519 class NextOnly:
520 def __next__(self):
521 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -0800522 return
Raymond Hettingeread22222010-11-29 03:56:12 +0000523 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000524
525 def test_Sized(self):
526 non_samples = [None, 42, 3.14, 1j,
527 (lambda: (yield))(),
528 (x for x in []),
529 ]
530 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000531 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000532 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000533 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000534 tuple(), list(), set(), frozenset(), dict(),
535 dict().keys(), dict().items(), dict().values(),
536 ]
537 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000538 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000539 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000540 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000541 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000542
543 def test_Container(self):
544 non_samples = [None, 42, 3.14, 1j,
545 (lambda: (yield))(),
546 (x for x in []),
547 ]
548 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000549 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000550 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000551 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000552 tuple(), list(), set(), frozenset(), dict(),
553 dict().keys(), dict().items(),
554 ]
555 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000556 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000557 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000558 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000559 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000560
561 def test_Callable(self):
562 non_samples = [None, 42, 3.14, 1j,
563 "", b"", (), [], {}, set(),
564 (lambda: (yield))(),
565 (x for x in []),
566 ]
567 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000568 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000569 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000570 samples = [lambda: None,
571 type, int, object,
572 len,
573 list.append, [].append,
574 ]
575 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000576 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000577 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000578 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000579 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000580
581 def test_direct_subclassing(self):
582 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
583 class C(B):
584 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000585 self.assertTrue(issubclass(C, B))
586 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000587
588 def test_registration(self):
589 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
590 class C:
591 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000592 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000593 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000594 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000595
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000596class WithSet(MutableSet):
597
598 def __init__(self, it=()):
599 self.data = set(it)
600
601 def __len__(self):
602 return len(self.data)
603
604 def __iter__(self):
605 return iter(self.data)
606
607 def __contains__(self, item):
608 return item in self.data
609
610 def add(self, item):
611 self.data.add(item)
612
613 def discard(self, item):
614 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000615
Raymond Hettingerae650182009-01-28 23:33:59 +0000616class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000617
618 # XXX For now, we only test some virtual inheritance properties.
619 # We should also test the proper behavior of the collection ABCs
620 # as real base classes or mix-in classes.
621
622 def test_Set(self):
623 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000624 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000625 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000626 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000627 class MySet(Set):
628 def __contains__(self, x):
629 return False
630 def __len__(self):
631 return 0
632 def __iter__(self):
633 return iter([])
634 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000635
Benjamin Peterson41181742008-07-02 20:22:54 +0000636 def test_hash_Set(self):
637 class OneTwoThreeSet(Set):
638 def __init__(self):
639 self.contents = [1, 2, 3]
640 def __contains__(self, x):
641 return x in self.contents
642 def __len__(self):
643 return len(self.contents)
644 def __iter__(self):
645 return iter(self.contents)
646 def __hash__(self):
647 return self._hash()
648 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000649 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000650
Raymond Hettinger2d452ee2014-05-25 18:28:39 -0700651 def test_isdisjoint_Set(self):
652 class MySet(Set):
653 def __init__(self, itr):
654 self.contents = itr
655 def __contains__(self, x):
656 return x in self.contents
657 def __iter__(self):
658 return iter(self.contents)
659 def __len__(self):
660 return len([x for x in self.contents])
661 s1 = MySet((1, 2, 3))
662 s2 = MySet((4, 5, 6))
663 s3 = MySet((1, 5, 6))
664 self.assertTrue(s1.isdisjoint(s2))
665 self.assertFalse(s1.isdisjoint(s3))
666
667 def test_equality_Set(self):
668 class MySet(Set):
669 def __init__(self, itr):
670 self.contents = itr
671 def __contains__(self, x):
672 return x in self.contents
673 def __iter__(self):
674 return iter(self.contents)
675 def __len__(self):
676 return len([x for x in self.contents])
677 s1 = MySet((1,))
678 s2 = MySet((1, 2))
679 s3 = MySet((3, 4))
680 s4 = MySet((3, 4))
681 self.assertTrue(s2 > s1)
682 self.assertTrue(s1 < s2)
683 self.assertFalse(s2 <= s1)
684 self.assertFalse(s2 <= s3)
685 self.assertFalse(s1 >= s2)
686 self.assertEqual(s3, s4)
687 self.assertNotEqual(s2, s3)
688
689 def test_arithmetic_Set(self):
690 class MySet(Set):
691 def __init__(self, itr):
692 self.contents = itr
693 def __contains__(self, x):
694 return x in self.contents
695 def __iter__(self):
696 return iter(self.contents)
697 def __len__(self):
698 return len([x for x in self.contents])
699 s1 = MySet((1, 2, 3))
700 s2 = MySet((3, 4, 5))
701 s3 = s1 & s2
702 self.assertEqual(s3, MySet((3,)))
703
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000704 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000705 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000706 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000707 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000708 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000709 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
710 'add', 'discard')
711
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000712 def test_issue_5647(self):
713 # MutableSet.__iand__ mutated the set during iteration
714 s = WithSet('abcd')
715 s &= WithSet('cdef') # This used to fail
716 self.assertEqual(set(s), set('cd'))
717
Raymond Hettingerae650182009-01-28 23:33:59 +0000718 def test_issue_4920(self):
719 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000720 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000721 __slots__=['__s']
722 def __init__(self,items=None):
723 if items is None:
724 items=[]
725 self.__s=set(items)
726 def __contains__(self,v):
727 return v in self.__s
728 def __iter__(self):
729 return iter(self.__s)
730 def __len__(self):
731 return len(self.__s)
732 def add(self,v):
733 result=v not in self.__s
734 self.__s.add(v)
735 return result
736 def discard(self,v):
737 result=v in self.__s
738 self.__s.discard(v)
739 return result
740 def __repr__(self):
741 return "MySet(%s)" % repr(list(self))
742 s = MySet([5,43,2,1])
743 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000744
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000745 def test_issue8750(self):
746 empty = WithSet()
747 full = WithSet(range(10))
748 s = WithSet(full)
749 s -= s
750 self.assertEqual(s, empty)
751 s = WithSet(full)
752 s ^= s
753 self.assertEqual(s, empty)
754 s = WithSet(full)
755 s &= s
756 self.assertEqual(s, full)
757 s |= s
758 self.assertEqual(s, full)
759
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200760 def test_issue16373(self):
761 # Recursion error comparing comparable and noncomparable
762 # Set instances
763 class MyComparableSet(Set):
764 def __contains__(self, x):
765 return False
766 def __len__(self):
767 return 0
768 def __iter__(self):
769 return iter([])
770 class MyNonComparableSet(Set):
771 def __contains__(self, x):
772 return False
773 def __len__(self):
774 return 0
775 def __iter__(self):
776 return iter([])
777 def __le__(self, x):
778 return NotImplemented
779 def __lt__(self, x):
780 return NotImplemented
781
782 cs = MyComparableSet()
783 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700784 self.assertFalse(ncs < cs)
785 self.assertTrue(ncs <= cs)
786 self.assertFalse(ncs > cs)
787 self.assertTrue(ncs >= cs)
788
789 def assertSameSet(self, s1, s2):
790 # coerce both to a real set then check equality
791 self.assertSetEqual(set(s1), set(s2))
792
793 def test_Set_interoperability_with_real_sets(self):
794 # Issue: 8743
795 class ListSet(Set):
796 def __init__(self, elements=()):
797 self.data = []
798 for elem in elements:
799 if elem not in self.data:
800 self.data.append(elem)
801 def __contains__(self, elem):
802 return elem in self.data
803 def __iter__(self):
804 return iter(self.data)
805 def __len__(self):
806 return len(self.data)
807 def __repr__(self):
808 return 'Set({!r})'.format(self.data)
809
810 r1 = set('abc')
811 r2 = set('bcd')
812 r3 = set('abcde')
813 f1 = ListSet('abc')
814 f2 = ListSet('bcd')
815 f3 = ListSet('abcde')
816 l1 = list('abccba')
817 l2 = list('bcddcb')
818 l3 = list('abcdeedcba')
819
820 target = r1 & r2
821 self.assertSameSet(f1 & f2, target)
822 self.assertSameSet(f1 & r2, target)
823 self.assertSameSet(r2 & f1, target)
824 self.assertSameSet(f1 & l2, target)
825
826 target = r1 | r2
827 self.assertSameSet(f1 | f2, target)
828 self.assertSameSet(f1 | r2, target)
829 self.assertSameSet(r2 | f1, target)
830 self.assertSameSet(f1 | l2, target)
831
832 fwd_target = r1 - r2
833 rev_target = r2 - r1
834 self.assertSameSet(f1 - f2, fwd_target)
835 self.assertSameSet(f2 - f1, rev_target)
836 self.assertSameSet(f1 - r2, fwd_target)
837 self.assertSameSet(f2 - r1, rev_target)
838 self.assertSameSet(r1 - f2, fwd_target)
839 self.assertSameSet(r2 - f1, rev_target)
840 self.assertSameSet(f1 - l2, fwd_target)
841 self.assertSameSet(f2 - l1, rev_target)
842
843 target = r1 ^ r2
844 self.assertSameSet(f1 ^ f2, target)
845 self.assertSameSet(f1 ^ r2, target)
846 self.assertSameSet(r2 ^ f1, target)
847 self.assertSameSet(f1 ^ l2, target)
848
849 # Don't change the following to use assertLess or other
850 # "more specific" unittest assertions. The current
851 # assertTrue/assertFalse style makes the pattern of test
852 # case combinations clear and allows us to know for sure
853 # the exact operator being invoked.
854
855 # proper subset
856 self.assertTrue(f1 < f3)
857 self.assertFalse(f1 < f1)
858 self.assertFalse(f1 < f2)
859 self.assertTrue(r1 < f3)
860 self.assertFalse(r1 < f1)
861 self.assertFalse(r1 < f2)
862 self.assertTrue(r1 < r3)
863 self.assertFalse(r1 < r1)
864 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200865 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700866 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200867 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700868 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200869 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700870 f1 < l2
871
872 # any subset
873 self.assertTrue(f1 <= f3)
874 self.assertTrue(f1 <= f1)
875 self.assertFalse(f1 <= f2)
876 self.assertTrue(r1 <= f3)
877 self.assertTrue(r1 <= f1)
878 self.assertFalse(r1 <= f2)
879 self.assertTrue(r1 <= r3)
880 self.assertTrue(r1 <= r1)
881 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200882 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700883 f1 <= l3
884 with self.assertRaises(TypeError):
885 f1 <= l1
886 with self.assertRaises(TypeError):
887 f1 <= l2
888
889 # proper superset
890 self.assertTrue(f3 > f1)
891 self.assertFalse(f1 > f1)
892 self.assertFalse(f2 > f1)
893 self.assertTrue(r3 > r1)
894 self.assertFalse(f1 > r1)
895 self.assertFalse(f2 > r1)
896 self.assertTrue(r3 > r1)
897 self.assertFalse(r1 > r1)
898 self.assertFalse(r2 > r1)
899 with self.assertRaises(TypeError):
900 f1 > l3
901 with self.assertRaises(TypeError):
902 f1 > l1
903 with self.assertRaises(TypeError):
904 f1 > l2
905
906 # any superset
907 self.assertTrue(f3 >= f1)
908 self.assertTrue(f1 >= f1)
909 self.assertFalse(f2 >= f1)
910 self.assertTrue(r3 >= r1)
911 self.assertTrue(f1 >= r1)
912 self.assertFalse(f2 >= r1)
913 self.assertTrue(r3 >= r1)
914 self.assertTrue(r1 >= r1)
915 self.assertFalse(r2 >= r1)
916 with self.assertRaises(TypeError):
917 f1 >= l3
918 with self.assertRaises(TypeError):
919 f1 >=l1
920 with self.assertRaises(TypeError):
921 f1 >= l2
922
923 # equality
924 self.assertTrue(f1 == f1)
925 self.assertTrue(r1 == f1)
926 self.assertTrue(f1 == r1)
927 self.assertFalse(f1 == f3)
928 self.assertFalse(r1 == f3)
929 self.assertFalse(f1 == r3)
930 self.assertFalse(f1 == l3)
931 self.assertFalse(f1 == l1)
932 self.assertFalse(f1 == l2)
933
934 # inequality
935 self.assertFalse(f1 != f1)
936 self.assertFalse(r1 != f1)
937 self.assertFalse(f1 != r1)
938 self.assertTrue(f1 != f3)
939 self.assertTrue(r1 != f3)
940 self.assertTrue(f1 != r3)
941 self.assertTrue(f1 != l3)
942 self.assertTrue(f1 != l1)
943 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200944
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000945 def test_Mapping(self):
946 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000947 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000948 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000949 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
950 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000951 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000952 def __len__(self):
953 return 0
954 def __getitem__(self, i):
955 raise IndexError
956 def __iter__(self):
957 return iter(())
958 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000959
960 def test_MutableMapping(self):
961 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000962 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000963 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000964 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
965 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000966
Raymond Hettinger9117c752010-08-22 07:44:24 +0000967 def test_MutableMapping_subclass(self):
968 # Test issue 9214
969 mymap = UserDict()
970 mymap['red'] = 5
971 self.assertIsInstance(mymap.keys(), Set)
972 self.assertIsInstance(mymap.keys(), KeysView)
973 self.assertIsInstance(mymap.items(), Set)
974 self.assertIsInstance(mymap.items(), ItemsView)
975
976 mymap = UserDict()
977 mymap['red'] = 5
978 z = mymap.keys() | {'orange'}
979 self.assertIsInstance(z, set)
980 list(z)
981 mymap['blue'] = 7 # Shouldn't affect 'z'
982 self.assertEqual(sorted(z), ['orange', 'red'])
983
984 mymap = UserDict()
985 mymap['red'] = 5
986 z = mymap.items() | {('orange', 3)}
987 self.assertIsInstance(z, set)
988 list(z)
989 mymap['blue'] = 7 # Shouldn't affect 'z'
990 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
991
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000992 def test_Sequence(self):
993 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000994 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000995 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000996 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000997 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +1000998 self.assertIsInstance(memoryview(b""), Sequence)
999 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001000 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001001 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1002 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001003
Guido van Rossumd05eb002007-11-21 22:26:24 +00001004 def test_ByteString(self):
1005 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001006 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001007 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001008 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001009 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001010 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001011 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001012 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001013
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001014 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001015 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001016 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001017 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001018 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001019 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001020 self.assertTrue(issubclass(sample, MutableSequence))
1021 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001022 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1023 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001024
Eli Bendersky0716a572011-03-04 10:38:14 +00001025 def test_MutableSequence_mixins(self):
1026 # Test the mixins of MutableSequence by creating a miminal concrete
1027 # class inherited from it.
1028 class MutableSequenceSubclass(MutableSequence):
1029 def __init__(self):
1030 self.lst = []
1031
1032 def __setitem__(self, index, value):
1033 self.lst[index] = value
1034
1035 def __getitem__(self, index):
1036 return self.lst[index]
1037
1038 def __len__(self):
1039 return len(self.lst)
1040
1041 def __delitem__(self, index):
1042 del self.lst[index]
1043
1044 def insert(self, index, value):
1045 self.lst.insert(index, value)
1046
1047 mss = MutableSequenceSubclass()
1048 mss.append(0)
1049 mss.extend((1, 2, 3, 4))
1050 self.assertEqual(len(mss), 5)
1051 self.assertEqual(mss[3], 3)
1052 mss.reverse()
1053 self.assertEqual(mss[3], 1)
1054 mss.pop()
1055 self.assertEqual(len(mss), 4)
1056 mss.remove(3)
1057 self.assertEqual(len(mss), 3)
1058 mss += (10, 20, 30)
1059 self.assertEqual(len(mss), 6)
1060 self.assertEqual(mss[-1], 30)
1061 mss.clear()
1062 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001063
1064################################################################################
1065### Counter
1066################################################################################
1067
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001068class CounterSubclassWithSetItem(Counter):
1069 # Test a counter subclass that overrides __setitem__
1070 def __init__(self, *args, **kwds):
1071 self.called = False
1072 Counter.__init__(self, *args, **kwds)
1073 def __setitem__(self, key, value):
1074 self.called = True
1075 Counter.__setitem__(self, key, value)
1076
1077class CounterSubclassWithGet(Counter):
1078 # Test a counter subclass that overrides get()
1079 def __init__(self, *args, **kwds):
1080 self.called = False
1081 Counter.__init__(self, *args, **kwds)
1082 def get(self, key, default):
1083 self.called = True
1084 return Counter.get(self, key, default)
1085
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001086class TestCounter(unittest.TestCase):
1087
1088 def test_basics(self):
1089 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001090 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1091 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001092 self.assertIsInstance(c, dict)
1093 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001094 self.assertTrue(issubclass(Counter, dict))
1095 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001096 self.assertEqual(len(c), 3)
1097 self.assertEqual(sum(c.values()), 6)
1098 self.assertEqual(sorted(c.values()), [1, 2, 3])
1099 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
1100 self.assertEqual(sorted(c), ['a', 'b', 'c'])
1101 self.assertEqual(sorted(c.items()),
1102 [('a', 3), ('b', 2), ('c', 1)])
1103 self.assertEqual(c['b'], 2)
1104 self.assertEqual(c['z'], 0)
1105 self.assertEqual(c.__contains__('c'), True)
1106 self.assertEqual(c.__contains__('z'), False)
1107 self.assertEqual(c.get('b', 10), 2)
1108 self.assertEqual(c.get('z', 10), 10)
1109 self.assertEqual(c, dict(a=3, b=2, c=1))
1110 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1111 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1112 for i in range(5):
1113 self.assertEqual(c.most_common(i),
1114 [('a', 3), ('b', 2), ('c', 1)][:i])
1115 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
1116 c['a'] += 1 # increment an existing value
1117 c['b'] -= 2 # sub existing value to zero
1118 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001119 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001120 c['d'] -= 2 # sub from a missing value
1121 c['e'] = -5 # directly assign a missing value
1122 c['f'] += 4 # add to a missing value
1123 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
1124 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
1125 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001126 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001127 for i in range(3):
1128 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001129 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001130 c.clear()
1131 self.assertEqual(c, {})
1132 self.assertEqual(repr(c), 'Counter()')
1133 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1134 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001135 c.update(dict(a=5, b=3))
1136 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001137 c.update(Counter('a' * 50 + 'b' * 30))
1138 c.update() # test case with no args
1139 c.__init__('a' * 500 + 'b' * 300)
1140 c.__init__('cdc')
1141 c.__init__()
1142 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1143 self.assertEqual(c.setdefault('d', 5), 1)
1144 self.assertEqual(c['d'], 1)
1145 self.assertEqual(c.setdefault('e', 5), 5)
1146 self.assertEqual(c['e'], 5)
1147
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001148 def test_init(self):
1149 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1150 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1151 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1152 self.assertRaises(TypeError, Counter, 42)
1153 self.assertRaises(TypeError, Counter, (), ())
1154 self.assertRaises(TypeError, Counter.__init__)
1155
1156 def test_update(self):
1157 c = Counter()
1158 c.update(self=42)
1159 self.assertEqual(list(c.items()), [('self', 42)])
1160 c = Counter()
1161 c.update(iterable=42)
1162 self.assertEqual(list(c.items()), [('iterable', 42)])
1163 c = Counter()
1164 c.update(iterable=None)
1165 self.assertEqual(list(c.items()), [('iterable', None)])
1166 self.assertRaises(TypeError, Counter().update, 42)
1167 self.assertRaises(TypeError, Counter().update, {}, {})
1168 self.assertRaises(TypeError, Counter.update)
1169
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001170 def test_copying(self):
1171 # Check that counters are copyable, deepcopyable, picklable, and
1172 #have a repr/eval round-trip
1173 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02001174 def check(dup):
1175 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1176 self.assertIsNot(dup, words, msg)
1177 self.assertEqual(dup, words)
1178 check(words.copy())
1179 check(copy.copy(words))
1180 check(copy.deepcopy(words))
1181 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1182 with self.subTest(proto=proto):
1183 check(pickle.loads(pickle.dumps(words, proto)))
1184 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001185 update_test = Counter()
1186 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001187 check(update_test)
1188 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001189
Raymond Hettinger1c746c22011-04-15 13:16:46 -07001190 def test_copy_subclass(self):
1191 class MyCounter(Counter):
1192 pass
1193 c = MyCounter('slartibartfast')
1194 d = c.copy()
1195 self.assertEqual(d, c)
1196 self.assertEqual(len(d), len(c))
1197 self.assertEqual(type(d), type(c))
1198
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001199 def test_conversions(self):
1200 # Convert to: set, list, dict
1201 s = 'she sells sea shells by the sea shore'
1202 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
1203 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
1204 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
1205 self.assertEqual(set(Counter(s)), set(s))
1206
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001207 def test_invariant_for_the_in_operator(self):
1208 c = Counter(a=10, b=-2, c=0)
1209 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001210 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001211 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001212
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001213 def test_multiset_operations(self):
1214 # Verify that adding a zero counter will strip zeros and negatives
1215 c = Counter(a=10, b=-2, c=0) + Counter()
1216 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001217
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001218 elements = 'abcd'
1219 for i in range(1000):
1220 # test random pairs of multisets
1221 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001222 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001223 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001224 q.update(h=1, i=-1, j=0)
1225 for counterop, numberop in [
1226 (Counter.__add__, lambda x, y: max(0, x+y)),
1227 (Counter.__sub__, lambda x, y: max(0, x-y)),
1228 (Counter.__or__, lambda x, y: max(0,x,y)),
1229 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001230 ]:
1231 result = counterop(p, q)
1232 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001233 self.assertEqual(numberop(p[x], q[x]), result[x],
1234 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001235 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001236 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001237
1238 elements = 'abcdef'
1239 for i in range(100):
1240 # verify that random multisets with no repeats are exactly like sets
1241 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1242 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1243 for counterop, setop in [
1244 (Counter.__sub__, set.__sub__),
1245 (Counter.__or__, set.__or__),
1246 (Counter.__and__, set.__and__),
1247 ]:
1248 counter_result = counterop(p, q)
1249 set_result = setop(set(p.elements()), set(q.elements()))
1250 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001251
Raymond Hettingerbecd5682011-10-19 13:40:37 -07001252 def test_inplace_operations(self):
1253 elements = 'abcd'
1254 for i in range(1000):
1255 # test random pairs of multisets
1256 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1257 p.update(e=1, f=-1, g=0)
1258 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1259 q.update(h=1, i=-1, j=0)
1260 for inplace_op, regular_op in [
1261 (Counter.__iadd__, Counter.__add__),
1262 (Counter.__isub__, Counter.__sub__),
1263 (Counter.__ior__, Counter.__or__),
1264 (Counter.__iand__, Counter.__and__),
1265 ]:
1266 c = p.copy()
1267 c_id = id(c)
1268 regular_result = regular_op(c, q)
1269 inplace_result = inplace_op(c, q)
1270 self.assertEqual(inplace_result, regular_result)
1271 self.assertEqual(id(inplace_result), c_id)
1272
Raymond Hettinger9c01e442010-04-03 10:32:58 +00001273 def test_subtract(self):
1274 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1275 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
1276 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1277 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1278 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
1279 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1280 c = Counter('aaabbcd')
1281 c.subtract('aaaabbcce')
1282 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001283
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001284 c = Counter()
1285 c.subtract(self=42)
1286 self.assertEqual(list(c.items()), [('self', -42)])
1287 c = Counter()
1288 c.subtract(iterable=42)
1289 self.assertEqual(list(c.items()), [('iterable', -42)])
1290 self.assertRaises(TypeError, Counter().subtract, 42)
1291 self.assertRaises(TypeError, Counter().subtract, {}, {})
1292 self.assertRaises(TypeError, Counter.subtract)
1293
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07001294 def test_unary(self):
1295 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1296 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
1297 self.assertEqual(dict(-c), dict(a=5))
1298
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07001299 def test_repr_nonsortable(self):
1300 c = Counter(a=2, b=None)
1301 r = repr(c)
1302 self.assertIn("'a': 2", r)
1303 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07001304
Raymond Hettinger426e0522011-01-03 02:12:02 +00001305 def test_helper_function(self):
1306 # two paths, one for real dicts and one for other mappings
1307 elems = list('abracadabra')
1308
1309 d = dict()
1310 _count_elements(d, elems)
1311 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1312
1313 m = OrderedDict()
1314 _count_elements(m, elems)
1315 self.assertEqual(m,
1316 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
1317
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001318 # test fidelity to the pure python version
1319 c = CounterSubclassWithSetItem('abracadabra')
1320 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001321 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001322 c = CounterSubclassWithGet('abracadabra')
1323 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001324 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001325
Raymond Hettinger499e1932011-02-23 07:56:53 +00001326
1327################################################################################
1328### OrderedDict
1329################################################################################
1330
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001331class TestOrderedDict(unittest.TestCase):
1332
1333 def test_init(self):
1334 with self.assertRaises(TypeError):
1335 OrderedDict([('a', 1), ('b', 2)], None) # too many args
1336 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1337 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
1338 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
1339 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
1340 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
1341 c=3, e=5).items()), pairs) # mixed input
1342
1343 # make sure no positional args conflict with possible kwdargs
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001344 self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
1345 self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
1346 self.assertRaises(TypeError, OrderedDict, 42)
1347 self.assertRaises(TypeError, OrderedDict, (), ())
1348 self.assertRaises(TypeError, OrderedDict.__init__)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001349
1350 # Make sure that direct calls to __init__ do not clear previous contents
1351 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1352 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
1353 self.assertEqual(list(d.items()),
1354 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1355
1356 def test_update(self):
1357 with self.assertRaises(TypeError):
1358 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
1359 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1360 od = OrderedDict()
1361 od.update(dict(pairs))
1362 self.assertEqual(sorted(od.items()), pairs) # dict input
1363 od = OrderedDict()
1364 od.update(**dict(pairs))
1365 self.assertEqual(sorted(od.items()), pairs) # kwds input
1366 od = OrderedDict()
1367 od.update(pairs)
1368 self.assertEqual(list(od.items()), pairs) # pairs input
1369 od = OrderedDict()
1370 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1371 self.assertEqual(list(od.items()), pairs) # mixed input
1372
Mark Dickinsonb214e902010-07-11 18:53:06 +00001373 # Issue 9137: Named argument called 'other' or 'self'
1374 # shouldn't be treated specially.
1375 od = OrderedDict()
1376 od.update(self=23)
1377 self.assertEqual(list(od.items()), [('self', 23)])
1378 od = OrderedDict()
1379 od.update(other={})
1380 self.assertEqual(list(od.items()), [('other', {})])
1381 od = OrderedDict()
1382 od.update(red=5, blue=6, other=7, self=8)
1383 self.assertEqual(sorted(list(od.items())),
1384 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
1385
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001386 # Make sure that direct calls to update do not clear previous contents
1387 # add that updates items are not moved to the end
1388 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1389 d.update([('e', 5), ('f', 6)], g=7, d=4)
1390 self.assertEqual(list(d.items()),
1391 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1392
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001393 self.assertRaises(TypeError, OrderedDict().update, 42)
1394 self.assertRaises(TypeError, OrderedDict().update, (), ())
1395 self.assertRaises(TypeError, OrderedDict.update)
1396
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001397 def test_abc(self):
1398 self.assertIsInstance(OrderedDict(), MutableMapping)
1399 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1400
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001401 def test_clear(self):
1402 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1403 shuffle(pairs)
1404 od = OrderedDict(pairs)
1405 self.assertEqual(len(od), len(pairs))
1406 od.clear()
1407 self.assertEqual(len(od), 0)
1408
1409 def test_delitem(self):
1410 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1411 od = OrderedDict(pairs)
1412 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001413 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001414 with self.assertRaises(KeyError):
1415 del od['a']
1416 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1417
1418 def test_setitem(self):
1419 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1420 od['c'] = 10 # existing element
1421 od['f'] = 20 # new element
1422 self.assertEqual(list(od.items()),
1423 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1424
1425 def test_iterators(self):
1426 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1427 shuffle(pairs)
1428 od = OrderedDict(pairs)
1429 self.assertEqual(list(od), [t[0] for t in pairs])
1430 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1431 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1432 self.assertEqual(list(od.items()), pairs)
1433 self.assertEqual(list(reversed(od)),
1434 [t[0] for t in reversed(pairs)])
Serhiy Storchaka578c9212014-04-04 15:19:36 +03001435 self.assertEqual(list(reversed(od.keys())),
1436 [t[0] for t in reversed(pairs)])
1437 self.assertEqual(list(reversed(od.values())),
1438 [t[1] for t in reversed(pairs)])
1439 self.assertEqual(list(reversed(od.items())), list(reversed(pairs)))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001440
Raymond Hettinger53d2c412014-05-03 21:58:45 -07001441 def test_detect_deletion_during_iteration(self):
1442 od = OrderedDict.fromkeys('abc')
1443 it = iter(od)
1444 key = next(it)
1445 del od[key]
1446 with self.assertRaises(Exception):
1447 # Note, the exact exception raised is not guaranteed
1448 # The only guarantee that the next() will not succeed
1449 next(it)
1450
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001451 def test_popitem(self):
1452 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1453 shuffle(pairs)
1454 od = OrderedDict(pairs)
1455 while pairs:
1456 self.assertEqual(od.popitem(), pairs.pop())
1457 with self.assertRaises(KeyError):
1458 od.popitem()
1459 self.assertEqual(len(od), 0)
1460
1461 def test_pop(self):
1462 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1463 shuffle(pairs)
1464 od = OrderedDict(pairs)
1465 shuffle(pairs)
1466 while pairs:
1467 k, v = pairs.pop()
1468 self.assertEqual(od.pop(k), v)
1469 with self.assertRaises(KeyError):
1470 od.pop('xyz')
1471 self.assertEqual(len(od), 0)
1472 self.assertEqual(od.pop(k, 12345), 12345)
1473
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001474 # make sure pop still works when __missing__ is defined
1475 class Missing(OrderedDict):
1476 def __missing__(self, key):
1477 return 0
1478 m = Missing(a=1)
1479 self.assertEqual(m.pop('b', 5), 5)
1480 self.assertEqual(m.pop('a', 6), 1)
1481 self.assertEqual(m.pop('a', 6), 6)
1482 with self.assertRaises(KeyError):
1483 m.pop('a')
1484
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001485 def test_equality(self):
1486 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1487 shuffle(pairs)
1488 od1 = OrderedDict(pairs)
1489 od2 = OrderedDict(pairs)
1490 self.assertEqual(od1, od2) # same order implies equality
1491 pairs = pairs[2:] + pairs[:2]
1492 od2 = OrderedDict(pairs)
1493 self.assertNotEqual(od1, od2) # different order implies inequality
1494 # comparison to regular dict is not order sensitive
1495 self.assertEqual(od1, dict(od2))
1496 self.assertEqual(dict(od2), od1)
1497 # different length implied inequality
1498 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1499
1500 def test_copying(self):
1501 # Check that ordered dicts are copyable, deepcopyable, picklable,
1502 # and have a repr/eval round-trip
1503 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1504 od = OrderedDict(pairs)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001505 def check(dup):
1506 msg = "\ncopy: %s\nod: %s" % (dup, od)
1507 self.assertIsNot(dup, od, msg)
1508 self.assertEqual(dup, od)
1509 check(od.copy())
1510 check(copy.copy(od))
1511 check(copy.deepcopy(od))
1512 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1513 with self.subTest(proto=proto):
1514 check(pickle.loads(pickle.dumps(od, proto)))
1515 check(eval(repr(od)))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001516 update_test = OrderedDict()
1517 update_test.update(od)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001518 check(update_test)
1519 check(OrderedDict(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001520
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001521 def test_yaml_linkage(self):
1522 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1523 # In yaml, lists are native but tuples are not.
1524 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1525 od = OrderedDict(pairs)
1526 # yaml.dump(od) -->
1527 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001528 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001529
Raymond Hettingerb2121572009-03-03 22:50:04 +00001530 def test_reduce_not_too_fat(self):
1531 # do not save instance dictionary if not needed
1532 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1533 od = OrderedDict(pairs)
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001534 self.assertIsNone(od.__reduce__()[2])
Raymond Hettingerb2121572009-03-03 22:50:04 +00001535 od.x = 10
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001536 self.assertIsNotNone(od.__reduce__()[2])
1537
1538 def test_pickle_recursive(self):
1539 od = OrderedDict()
1540 od[1] = od
1541 for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
1542 dup = pickle.loads(pickle.dumps(od, proto))
1543 self.assertIsNot(dup, od)
1544 self.assertEqual(list(dup.keys()), [1])
1545 self.assertIs(dup[1], dup)
Raymond Hettingerb2121572009-03-03 22:50:04 +00001546
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001547 def test_repr(self):
1548 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1549 self.assertEqual(repr(od),
1550 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1551 self.assertEqual(eval(repr(od)), od)
1552 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1553
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001554 def test_repr_recursive(self):
1555 # See issue #9826
1556 od = OrderedDict.fromkeys('abc')
1557 od['x'] = od
1558 self.assertEqual(repr(od),
1559 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1560
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001561 def test_setdefault(self):
1562 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1563 shuffle(pairs)
1564 od = OrderedDict(pairs)
1565 pair_order = list(od.items())
1566 self.assertEqual(od.setdefault('a', 10), 3)
1567 # make sure order didn't change
1568 self.assertEqual(list(od.items()), pair_order)
1569 self.assertEqual(od.setdefault('x', 10), 10)
1570 # make sure 'x' is added to the end
1571 self.assertEqual(list(od.items())[-1], ('x', 10))
1572
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001573 # make sure setdefault still works when __missing__ is defined
1574 class Missing(OrderedDict):
1575 def __missing__(self, key):
1576 return 0
1577 self.assertEqual(Missing().setdefault(5, 9), 9)
1578
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001579 def test_reinsert(self):
1580 # Given insert a, insert b, delete a, re-insert a,
1581 # verify that a is now later than b.
1582 od = OrderedDict()
1583 od['a'] = 1
1584 od['b'] = 2
1585 del od['a']
1586 od['a'] = 1
1587 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1588
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001589 def test_move_to_end(self):
1590 od = OrderedDict.fromkeys('abcde')
1591 self.assertEqual(list(od), list('abcde'))
1592 od.move_to_end('c')
1593 self.assertEqual(list(od), list('abdec'))
1594 od.move_to_end('c', 0)
1595 self.assertEqual(list(od), list('cabde'))
1596 od.move_to_end('c', 0)
1597 self.assertEqual(list(od), list('cabde'))
1598 od.move_to_end('e')
1599 self.assertEqual(list(od), list('cabde'))
1600 with self.assertRaises(KeyError):
1601 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001602
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001603 def test_sizeof(self):
1604 # Wimpy test: Just verify the reported size is larger than a regular dict
1605 d = dict(a=1)
1606 od = OrderedDict(**d)
1607 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1608
Raymond Hettinger32062e92011-01-01 22:38:00 +00001609 def test_override_update(self):
1610 # Verify that subclasses can override update() without breaking __init__()
1611 class MyOD(OrderedDict):
1612 def update(self, *args, **kwds):
1613 raise Exception()
1614 items = [('a', 1), ('c', 3), ('b', 2)]
1615 self.assertEqual(list(MyOD(items).items()), items)
1616
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001617class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1618 type2test = OrderedDict
1619
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001620 def test_popitem(self):
1621 d = self._empty_mapping()
1622 self.assertRaises(KeyError, d.popitem)
1623
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001624class MyOrderedDict(OrderedDict):
1625 pass
1626
1627class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1628 type2test = MyOrderedDict
1629
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001630 def test_popitem(self):
1631 d = self._empty_mapping()
1632 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001633
1634
Raymond Hettinger499e1932011-02-23 07:56:53 +00001635################################################################################
1636### Run tests
1637################################################################################
1638
Christian Heimes25bb7832008-01-11 16:17:00 +00001639import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001640
Guido van Rossumd8faa362007-04-27 19:54:29 +00001641def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001642 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001643 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001644 TestCollectionABCs, TestCounter, TestChainMap,
Serhiy Storchakaa86700a2014-11-27 17:45:44 +02001645 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001646 support.run_unittest(*test_classes)
1647 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001648
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001649
Guido van Rossumd8faa362007-04-27 19:54:29 +00001650if __name__ == "__main__":
1651 test_main(verbose=True)