blob: db44d661897ebaf886231fcee02a68ddab237a6c [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00003import unittest, doctest, operator
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -07004from test.support import TESTFN, forget, unlink
Raymond Hettinger2d32f632009-03-02 21:24:57 +00005import inspect
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Raymond Hettinger426e0522011-01-03 02:12:02 +00007from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger2d32f632009-03-02 21:24:57 +00008from test import mapping_tests
Georg Brandlc28e1fa2008-06-10 19:20:26 +00009import pickle, copy
Raymond Hettinger2d32f632009-03-02 21:24:57 +000010from random import randrange, shuffle
Raymond Hettinger499b2ee2009-05-27 01:53:46 +000011import keyword
12import re
R. David Murray378c0cf2010-02-24 01:46:21 +000013import sys
Raymond Hettinger57d1a882011-02-23 00:46:28 +000014from collections import UserDict
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000015from collections import ChainMap
Raymond Hettinger57d1a882011-02-23 00:46:28 +000016from collections.abc import Hashable, Iterable, Iterator
17from collections.abc import Sized, Container, Callable
18from collections.abc import Set, MutableSet
19from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
20from collections.abc import Sequence, MutableSequence
21from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000022
Raymond Hettinger499e1932011-02-23 07:56:53 +000023
24################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000025### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000026################################################################################
27
28class TestChainMap(unittest.TestCase):
29
30 def test_basics(self):
31 c = ChainMap()
32 c['a'] = 1
33 c['b'] = 2
34 d = c.new_child()
35 d['b'] = 20
36 d['c'] = 30
37 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
38 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
39 self.assertEqual(len(d), 3) # check len
40 for key in 'abc': # check contains
41 self.assertIn(key, d)
42 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
43 self.assertEqual(d.get(k, 100), v)
44
45 del d['b'] # unmask a value
46 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
47 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
48 self.assertEqual(len(d), 3) # check len
49 for key in 'abc': # check contains
50 self.assertIn(key, d)
51 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
52 self.assertEqual(d.get(k, 100), v)
53 self.assertIn(repr(d), [ # check repr
54 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
55 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
56 ])
57
58 for e in d.copy(), copy.copy(d): # check shallow copies
59 self.assertEqual(d, e)
60 self.assertEqual(d.maps, e.maps)
61 self.assertIsNot(d, e)
62 self.assertIsNot(d.maps[0], e.maps[0])
63 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
64 self.assertIs(m1, m2)
65
66 for e in [pickle.loads(pickle.dumps(d)),
67 copy.deepcopy(d),
68 eval(repr(d))
69 ]: # check deep copies
70 self.assertEqual(d, e)
71 self.assertEqual(d.maps, e.maps)
72 self.assertIsNot(d, e)
73 for m1, m2 in zip(d.maps, e.maps):
74 self.assertIsNot(m1, m2, e)
75
Raymond Hettingerd0321312011-02-26 06:53:58 +000076 f = d.new_child()
77 f['b'] = 5
78 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
79 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
80 self.assertEqual(f['b'], 5) # find first in chain
81 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +000082
83 def test_contructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +000084 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +000085 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
86
Raymond Hettingerd0321312011-02-26 06:53:58 +000087 def test_bool(self):
88 self.assertFalse(ChainMap())
89 self.assertFalse(ChainMap({}, {}))
90 self.assertTrue(ChainMap({1:2}, {}))
91 self.assertTrue(ChainMap({}, {1:2}))
92
Raymond Hettinger499e1932011-02-23 07:56:53 +000093 def test_missing(self):
94 class DefaultChainMap(ChainMap):
95 def __missing__(self, key):
96 return 999
97 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
98 for k, v in dict(a=1, b=2, c=30, d=999).items():
99 self.assertEqual(d[k], v) # check __getitem__ w/missing
100 for k, v in dict(a=1, b=2, c=30, d=77).items():
101 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
102 for k, v in dict(a=True, b=True, c=True, d=False).items():
103 self.assertEqual(k in d, v) # check __contains__ w/missing
104 self.assertEqual(d.pop('a', 1001), 1, d)
105 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
106 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
107 with self.assertRaises(KeyError):
108 d.popitem()
109
110 def test_dict_coercion(self):
111 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
112 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
113 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
114
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000115 def test_new_child(self):
116 'Tests for changes for issue #16613.'
117 c = ChainMap()
118 c['a'] = 1
119 c['b'] = 2
120 m = {'b':20, 'c': 30}
121 d = c.new_child(m)
122 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
123 self.assertIs(m, d.maps[0])
124
125 # Use a different map than a dict
126 class lowerdict(dict):
127 def __getitem__(self, key):
128 if isinstance(key, str):
129 key = key.lower()
130 return dict.__getitem__(self, key)
131 def __contains__(self, key):
132 if isinstance(key, str):
133 key = key.lower()
134 return dict.__contains__(self, key)
135
136 c = ChainMap()
137 c['a'] = 1
138 c['b'] = 2
139 m = lowerdict(b=20, c=30)
140 d = c.new_child(m)
141 self.assertIs(m, d.maps[0])
142 for key in 'abc': # check contains
143 self.assertIn(key, d)
144 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
145 self.assertEqual(d.get(k, 100), v)
146
Raymond Hettinger499e1932011-02-23 07:56:53 +0000147
148################################################################################
149### Named Tuples
150################################################################################
151
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000152TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000153
154class TestNamedTuple(unittest.TestCase):
155
156 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000157 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000158 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000159 self.assertEqual(Point.__slots__, ())
160 self.assertEqual(Point.__module__, __name__)
161 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000162 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettinger2ebea412011-03-23 12:52:23 -0700163 self.assertIn('class Point(tuple)', Point._source)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000164
165 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
166 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
167 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
168
169 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
170 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
171 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000172 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000173 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
174
175 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000176 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000177
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000178 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000179 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000180 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000181 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000182
Christian Heimesfaf2f632008-01-06 16:59:19 +0000183 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
184 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
185
R. David Murray378c0cf2010-02-24 01:46:21 +0000186 @unittest.skipIf(sys.flags.optimize >= 2,
187 "Docstrings are omitted with -O2 and above")
188 def test_factory_doc_attr(self):
189 Point = namedtuple('Point', 'x y')
190 self.assertEqual(Point.__doc__, 'Point(x, y)')
191
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000192 def test_name_fixer(self):
193 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000194 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
195 [('abc', 'class'), ('abc', '_1')], # field has keyword
196 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
197 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
198 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
199 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000200 ]:
201 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
202
Guido van Rossumd8faa362007-04-27 19:54:29 +0000203 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000204 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000205 p = Point(11, 22)
206 self.assertEqual(p, Point(x=11, y=22))
207 self.assertEqual(p, Point(11, y=22))
208 self.assertEqual(p, Point(y=22, x=11))
209 self.assertEqual(p, Point(*(11, 22)))
210 self.assertEqual(p, Point(**dict(x=11, y=22)))
211 self.assertRaises(TypeError, Point, 1) # too few args
212 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
213 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
214 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
215 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000216 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000217 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000218 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
219 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
Raymond Hettinger163e9822013-05-18 00:05:20 -0700220 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
221 self.assertEqual(vars(p), p._asdict()) # verify that vars() works
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000222
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000223 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000224 p._replace(x=1, error=2)
225 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000226 pass
227 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000228 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000229
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000230 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000231 Point = namedtuple('Point', 'x, y')
232 p = Point(x=11, y=22)
233 self.assertEqual(repr(p), 'Point(x=11, y=22)')
234
235 # verify that fieldspec can be a non-string sequence
236 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000237 p = Point(x=11, y=22)
238 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000239
240 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000241 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000242 p = Point(11, 22)
243
Ezio Melottie9615932010-01-24 19:26:24 +0000244 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000245 self.assertEqual(p, (11, 22)) # matches a real tuple
246 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
247 self.assertEqual(list(p), [11, 22]) # coercable to a list
248 self.assertEqual(max(p), 22) # iterable
249 self.assertEqual(max(*p), 22) # star-able
250 x, y = p
251 self.assertEqual(p, (x, y)) # unpacks like a tuple
252 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
253 self.assertRaises(IndexError, p.__getitem__, 3)
254
255 self.assertEqual(p.x, x)
256 self.assertEqual(p.y, y)
257 self.assertRaises(AttributeError, eval, 'p.z', locals())
258
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000259 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000260 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000261 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000262 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000263 self.assertEqual(repr(Zero()), 'Zero()')
264 self.assertEqual(Zero()._asdict(), {})
265 self.assertEqual(Zero()._fields, ())
266
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000267 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000268 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000269 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000270 self.assertEqual(Dot(1).d, 1)
271 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
272 self.assertEqual(Dot(1)._asdict(), {'d':1})
273 self.assertEqual(Dot(1)._replace(d=999), (999,))
274 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000275
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000276 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000277 n = 254 # SyntaxError: more than 255 arguments:
278 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000279 names = list(set(''.join([random.choice(string.ascii_letters)
280 for j in range(10)]) for i in range(n)))
281 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000282 Big = namedtuple('Big', names)
283 b = Big(*range(n))
284 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000285 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000286 for pos, name in enumerate(names):
287 self.assertEqual(getattr(b, name), pos)
288 repr(b) # make sure repr() doesn't blow-up
289 d = b._asdict()
290 d_expected = dict(zip(names, range(n)))
291 self.assertEqual(d, d_expected)
292 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
293 b2_expected = list(range(n))
294 b2_expected[1] = 999
295 b2_expected[-5] = 42
296 self.assertEqual(b2, tuple(b2_expected))
297 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000298
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000299 def test_pickle(self):
300 p = TestNT(x=10, y=20, z=30)
301 for module in (pickle,):
302 loads = getattr(module, 'loads')
303 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500304 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000305 q = loads(dumps(p, protocol))
306 self.assertEqual(p, q)
307 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700308 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000309
310 def test_copy(self):
311 p = TestNT(x=10, y=20, z=30)
312 for copier in copy.copy, copy.deepcopy:
313 q = copier(p)
314 self.assertEqual(p, q)
315 self.assertEqual(p._fields, q._fields)
316
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000317 def test_name_conflicts(self):
318 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
319 # failed when used as field names. Test to make sure these now work.
320 T = namedtuple('T', 'itemgetter property self cls tuple')
321 t = T(1, 2, 3, 4, 5)
322 self.assertEqual(t, (1,2,3,4,5))
323 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
324 self.assertEqual(newt, (10,20,30,40,50))
325
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000326 # Broader test of all interesting names in a template
327 with support.captured_stdout() as template:
328 T = namedtuple('T', 'x', verbose=True)
329 words = set(re.findall('[A-Za-z]+', template.getvalue()))
330 words -= set(keyword.kwlist)
331 T = namedtuple('T', words)
332 # test __new__
333 values = tuple(range(len(words)))
334 t = T(*values)
335 self.assertEqual(t, values)
336 t = T(**dict(zip(T._fields, values)))
337 self.assertEqual(t, values)
338 # test _make
339 t = T._make(values)
340 self.assertEqual(t, values)
341 # exercise __repr__
342 repr(t)
343 # test _asdict
344 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
345 # test _replace
346 t = T._make(values)
347 newvalues = tuple(v*10 for v in values)
348 newt = t._replace(**dict(zip(T._fields, newvalues)))
349 self.assertEqual(newt, newvalues)
350 # test _fields
351 self.assertEqual(T._fields, tuple(words))
352 # test __getnewargs__
353 self.assertEqual(t.__getnewargs__(), values)
354
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000355 def test_repr(self):
356 with support.captured_stdout() as template:
357 A = namedtuple('A', 'x', verbose=True)
358 self.assertEqual(repr(A(1)), 'A(x=1)')
359 # repr should show the name of the subclass
360 class B(A):
361 pass
362 self.assertEqual(repr(B(1)), 'B(x=1)')
363
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700364 def test_source(self):
365 # verify that _source can be run through exec()
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700366 tmp = namedtuple('NTColor', 'red green blue')
367 globals().pop('NTColor', None) # remove artifacts from other tests
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700368 exec(tmp._source, globals())
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700369 self.assertIn('NTColor', globals())
370 c = NTColor(10, 20, 30)
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700371 self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700372 self.assertEqual(NTColor._fields, ('red', 'green', 'blue'))
373 globals().pop('NTColor', None) # clean-up after this test
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700374
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000375
Raymond Hettinger499e1932011-02-23 07:56:53 +0000376################################################################################
377### Abstract Base Classes
378################################################################################
379
Raymond Hettingerae650182009-01-28 23:33:59 +0000380class ABCTestCase(unittest.TestCase):
381
382 def validate_abstract_methods(self, abc, *names):
383 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
384
385 # everything should work will all required methods are present
386 C = type('C', (abc,), methodstubs)
387 C()
388
389 # instantiation should fail if a required method is missing
390 for name in names:
391 stubs = methodstubs.copy()
392 del stubs[name]
393 C = type('C', (abc,), stubs)
394 self.assertRaises(TypeError, C, name)
395
Florent Xiclunace153f62010-03-08 15:34:35 +0000396 def validate_isinstance(self, abc, name):
397 stub = lambda s, *args: 0
398
399 C = type('C', (object,), {'__hash__': None})
400 setattr(C, name, stub)
401 self.assertIsInstance(C(), abc)
402 self.assertTrue(issubclass(C, abc))
403
404 C = type('C', (object,), {'__hash__': None})
405 self.assertNotIsInstance(C(), abc)
406 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000407
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000408 def validate_comparison(self, instance):
409 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
410 operators = {}
411 for op in ops:
412 name = '__' + op + '__'
413 operators[name] = getattr(operator, name)
414
415 class Other:
416 def __init__(self):
417 self.right_side = False
418 def __eq__(self, other):
419 self.right_side = True
420 return True
421 __lt__ = __eq__
422 __gt__ = __eq__
423 __le__ = __eq__
424 __ge__ = __eq__
425 __ne__ = __eq__
426 __ror__ = __eq__
427 __rand__ = __eq__
428 __rxor__ = __eq__
429 __rsub__ = __eq__
430
431 for name, op in operators.items():
432 if not hasattr(instance, name):
433 continue
434 other = Other()
435 op(instance, other)
436 self.assertTrue(other.right_side,'Right side not called for %s.%s'
437 % (type(instance), name))
438
Raymond Hettingerae650182009-01-28 23:33:59 +0000439class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000440
441 def test_Hashable(self):
442 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000443 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000444 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000445 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000446 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000447 # Check some hashables
448 samples = [None,
449 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000450 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000451 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000452 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000453 ]
454 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000455 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000456 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000457 self.assertRaises(TypeError, Hashable)
458 # Check direct subclassing
459 class H(Hashable):
460 def __hash__(self):
461 return super().__hash__()
462 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000463 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000464 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000465 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000466
467 def test_Iterable(self):
468 # Check some non-iterables
469 non_samples = [None, 42, 3.14, 1j]
470 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000471 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000472 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000473 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000474 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000475 tuple(), list(), set(), frozenset(), dict(),
476 dict().keys(), dict().items(), dict().values(),
477 (lambda: (yield))(),
478 (x for x in []),
479 ]
480 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000481 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000482 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000483 # Check direct subclassing
484 class I(Iterable):
485 def __iter__(self):
486 return super().__iter__()
487 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000488 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000489 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000490 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000491
492 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000493 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000494 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000495 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000496 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000497 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000498 iter(tuple()), iter(list()), iter(dict()),
499 iter(set()), iter(frozenset()),
500 iter(dict().keys()), iter(dict().items()),
501 iter(dict().values()),
502 (lambda: (yield))(),
503 (x for x in []),
504 ]
505 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000506 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000507 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000508 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
509
510 # Issue 10565
511 class NextOnly:
512 def __next__(self):
513 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -0800514 return
Raymond Hettingeread22222010-11-29 03:56:12 +0000515 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000516
517 def test_Sized(self):
518 non_samples = [None, 42, 3.14, 1j,
519 (lambda: (yield))(),
520 (x for x in []),
521 ]
522 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000523 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000524 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000525 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000526 tuple(), list(), set(), frozenset(), dict(),
527 dict().keys(), dict().items(), dict().values(),
528 ]
529 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000530 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000531 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000532 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000533 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000534
535 def test_Container(self):
536 non_samples = [None, 42, 3.14, 1j,
537 (lambda: (yield))(),
538 (x for x in []),
539 ]
540 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000541 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000542 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000543 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000544 tuple(), list(), set(), frozenset(), dict(),
545 dict().keys(), dict().items(),
546 ]
547 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000548 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000549 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000550 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000551 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000552
553 def test_Callable(self):
554 non_samples = [None, 42, 3.14, 1j,
555 "", b"", (), [], {}, set(),
556 (lambda: (yield))(),
557 (x for x in []),
558 ]
559 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000560 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000561 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000562 samples = [lambda: None,
563 type, int, object,
564 len,
565 list.append, [].append,
566 ]
567 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000568 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000569 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000570 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000571 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000572
573 def test_direct_subclassing(self):
574 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
575 class C(B):
576 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000577 self.assertTrue(issubclass(C, B))
578 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000579
580 def test_registration(self):
581 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
582 class C:
583 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000584 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000585 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000586 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000587
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000588class WithSet(MutableSet):
589
590 def __init__(self, it=()):
591 self.data = set(it)
592
593 def __len__(self):
594 return len(self.data)
595
596 def __iter__(self):
597 return iter(self.data)
598
599 def __contains__(self, item):
600 return item in self.data
601
602 def add(self, item):
603 self.data.add(item)
604
605 def discard(self, item):
606 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000607
Raymond Hettingerae650182009-01-28 23:33:59 +0000608class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000609
610 # XXX For now, we only test some virtual inheritance properties.
611 # We should also test the proper behavior of the collection ABCs
612 # as real base classes or mix-in classes.
613
614 def test_Set(self):
615 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000616 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000617 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000618 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000619 class MySet(Set):
620 def __contains__(self, x):
621 return False
622 def __len__(self):
623 return 0
624 def __iter__(self):
625 return iter([])
626 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000627
Benjamin Peterson41181742008-07-02 20:22:54 +0000628 def test_hash_Set(self):
629 class OneTwoThreeSet(Set):
630 def __init__(self):
631 self.contents = [1, 2, 3]
632 def __contains__(self, x):
633 return x in self.contents
634 def __len__(self):
635 return len(self.contents)
636 def __iter__(self):
637 return iter(self.contents)
638 def __hash__(self):
639 return self._hash()
640 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000641 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000642
Raymond Hettinger2d452ee2014-05-25 18:28:39 -0700643 def test_isdisjoint_Set(self):
644 class MySet(Set):
645 def __init__(self, itr):
646 self.contents = itr
647 def __contains__(self, x):
648 return x in self.contents
649 def __iter__(self):
650 return iter(self.contents)
651 def __len__(self):
652 return len([x for x in self.contents])
653 s1 = MySet((1, 2, 3))
654 s2 = MySet((4, 5, 6))
655 s3 = MySet((1, 5, 6))
656 self.assertTrue(s1.isdisjoint(s2))
657 self.assertFalse(s1.isdisjoint(s3))
658
659 def test_equality_Set(self):
660 class MySet(Set):
661 def __init__(self, itr):
662 self.contents = itr
663 def __contains__(self, x):
664 return x in self.contents
665 def __iter__(self):
666 return iter(self.contents)
667 def __len__(self):
668 return len([x for x in self.contents])
669 s1 = MySet((1,))
670 s2 = MySet((1, 2))
671 s3 = MySet((3, 4))
672 s4 = MySet((3, 4))
673 self.assertTrue(s2 > s1)
674 self.assertTrue(s1 < s2)
675 self.assertFalse(s2 <= s1)
676 self.assertFalse(s2 <= s3)
677 self.assertFalse(s1 >= s2)
678 self.assertEqual(s3, s4)
679 self.assertNotEqual(s2, s3)
680
681 def test_arithmetic_Set(self):
682 class MySet(Set):
683 def __init__(self, itr):
684 self.contents = itr
685 def __contains__(self, x):
686 return x in self.contents
687 def __iter__(self):
688 return iter(self.contents)
689 def __len__(self):
690 return len([x for x in self.contents])
691 s1 = MySet((1, 2, 3))
692 s2 = MySet((3, 4, 5))
693 s3 = s1 & s2
694 self.assertEqual(s3, MySet((3,)))
695
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000696 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000697 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000698 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000699 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000700 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000701 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
702 'add', 'discard')
703
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000704 def test_issue_5647(self):
705 # MutableSet.__iand__ mutated the set during iteration
706 s = WithSet('abcd')
707 s &= WithSet('cdef') # This used to fail
708 self.assertEqual(set(s), set('cd'))
709
Raymond Hettingerae650182009-01-28 23:33:59 +0000710 def test_issue_4920(self):
711 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000712 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000713 __slots__=['__s']
714 def __init__(self,items=None):
715 if items is None:
716 items=[]
717 self.__s=set(items)
718 def __contains__(self,v):
719 return v in self.__s
720 def __iter__(self):
721 return iter(self.__s)
722 def __len__(self):
723 return len(self.__s)
724 def add(self,v):
725 result=v not in self.__s
726 self.__s.add(v)
727 return result
728 def discard(self,v):
729 result=v in self.__s
730 self.__s.discard(v)
731 return result
732 def __repr__(self):
733 return "MySet(%s)" % repr(list(self))
734 s = MySet([5,43,2,1])
735 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000736
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000737 def test_issue8750(self):
738 empty = WithSet()
739 full = WithSet(range(10))
740 s = WithSet(full)
741 s -= s
742 self.assertEqual(s, empty)
743 s = WithSet(full)
744 s ^= s
745 self.assertEqual(s, empty)
746 s = WithSet(full)
747 s &= s
748 self.assertEqual(s, full)
749 s |= s
750 self.assertEqual(s, full)
751
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200752 def test_issue16373(self):
753 # Recursion error comparing comparable and noncomparable
754 # Set instances
755 class MyComparableSet(Set):
756 def __contains__(self, x):
757 return False
758 def __len__(self):
759 return 0
760 def __iter__(self):
761 return iter([])
762 class MyNonComparableSet(Set):
763 def __contains__(self, x):
764 return False
765 def __len__(self):
766 return 0
767 def __iter__(self):
768 return iter([])
769 def __le__(self, x):
770 return NotImplemented
771 def __lt__(self, x):
772 return NotImplemented
773
774 cs = MyComparableSet()
775 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700776 self.assertFalse(ncs < cs)
777 self.assertTrue(ncs <= cs)
778 self.assertFalse(ncs > cs)
779 self.assertTrue(ncs >= cs)
780
781 def assertSameSet(self, s1, s2):
782 # coerce both to a real set then check equality
783 self.assertSetEqual(set(s1), set(s2))
784
785 def test_Set_interoperability_with_real_sets(self):
786 # Issue: 8743
787 class ListSet(Set):
788 def __init__(self, elements=()):
789 self.data = []
790 for elem in elements:
791 if elem not in self.data:
792 self.data.append(elem)
793 def __contains__(self, elem):
794 return elem in self.data
795 def __iter__(self):
796 return iter(self.data)
797 def __len__(self):
798 return len(self.data)
799 def __repr__(self):
800 return 'Set({!r})'.format(self.data)
801
802 r1 = set('abc')
803 r2 = set('bcd')
804 r3 = set('abcde')
805 f1 = ListSet('abc')
806 f2 = ListSet('bcd')
807 f3 = ListSet('abcde')
808 l1 = list('abccba')
809 l2 = list('bcddcb')
810 l3 = list('abcdeedcba')
811
812 target = r1 & r2
813 self.assertSameSet(f1 & f2, target)
814 self.assertSameSet(f1 & r2, target)
815 self.assertSameSet(r2 & f1, target)
816 self.assertSameSet(f1 & l2, target)
817
818 target = r1 | r2
819 self.assertSameSet(f1 | f2, target)
820 self.assertSameSet(f1 | r2, target)
821 self.assertSameSet(r2 | f1, target)
822 self.assertSameSet(f1 | l2, target)
823
824 fwd_target = r1 - r2
825 rev_target = r2 - r1
826 self.assertSameSet(f1 - f2, fwd_target)
827 self.assertSameSet(f2 - f1, rev_target)
828 self.assertSameSet(f1 - r2, fwd_target)
829 self.assertSameSet(f2 - r1, rev_target)
830 self.assertSameSet(r1 - f2, fwd_target)
831 self.assertSameSet(r2 - f1, rev_target)
832 self.assertSameSet(f1 - l2, fwd_target)
833 self.assertSameSet(f2 - l1, rev_target)
834
835 target = r1 ^ r2
836 self.assertSameSet(f1 ^ f2, target)
837 self.assertSameSet(f1 ^ r2, target)
838 self.assertSameSet(r2 ^ f1, target)
839 self.assertSameSet(f1 ^ l2, target)
840
841 # Don't change the following to use assertLess or other
842 # "more specific" unittest assertions. The current
843 # assertTrue/assertFalse style makes the pattern of test
844 # case combinations clear and allows us to know for sure
845 # the exact operator being invoked.
846
847 # proper subset
848 self.assertTrue(f1 < f3)
849 self.assertFalse(f1 < f1)
850 self.assertFalse(f1 < f2)
851 self.assertTrue(r1 < f3)
852 self.assertFalse(r1 < f1)
853 self.assertFalse(r1 < f2)
854 self.assertTrue(r1 < r3)
855 self.assertFalse(r1 < r1)
856 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200857 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700858 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200859 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700860 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200861 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700862 f1 < l2
863
864 # any subset
865 self.assertTrue(f1 <= f3)
866 self.assertTrue(f1 <= f1)
867 self.assertFalse(f1 <= f2)
868 self.assertTrue(r1 <= f3)
869 self.assertTrue(r1 <= f1)
870 self.assertFalse(r1 <= f2)
871 self.assertTrue(r1 <= r3)
872 self.assertTrue(r1 <= r1)
873 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200874 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700875 f1 <= l3
876 with self.assertRaises(TypeError):
877 f1 <= l1
878 with self.assertRaises(TypeError):
879 f1 <= l2
880
881 # proper superset
882 self.assertTrue(f3 > f1)
883 self.assertFalse(f1 > f1)
884 self.assertFalse(f2 > f1)
885 self.assertTrue(r3 > r1)
886 self.assertFalse(f1 > r1)
887 self.assertFalse(f2 > r1)
888 self.assertTrue(r3 > r1)
889 self.assertFalse(r1 > r1)
890 self.assertFalse(r2 > r1)
891 with self.assertRaises(TypeError):
892 f1 > l3
893 with self.assertRaises(TypeError):
894 f1 > l1
895 with self.assertRaises(TypeError):
896 f1 > l2
897
898 # any superset
899 self.assertTrue(f3 >= f1)
900 self.assertTrue(f1 >= f1)
901 self.assertFalse(f2 >= f1)
902 self.assertTrue(r3 >= r1)
903 self.assertTrue(f1 >= r1)
904 self.assertFalse(f2 >= r1)
905 self.assertTrue(r3 >= r1)
906 self.assertTrue(r1 >= r1)
907 self.assertFalse(r2 >= r1)
908 with self.assertRaises(TypeError):
909 f1 >= l3
910 with self.assertRaises(TypeError):
911 f1 >=l1
912 with self.assertRaises(TypeError):
913 f1 >= l2
914
915 # equality
916 self.assertTrue(f1 == f1)
917 self.assertTrue(r1 == f1)
918 self.assertTrue(f1 == r1)
919 self.assertFalse(f1 == f3)
920 self.assertFalse(r1 == f3)
921 self.assertFalse(f1 == r3)
922 self.assertFalse(f1 == l3)
923 self.assertFalse(f1 == l1)
924 self.assertFalse(f1 == l2)
925
926 # inequality
927 self.assertFalse(f1 != f1)
928 self.assertFalse(r1 != f1)
929 self.assertFalse(f1 != r1)
930 self.assertTrue(f1 != f3)
931 self.assertTrue(r1 != f3)
932 self.assertTrue(f1 != r3)
933 self.assertTrue(f1 != l3)
934 self.assertTrue(f1 != l1)
935 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200936
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000937 def test_Mapping(self):
938 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000939 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000940 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000941 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
942 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000943 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000944 def __len__(self):
945 return 0
946 def __getitem__(self, i):
947 raise IndexError
948 def __iter__(self):
949 return iter(())
950 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000951
952 def test_MutableMapping(self):
953 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000954 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000955 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000956 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
957 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000958
Raymond Hettinger9117c752010-08-22 07:44:24 +0000959 def test_MutableMapping_subclass(self):
960 # Test issue 9214
961 mymap = UserDict()
962 mymap['red'] = 5
963 self.assertIsInstance(mymap.keys(), Set)
964 self.assertIsInstance(mymap.keys(), KeysView)
965 self.assertIsInstance(mymap.items(), Set)
966 self.assertIsInstance(mymap.items(), ItemsView)
967
968 mymap = UserDict()
969 mymap['red'] = 5
970 z = mymap.keys() | {'orange'}
971 self.assertIsInstance(z, set)
972 list(z)
973 mymap['blue'] = 7 # Shouldn't affect 'z'
974 self.assertEqual(sorted(z), ['orange', 'red'])
975
976 mymap = UserDict()
977 mymap['red'] = 5
978 z = mymap.items() | {('orange', 3)}
979 self.assertIsInstance(z, set)
980 list(z)
981 mymap['blue'] = 7 # Shouldn't affect 'z'
982 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
983
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000984 def test_Sequence(self):
985 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000986 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000987 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000988 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000989 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +1000990 self.assertIsInstance(memoryview(b""), Sequence)
991 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000992 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000993 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
994 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000995
Guido van Rossumd05eb002007-11-21 22:26:24 +0000996 def test_ByteString(self):
997 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000998 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000999 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001000 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001001 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001002 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001003 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001004 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001005
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001006 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001007 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001008 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001009 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001010 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001011 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001012 self.assertTrue(issubclass(sample, MutableSequence))
1013 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001014 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1015 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001016
Eli Bendersky0716a572011-03-04 10:38:14 +00001017 def test_MutableSequence_mixins(self):
1018 # Test the mixins of MutableSequence by creating a miminal concrete
1019 # class inherited from it.
1020 class MutableSequenceSubclass(MutableSequence):
1021 def __init__(self):
1022 self.lst = []
1023
1024 def __setitem__(self, index, value):
1025 self.lst[index] = value
1026
1027 def __getitem__(self, index):
1028 return self.lst[index]
1029
1030 def __len__(self):
1031 return len(self.lst)
1032
1033 def __delitem__(self, index):
1034 del self.lst[index]
1035
1036 def insert(self, index, value):
1037 self.lst.insert(index, value)
1038
1039 mss = MutableSequenceSubclass()
1040 mss.append(0)
1041 mss.extend((1, 2, 3, 4))
1042 self.assertEqual(len(mss), 5)
1043 self.assertEqual(mss[3], 3)
1044 mss.reverse()
1045 self.assertEqual(mss[3], 1)
1046 mss.pop()
1047 self.assertEqual(len(mss), 4)
1048 mss.remove(3)
1049 self.assertEqual(len(mss), 3)
1050 mss += (10, 20, 30)
1051 self.assertEqual(len(mss), 6)
1052 self.assertEqual(mss[-1], 30)
1053 mss.clear()
1054 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001055
1056################################################################################
1057### Counter
1058################################################################################
1059
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001060class CounterSubclassWithSetItem(Counter):
1061 # Test a counter subclass that overrides __setitem__
1062 def __init__(self, *args, **kwds):
1063 self.called = False
1064 Counter.__init__(self, *args, **kwds)
1065 def __setitem__(self, key, value):
1066 self.called = True
1067 Counter.__setitem__(self, key, value)
1068
1069class CounterSubclassWithGet(Counter):
1070 # Test a counter subclass that overrides get()
1071 def __init__(self, *args, **kwds):
1072 self.called = False
1073 Counter.__init__(self, *args, **kwds)
1074 def get(self, key, default):
1075 self.called = True
1076 return Counter.get(self, key, default)
1077
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001078class TestCounter(unittest.TestCase):
1079
1080 def test_basics(self):
1081 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001082 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1083 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001084 self.assertIsInstance(c, dict)
1085 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001086 self.assertTrue(issubclass(Counter, dict))
1087 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001088 self.assertEqual(len(c), 3)
1089 self.assertEqual(sum(c.values()), 6)
1090 self.assertEqual(sorted(c.values()), [1, 2, 3])
1091 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
1092 self.assertEqual(sorted(c), ['a', 'b', 'c'])
1093 self.assertEqual(sorted(c.items()),
1094 [('a', 3), ('b', 2), ('c', 1)])
1095 self.assertEqual(c['b'], 2)
1096 self.assertEqual(c['z'], 0)
1097 self.assertEqual(c.__contains__('c'), True)
1098 self.assertEqual(c.__contains__('z'), False)
1099 self.assertEqual(c.get('b', 10), 2)
1100 self.assertEqual(c.get('z', 10), 10)
1101 self.assertEqual(c, dict(a=3, b=2, c=1))
1102 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1103 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1104 for i in range(5):
1105 self.assertEqual(c.most_common(i),
1106 [('a', 3), ('b', 2), ('c', 1)][:i])
1107 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
1108 c['a'] += 1 # increment an existing value
1109 c['b'] -= 2 # sub existing value to zero
1110 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001111 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001112 c['d'] -= 2 # sub from a missing value
1113 c['e'] = -5 # directly assign a missing value
1114 c['f'] += 4 # add to a missing value
1115 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
1116 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
1117 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001118 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001119 for i in range(3):
1120 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001121 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001122 c.clear()
1123 self.assertEqual(c, {})
1124 self.assertEqual(repr(c), 'Counter()')
1125 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1126 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001127 c.update(dict(a=5, b=3))
1128 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001129 c.update(Counter('a' * 50 + 'b' * 30))
1130 c.update() # test case with no args
1131 c.__init__('a' * 500 + 'b' * 300)
1132 c.__init__('cdc')
1133 c.__init__()
1134 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1135 self.assertEqual(c.setdefault('d', 5), 1)
1136 self.assertEqual(c['d'], 1)
1137 self.assertEqual(c.setdefault('e', 5), 5)
1138 self.assertEqual(c['e'], 5)
1139
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001140 def test_init(self):
1141 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1142 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1143 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1144 self.assertRaises(TypeError, Counter, 42)
1145 self.assertRaises(TypeError, Counter, (), ())
1146 self.assertRaises(TypeError, Counter.__init__)
1147
1148 def test_update(self):
1149 c = Counter()
1150 c.update(self=42)
1151 self.assertEqual(list(c.items()), [('self', 42)])
1152 c = Counter()
1153 c.update(iterable=42)
1154 self.assertEqual(list(c.items()), [('iterable', 42)])
1155 c = Counter()
1156 c.update(iterable=None)
1157 self.assertEqual(list(c.items()), [('iterable', None)])
1158 self.assertRaises(TypeError, Counter().update, 42)
1159 self.assertRaises(TypeError, Counter().update, {}, {})
1160 self.assertRaises(TypeError, Counter.update)
1161
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001162 def test_copying(self):
1163 # Check that counters are copyable, deepcopyable, picklable, and
1164 #have a repr/eval round-trip
1165 words = Counter('which witch had which witches wrist watch'.split())
1166 update_test = Counter()
1167 update_test.update(words)
Ezio Melotti0cb2aaf2013-07-07 13:37:20 +02001168 for label, dup in [
1169 ('words.copy()', words.copy()),
1170 ('copy.copy(words)', copy.copy(words)),
1171 ('copy.deepcopy(words)', copy.deepcopy(words)),
1172 ('pickle.loads(pickle.dumps(words, 0))',
1173 pickle.loads(pickle.dumps(words, 0))),
1174 ('pickle.loads(pickle.dumps(words, 1))',
1175 pickle.loads(pickle.dumps(words, 1))),
1176 ('pickle.loads(pickle.dumps(words, 2))',
1177 pickle.loads(pickle.dumps(words, 2))),
1178 ('pickle.loads(pickle.dumps(words, -1))',
1179 pickle.loads(pickle.dumps(words, -1))),
1180 ('eval(repr(words))', eval(repr(words))),
1181 ('update_test', update_test),
1182 ('Counter(words)', Counter(words)),
1183 ]:
1184 with self.subTest(label=label):
1185 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1186 self.assertIsNot(dup, words, msg)
1187 self.assertEqual(dup, words)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001188
Raymond Hettinger1c746c22011-04-15 13:16:46 -07001189 def test_copy_subclass(self):
1190 class MyCounter(Counter):
1191 pass
1192 c = MyCounter('slartibartfast')
1193 d = c.copy()
1194 self.assertEqual(d, c)
1195 self.assertEqual(len(d), len(c))
1196 self.assertEqual(type(d), type(c))
1197
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001198 def test_conversions(self):
1199 # Convert to: set, list, dict
1200 s = 'she sells sea shells by the sea shore'
1201 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
1202 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
1203 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
1204 self.assertEqual(set(Counter(s)), set(s))
1205
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001206 def test_invariant_for_the_in_operator(self):
1207 c = Counter(a=10, b=-2, c=0)
1208 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001209 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001210 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001211
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001212 def test_multiset_operations(self):
1213 # Verify that adding a zero counter will strip zeros and negatives
1214 c = Counter(a=10, b=-2, c=0) + Counter()
1215 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001216
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001217 elements = 'abcd'
1218 for i in range(1000):
1219 # test random pairs of multisets
1220 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001221 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001222 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001223 q.update(h=1, i=-1, j=0)
1224 for counterop, numberop in [
1225 (Counter.__add__, lambda x, y: max(0, x+y)),
1226 (Counter.__sub__, lambda x, y: max(0, x-y)),
1227 (Counter.__or__, lambda x, y: max(0,x,y)),
1228 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001229 ]:
1230 result = counterop(p, q)
1231 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001232 self.assertEqual(numberop(p[x], q[x]), result[x],
1233 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001234 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001235 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001236
1237 elements = 'abcdef'
1238 for i in range(100):
1239 # verify that random multisets with no repeats are exactly like sets
1240 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1241 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1242 for counterop, setop in [
1243 (Counter.__sub__, set.__sub__),
1244 (Counter.__or__, set.__or__),
1245 (Counter.__and__, set.__and__),
1246 ]:
1247 counter_result = counterop(p, q)
1248 set_result = setop(set(p.elements()), set(q.elements()))
1249 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001250
Raymond Hettingerbecd5682011-10-19 13:40:37 -07001251 def test_inplace_operations(self):
1252 elements = 'abcd'
1253 for i in range(1000):
1254 # test random pairs of multisets
1255 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1256 p.update(e=1, f=-1, g=0)
1257 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1258 q.update(h=1, i=-1, j=0)
1259 for inplace_op, regular_op in [
1260 (Counter.__iadd__, Counter.__add__),
1261 (Counter.__isub__, Counter.__sub__),
1262 (Counter.__ior__, Counter.__or__),
1263 (Counter.__iand__, Counter.__and__),
1264 ]:
1265 c = p.copy()
1266 c_id = id(c)
1267 regular_result = regular_op(c, q)
1268 inplace_result = inplace_op(c, q)
1269 self.assertEqual(inplace_result, regular_result)
1270 self.assertEqual(id(inplace_result), c_id)
1271
Raymond Hettinger9c01e442010-04-03 10:32:58 +00001272 def test_subtract(self):
1273 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1274 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
1275 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1276 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1277 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
1278 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1279 c = Counter('aaabbcd')
1280 c.subtract('aaaabbcce')
1281 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001282
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001283 c = Counter()
1284 c.subtract(self=42)
1285 self.assertEqual(list(c.items()), [('self', -42)])
1286 c = Counter()
1287 c.subtract(iterable=42)
1288 self.assertEqual(list(c.items()), [('iterable', -42)])
1289 self.assertRaises(TypeError, Counter().subtract, 42)
1290 self.assertRaises(TypeError, Counter().subtract, {}, {})
1291 self.assertRaises(TypeError, Counter.subtract)
1292
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07001293 def test_unary(self):
1294 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1295 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
1296 self.assertEqual(dict(-c), dict(a=5))
1297
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07001298 def test_repr_nonsortable(self):
1299 c = Counter(a=2, b=None)
1300 r = repr(c)
1301 self.assertIn("'a': 2", r)
1302 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07001303
Raymond Hettinger426e0522011-01-03 02:12:02 +00001304 def test_helper_function(self):
1305 # two paths, one for real dicts and one for other mappings
1306 elems = list('abracadabra')
1307
1308 d = dict()
1309 _count_elements(d, elems)
1310 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1311
1312 m = OrderedDict()
1313 _count_elements(m, elems)
1314 self.assertEqual(m,
1315 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
1316
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001317 # test fidelity to the pure python version
1318 c = CounterSubclassWithSetItem('abracadabra')
1319 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001320 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001321 c = CounterSubclassWithGet('abracadabra')
1322 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001323 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001324
Raymond Hettinger499e1932011-02-23 07:56:53 +00001325
1326################################################################################
1327### OrderedDict
1328################################################################################
1329
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001330class TestOrderedDict(unittest.TestCase):
1331
1332 def test_init(self):
1333 with self.assertRaises(TypeError):
1334 OrderedDict([('a', 1), ('b', 2)], None) # too many args
1335 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1336 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
1337 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
1338 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
1339 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
1340 c=3, e=5).items()), pairs) # mixed input
1341
1342 # make sure no positional args conflict with possible kwdargs
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001343 self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
1344 self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
1345 self.assertRaises(TypeError, OrderedDict, 42)
1346 self.assertRaises(TypeError, OrderedDict, (), ())
1347 self.assertRaises(TypeError, OrderedDict.__init__)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001348
1349 # Make sure that direct calls to __init__ do not clear previous contents
1350 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1351 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
1352 self.assertEqual(list(d.items()),
1353 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1354
1355 def test_update(self):
1356 with self.assertRaises(TypeError):
1357 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
1358 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1359 od = OrderedDict()
1360 od.update(dict(pairs))
1361 self.assertEqual(sorted(od.items()), pairs) # dict input
1362 od = OrderedDict()
1363 od.update(**dict(pairs))
1364 self.assertEqual(sorted(od.items()), pairs) # kwds input
1365 od = OrderedDict()
1366 od.update(pairs)
1367 self.assertEqual(list(od.items()), pairs) # pairs input
1368 od = OrderedDict()
1369 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1370 self.assertEqual(list(od.items()), pairs) # mixed input
1371
Mark Dickinsonb214e902010-07-11 18:53:06 +00001372 # Issue 9137: Named argument called 'other' or 'self'
1373 # shouldn't be treated specially.
1374 od = OrderedDict()
1375 od.update(self=23)
1376 self.assertEqual(list(od.items()), [('self', 23)])
1377 od = OrderedDict()
1378 od.update(other={})
1379 self.assertEqual(list(od.items()), [('other', {})])
1380 od = OrderedDict()
1381 od.update(red=5, blue=6, other=7, self=8)
1382 self.assertEqual(sorted(list(od.items())),
1383 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
1384
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001385 # Make sure that direct calls to update do not clear previous contents
1386 # add that updates items are not moved to the end
1387 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1388 d.update([('e', 5), ('f', 6)], g=7, d=4)
1389 self.assertEqual(list(d.items()),
1390 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1391
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001392 self.assertRaises(TypeError, OrderedDict().update, 42)
1393 self.assertRaises(TypeError, OrderedDict().update, (), ())
1394 self.assertRaises(TypeError, OrderedDict.update)
1395
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001396 def test_abc(self):
1397 self.assertIsInstance(OrderedDict(), MutableMapping)
1398 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1399
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001400 def test_clear(self):
1401 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1402 shuffle(pairs)
1403 od = OrderedDict(pairs)
1404 self.assertEqual(len(od), len(pairs))
1405 od.clear()
1406 self.assertEqual(len(od), 0)
1407
1408 def test_delitem(self):
1409 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1410 od = OrderedDict(pairs)
1411 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001412 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001413 with self.assertRaises(KeyError):
1414 del od['a']
1415 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1416
1417 def test_setitem(self):
1418 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1419 od['c'] = 10 # existing element
1420 od['f'] = 20 # new element
1421 self.assertEqual(list(od.items()),
1422 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1423
1424 def test_iterators(self):
1425 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1426 shuffle(pairs)
1427 od = OrderedDict(pairs)
1428 self.assertEqual(list(od), [t[0] for t in pairs])
1429 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1430 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1431 self.assertEqual(list(od.items()), pairs)
1432 self.assertEqual(list(reversed(od)),
1433 [t[0] for t in reversed(pairs)])
Serhiy Storchaka578c9212014-04-04 15:19:36 +03001434 self.assertEqual(list(reversed(od.keys())),
1435 [t[0] for t in reversed(pairs)])
1436 self.assertEqual(list(reversed(od.values())),
1437 [t[1] for t in reversed(pairs)])
1438 self.assertEqual(list(reversed(od.items())), list(reversed(pairs)))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001439
Raymond Hettinger53d2c412014-05-03 21:58:45 -07001440 def test_detect_deletion_during_iteration(self):
1441 od = OrderedDict.fromkeys('abc')
1442 it = iter(od)
1443 key = next(it)
1444 del od[key]
1445 with self.assertRaises(Exception):
1446 # Note, the exact exception raised is not guaranteed
1447 # The only guarantee that the next() will not succeed
1448 next(it)
1449
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001450 def test_popitem(self):
1451 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1452 shuffle(pairs)
1453 od = OrderedDict(pairs)
1454 while pairs:
1455 self.assertEqual(od.popitem(), pairs.pop())
1456 with self.assertRaises(KeyError):
1457 od.popitem()
1458 self.assertEqual(len(od), 0)
1459
1460 def test_pop(self):
1461 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1462 shuffle(pairs)
1463 od = OrderedDict(pairs)
1464 shuffle(pairs)
1465 while pairs:
1466 k, v = pairs.pop()
1467 self.assertEqual(od.pop(k), v)
1468 with self.assertRaises(KeyError):
1469 od.pop('xyz')
1470 self.assertEqual(len(od), 0)
1471 self.assertEqual(od.pop(k, 12345), 12345)
1472
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001473 # make sure pop still works when __missing__ is defined
1474 class Missing(OrderedDict):
1475 def __missing__(self, key):
1476 return 0
1477 m = Missing(a=1)
1478 self.assertEqual(m.pop('b', 5), 5)
1479 self.assertEqual(m.pop('a', 6), 1)
1480 self.assertEqual(m.pop('a', 6), 6)
1481 with self.assertRaises(KeyError):
1482 m.pop('a')
1483
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001484 def test_equality(self):
1485 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1486 shuffle(pairs)
1487 od1 = OrderedDict(pairs)
1488 od2 = OrderedDict(pairs)
1489 self.assertEqual(od1, od2) # same order implies equality
1490 pairs = pairs[2:] + pairs[:2]
1491 od2 = OrderedDict(pairs)
1492 self.assertNotEqual(od1, od2) # different order implies inequality
1493 # comparison to regular dict is not order sensitive
1494 self.assertEqual(od1, dict(od2))
1495 self.assertEqual(dict(od2), od1)
1496 # different length implied inequality
1497 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1498
1499 def test_copying(self):
1500 # Check that ordered dicts are copyable, deepcopyable, picklable,
1501 # and have a repr/eval round-trip
1502 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1503 od = OrderedDict(pairs)
1504 update_test = OrderedDict()
1505 update_test.update(od)
Ezio Melotti0cb2aaf2013-07-07 13:37:20 +02001506 for label, dup in [
1507 ('od.copy()', od.copy()),
1508 ('copy.copy(od)', copy.copy(od)),
1509 ('copy.deepcopy(od)', copy.deepcopy(od)),
1510 ('pickle.loads(pickle.dumps(od, 0))',
1511 pickle.loads(pickle.dumps(od, 0))),
1512 ('pickle.loads(pickle.dumps(od, 1))',
1513 pickle.loads(pickle.dumps(od, 1))),
1514 ('pickle.loads(pickle.dumps(od, 2))',
1515 pickle.loads(pickle.dumps(od, 2))),
1516 ('pickle.loads(pickle.dumps(od, 3))',
1517 pickle.loads(pickle.dumps(od, 3))),
1518 ('pickle.loads(pickle.dumps(od, -1))',
1519 pickle.loads(pickle.dumps(od, -1))),
1520 ('eval(repr(od))', eval(repr(od))),
1521 ('update_test', update_test),
1522 ('OrderedDict(od)', OrderedDict(od)),
1523 ]:
1524 with self.subTest(label=label):
1525 msg = "\ncopy: %s\nod: %s" % (dup, od)
1526 self.assertIsNot(dup, od, msg)
1527 self.assertEqual(dup, od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001528
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001529 def test_yaml_linkage(self):
1530 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1531 # In yaml, lists are native but tuples are not.
1532 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1533 od = OrderedDict(pairs)
1534 # yaml.dump(od) -->
1535 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001536 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001537
Raymond Hettingerb2121572009-03-03 22:50:04 +00001538 def test_reduce_not_too_fat(self):
1539 # do not save instance dictionary if not needed
1540 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1541 od = OrderedDict(pairs)
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001542 self.assertIsNone(od.__reduce__()[2])
Raymond Hettingerb2121572009-03-03 22:50:04 +00001543 od.x = 10
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001544 self.assertIsNotNone(od.__reduce__()[2])
1545
1546 def test_pickle_recursive(self):
1547 od = OrderedDict()
1548 od[1] = od
1549 for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
1550 dup = pickle.loads(pickle.dumps(od, proto))
1551 self.assertIsNot(dup, od)
1552 self.assertEqual(list(dup.keys()), [1])
1553 self.assertIs(dup[1], dup)
Raymond Hettingerb2121572009-03-03 22:50:04 +00001554
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001555 def test_repr(self):
1556 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1557 self.assertEqual(repr(od),
1558 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1559 self.assertEqual(eval(repr(od)), od)
1560 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1561
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001562 def test_repr_recursive(self):
1563 # See issue #9826
1564 od = OrderedDict.fromkeys('abc')
1565 od['x'] = od
1566 self.assertEqual(repr(od),
1567 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1568
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001569 def test_setdefault(self):
1570 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1571 shuffle(pairs)
1572 od = OrderedDict(pairs)
1573 pair_order = list(od.items())
1574 self.assertEqual(od.setdefault('a', 10), 3)
1575 # make sure order didn't change
1576 self.assertEqual(list(od.items()), pair_order)
1577 self.assertEqual(od.setdefault('x', 10), 10)
1578 # make sure 'x' is added to the end
1579 self.assertEqual(list(od.items())[-1], ('x', 10))
1580
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001581 # make sure setdefault still works when __missing__ is defined
1582 class Missing(OrderedDict):
1583 def __missing__(self, key):
1584 return 0
1585 self.assertEqual(Missing().setdefault(5, 9), 9)
1586
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001587 def test_reinsert(self):
1588 # Given insert a, insert b, delete a, re-insert a,
1589 # verify that a is now later than b.
1590 od = OrderedDict()
1591 od['a'] = 1
1592 od['b'] = 2
1593 del od['a']
1594 od['a'] = 1
1595 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1596
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001597 def test_move_to_end(self):
1598 od = OrderedDict.fromkeys('abcde')
1599 self.assertEqual(list(od), list('abcde'))
1600 od.move_to_end('c')
1601 self.assertEqual(list(od), list('abdec'))
1602 od.move_to_end('c', 0)
1603 self.assertEqual(list(od), list('cabde'))
1604 od.move_to_end('c', 0)
1605 self.assertEqual(list(od), list('cabde'))
1606 od.move_to_end('e')
1607 self.assertEqual(list(od), list('cabde'))
1608 with self.assertRaises(KeyError):
1609 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001610
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001611 def test_sizeof(self):
1612 # Wimpy test: Just verify the reported size is larger than a regular dict
1613 d = dict(a=1)
1614 od = OrderedDict(**d)
1615 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1616
Raymond Hettinger32062e92011-01-01 22:38:00 +00001617 def test_override_update(self):
1618 # Verify that subclasses can override update() without breaking __init__()
1619 class MyOD(OrderedDict):
1620 def update(self, *args, **kwds):
1621 raise Exception()
1622 items = [('a', 1), ('c', 3), ('b', 2)]
1623 self.assertEqual(list(MyOD(items).items()), items)
1624
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001625class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1626 type2test = OrderedDict
1627
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001628 def test_popitem(self):
1629 d = self._empty_mapping()
1630 self.assertRaises(KeyError, d.popitem)
1631
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001632class MyOrderedDict(OrderedDict):
1633 pass
1634
1635class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1636 type2test = MyOrderedDict
1637
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001638 def test_popitem(self):
1639 d = self._empty_mapping()
1640 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001641
1642
Raymond Hettinger499e1932011-02-23 07:56:53 +00001643################################################################################
1644### Run tests
1645################################################################################
1646
Christian Heimes25bb7832008-01-11 16:17:00 +00001647import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001648
Guido van Rossumd8faa362007-04-27 19:54:29 +00001649def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001650 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001651 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001652 TestCollectionABCs, TestCounter, TestChainMap,
Serhiy Storchakaa86700a2014-11-27 17:45:44 +02001653 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001654 support.run_unittest(*test_classes)
1655 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001656
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001657
Guido van Rossumd8faa362007-04-27 19:54:29 +00001658if __name__ == "__main__":
1659 test_main(verbose=True)