blob: 7780c48e3962a31b78610a95e3747ac5d09eefe2 [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
514 raise StopIteration
515 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
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000643 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000644 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000645 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000646 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000647 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000648 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
649 'add', 'discard')
650
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000651 def test_issue_5647(self):
652 # MutableSet.__iand__ mutated the set during iteration
653 s = WithSet('abcd')
654 s &= WithSet('cdef') # This used to fail
655 self.assertEqual(set(s), set('cd'))
656
Raymond Hettingerae650182009-01-28 23:33:59 +0000657 def test_issue_4920(self):
658 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000659 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000660 __slots__=['__s']
661 def __init__(self,items=None):
662 if items is None:
663 items=[]
664 self.__s=set(items)
665 def __contains__(self,v):
666 return v in self.__s
667 def __iter__(self):
668 return iter(self.__s)
669 def __len__(self):
670 return len(self.__s)
671 def add(self,v):
672 result=v not in self.__s
673 self.__s.add(v)
674 return result
675 def discard(self,v):
676 result=v in self.__s
677 self.__s.discard(v)
678 return result
679 def __repr__(self):
680 return "MySet(%s)" % repr(list(self))
681 s = MySet([5,43,2,1])
682 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000683
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000684 def test_issue8750(self):
685 empty = WithSet()
686 full = WithSet(range(10))
687 s = WithSet(full)
688 s -= s
689 self.assertEqual(s, empty)
690 s = WithSet(full)
691 s ^= s
692 self.assertEqual(s, empty)
693 s = WithSet(full)
694 s &= s
695 self.assertEqual(s, full)
696 s |= s
697 self.assertEqual(s, full)
698
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200699 def test_issue16373(self):
700 # Recursion error comparing comparable and noncomparable
701 # Set instances
702 class MyComparableSet(Set):
703 def __contains__(self, x):
704 return False
705 def __len__(self):
706 return 0
707 def __iter__(self):
708 return iter([])
709 class MyNonComparableSet(Set):
710 def __contains__(self, x):
711 return False
712 def __len__(self):
713 return 0
714 def __iter__(self):
715 return iter([])
716 def __le__(self, x):
717 return NotImplemented
718 def __lt__(self, x):
719 return NotImplemented
720
721 cs = MyComparableSet()
722 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700723 self.assertFalse(ncs < cs)
724 self.assertTrue(ncs <= cs)
725 self.assertFalse(ncs > cs)
726 self.assertTrue(ncs >= cs)
727
728 def assertSameSet(self, s1, s2):
729 # coerce both to a real set then check equality
730 self.assertSetEqual(set(s1), set(s2))
731
732 def test_Set_interoperability_with_real_sets(self):
733 # Issue: 8743
734 class ListSet(Set):
735 def __init__(self, elements=()):
736 self.data = []
737 for elem in elements:
738 if elem not in self.data:
739 self.data.append(elem)
740 def __contains__(self, elem):
741 return elem in self.data
742 def __iter__(self):
743 return iter(self.data)
744 def __len__(self):
745 return len(self.data)
746 def __repr__(self):
747 return 'Set({!r})'.format(self.data)
748
749 r1 = set('abc')
750 r2 = set('bcd')
751 r3 = set('abcde')
752 f1 = ListSet('abc')
753 f2 = ListSet('bcd')
754 f3 = ListSet('abcde')
755 l1 = list('abccba')
756 l2 = list('bcddcb')
757 l3 = list('abcdeedcba')
758
759 target = r1 & r2
760 self.assertSameSet(f1 & f2, target)
761 self.assertSameSet(f1 & r2, target)
762 self.assertSameSet(r2 & f1, target)
763 self.assertSameSet(f1 & l2, target)
764
765 target = r1 | r2
766 self.assertSameSet(f1 | f2, target)
767 self.assertSameSet(f1 | r2, target)
768 self.assertSameSet(r2 | f1, target)
769 self.assertSameSet(f1 | l2, target)
770
771 fwd_target = r1 - r2
772 rev_target = r2 - r1
773 self.assertSameSet(f1 - f2, fwd_target)
774 self.assertSameSet(f2 - f1, rev_target)
775 self.assertSameSet(f1 - r2, fwd_target)
776 self.assertSameSet(f2 - r1, rev_target)
777 self.assertSameSet(r1 - f2, fwd_target)
778 self.assertSameSet(r2 - f1, rev_target)
779 self.assertSameSet(f1 - l2, fwd_target)
780 self.assertSameSet(f2 - l1, rev_target)
781
782 target = r1 ^ r2
783 self.assertSameSet(f1 ^ f2, target)
784 self.assertSameSet(f1 ^ r2, target)
785 self.assertSameSet(r2 ^ f1, target)
786 self.assertSameSet(f1 ^ l2, target)
787
788 # Don't change the following to use assertLess or other
789 # "more specific" unittest assertions. The current
790 # assertTrue/assertFalse style makes the pattern of test
791 # case combinations clear and allows us to know for sure
792 # the exact operator being invoked.
793
794 # proper subset
795 self.assertTrue(f1 < f3)
796 self.assertFalse(f1 < f1)
797 self.assertFalse(f1 < f2)
798 self.assertTrue(r1 < f3)
799 self.assertFalse(r1 < f1)
800 self.assertFalse(r1 < f2)
801 self.assertTrue(r1 < r3)
802 self.assertFalse(r1 < r1)
803 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200804 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700805 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200806 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700807 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200808 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700809 f1 < l2
810
811 # any subset
812 self.assertTrue(f1 <= f3)
813 self.assertTrue(f1 <= f1)
814 self.assertFalse(f1 <= f2)
815 self.assertTrue(r1 <= f3)
816 self.assertTrue(r1 <= f1)
817 self.assertFalse(r1 <= f2)
818 self.assertTrue(r1 <= r3)
819 self.assertTrue(r1 <= r1)
820 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200821 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700822 f1 <= l3
823 with self.assertRaises(TypeError):
824 f1 <= l1
825 with self.assertRaises(TypeError):
826 f1 <= l2
827
828 # proper superset
829 self.assertTrue(f3 > f1)
830 self.assertFalse(f1 > f1)
831 self.assertFalse(f2 > f1)
832 self.assertTrue(r3 > r1)
833 self.assertFalse(f1 > r1)
834 self.assertFalse(f2 > r1)
835 self.assertTrue(r3 > r1)
836 self.assertFalse(r1 > r1)
837 self.assertFalse(r2 > r1)
838 with self.assertRaises(TypeError):
839 f1 > l3
840 with self.assertRaises(TypeError):
841 f1 > l1
842 with self.assertRaises(TypeError):
843 f1 > l2
844
845 # any superset
846 self.assertTrue(f3 >= f1)
847 self.assertTrue(f1 >= f1)
848 self.assertFalse(f2 >= f1)
849 self.assertTrue(r3 >= r1)
850 self.assertTrue(f1 >= r1)
851 self.assertFalse(f2 >= r1)
852 self.assertTrue(r3 >= r1)
853 self.assertTrue(r1 >= r1)
854 self.assertFalse(r2 >= r1)
855 with self.assertRaises(TypeError):
856 f1 >= l3
857 with self.assertRaises(TypeError):
858 f1 >=l1
859 with self.assertRaises(TypeError):
860 f1 >= l2
861
862 # equality
863 self.assertTrue(f1 == f1)
864 self.assertTrue(r1 == f1)
865 self.assertTrue(f1 == r1)
866 self.assertFalse(f1 == f3)
867 self.assertFalse(r1 == f3)
868 self.assertFalse(f1 == r3)
869 self.assertFalse(f1 == l3)
870 self.assertFalse(f1 == l1)
871 self.assertFalse(f1 == l2)
872
873 # inequality
874 self.assertFalse(f1 != f1)
875 self.assertFalse(r1 != f1)
876 self.assertFalse(f1 != r1)
877 self.assertTrue(f1 != f3)
878 self.assertTrue(r1 != f3)
879 self.assertTrue(f1 != r3)
880 self.assertTrue(f1 != l3)
881 self.assertTrue(f1 != l1)
882 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200883
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000884 def test_Mapping(self):
885 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000886 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000887 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000888 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
889 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000890 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000891 def __len__(self):
892 return 0
893 def __getitem__(self, i):
894 raise IndexError
895 def __iter__(self):
896 return iter(())
897 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000898
899 def test_MutableMapping(self):
900 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000901 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000902 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000903 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
904 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000905
Raymond Hettinger9117c752010-08-22 07:44:24 +0000906 def test_MutableMapping_subclass(self):
907 # Test issue 9214
908 mymap = UserDict()
909 mymap['red'] = 5
910 self.assertIsInstance(mymap.keys(), Set)
911 self.assertIsInstance(mymap.keys(), KeysView)
912 self.assertIsInstance(mymap.items(), Set)
913 self.assertIsInstance(mymap.items(), ItemsView)
914
915 mymap = UserDict()
916 mymap['red'] = 5
917 z = mymap.keys() | {'orange'}
918 self.assertIsInstance(z, set)
919 list(z)
920 mymap['blue'] = 7 # Shouldn't affect 'z'
921 self.assertEqual(sorted(z), ['orange', 'red'])
922
923 mymap = UserDict()
924 mymap['red'] = 5
925 z = mymap.items() | {('orange', 3)}
926 self.assertIsInstance(z, set)
927 list(z)
928 mymap['blue'] = 7 # Shouldn't affect 'z'
929 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
930
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000931 def test_Sequence(self):
932 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000933 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000934 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000935 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000936 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +1000937 self.assertIsInstance(memoryview(b""), Sequence)
938 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000939 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000940 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
941 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000942
Guido van Rossumd05eb002007-11-21 22:26:24 +0000943 def test_ByteString(self):
944 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000945 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000946 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000947 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000948 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000949 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000950 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000951 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000952
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000953 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000954 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000955 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000956 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000957 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000958 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000959 self.assertTrue(issubclass(sample, MutableSequence))
960 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000961 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
962 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000963
Eli Bendersky0716a572011-03-04 10:38:14 +0000964 def test_MutableSequence_mixins(self):
965 # Test the mixins of MutableSequence by creating a miminal concrete
966 # class inherited from it.
967 class MutableSequenceSubclass(MutableSequence):
968 def __init__(self):
969 self.lst = []
970
971 def __setitem__(self, index, value):
972 self.lst[index] = value
973
974 def __getitem__(self, index):
975 return self.lst[index]
976
977 def __len__(self):
978 return len(self.lst)
979
980 def __delitem__(self, index):
981 del self.lst[index]
982
983 def insert(self, index, value):
984 self.lst.insert(index, value)
985
986 mss = MutableSequenceSubclass()
987 mss.append(0)
988 mss.extend((1, 2, 3, 4))
989 self.assertEqual(len(mss), 5)
990 self.assertEqual(mss[3], 3)
991 mss.reverse()
992 self.assertEqual(mss[3], 1)
993 mss.pop()
994 self.assertEqual(len(mss), 4)
995 mss.remove(3)
996 self.assertEqual(len(mss), 3)
997 mss += (10, 20, 30)
998 self.assertEqual(len(mss), 6)
999 self.assertEqual(mss[-1], 30)
1000 mss.clear()
1001 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001002
1003################################################################################
1004### Counter
1005################################################################################
1006
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001007class CounterSubclassWithSetItem(Counter):
1008 # Test a counter subclass that overrides __setitem__
1009 def __init__(self, *args, **kwds):
1010 self.called = False
1011 Counter.__init__(self, *args, **kwds)
1012 def __setitem__(self, key, value):
1013 self.called = True
1014 Counter.__setitem__(self, key, value)
1015
1016class CounterSubclassWithGet(Counter):
1017 # Test a counter subclass that overrides get()
1018 def __init__(self, *args, **kwds):
1019 self.called = False
1020 Counter.__init__(self, *args, **kwds)
1021 def get(self, key, default):
1022 self.called = True
1023 return Counter.get(self, key, default)
1024
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001025class TestCounter(unittest.TestCase):
1026
1027 def test_basics(self):
1028 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001029 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1030 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001031 self.assertIsInstance(c, dict)
1032 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001033 self.assertTrue(issubclass(Counter, dict))
1034 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001035 self.assertEqual(len(c), 3)
1036 self.assertEqual(sum(c.values()), 6)
1037 self.assertEqual(sorted(c.values()), [1, 2, 3])
1038 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
1039 self.assertEqual(sorted(c), ['a', 'b', 'c'])
1040 self.assertEqual(sorted(c.items()),
1041 [('a', 3), ('b', 2), ('c', 1)])
1042 self.assertEqual(c['b'], 2)
1043 self.assertEqual(c['z'], 0)
1044 self.assertEqual(c.__contains__('c'), True)
1045 self.assertEqual(c.__contains__('z'), False)
1046 self.assertEqual(c.get('b', 10), 2)
1047 self.assertEqual(c.get('z', 10), 10)
1048 self.assertEqual(c, dict(a=3, b=2, c=1))
1049 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1050 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1051 for i in range(5):
1052 self.assertEqual(c.most_common(i),
1053 [('a', 3), ('b', 2), ('c', 1)][:i])
1054 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
1055 c['a'] += 1 # increment an existing value
1056 c['b'] -= 2 # sub existing value to zero
1057 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001058 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001059 c['d'] -= 2 # sub from a missing value
1060 c['e'] = -5 # directly assign a missing value
1061 c['f'] += 4 # add to a missing value
1062 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
1063 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
1064 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001065 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001066 for i in range(3):
1067 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001068 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001069 c.clear()
1070 self.assertEqual(c, {})
1071 self.assertEqual(repr(c), 'Counter()')
1072 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1073 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001074 c.update(dict(a=5, b=3))
1075 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001076 c.update(Counter('a' * 50 + 'b' * 30))
1077 c.update() # test case with no args
1078 c.__init__('a' * 500 + 'b' * 300)
1079 c.__init__('cdc')
1080 c.__init__()
1081 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1082 self.assertEqual(c.setdefault('d', 5), 1)
1083 self.assertEqual(c['d'], 1)
1084 self.assertEqual(c.setdefault('e', 5), 5)
1085 self.assertEqual(c['e'], 5)
1086
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001087 def test_init(self):
1088 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1089 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1090 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1091 self.assertRaises(TypeError, Counter, 42)
1092 self.assertRaises(TypeError, Counter, (), ())
1093 self.assertRaises(TypeError, Counter.__init__)
1094
1095 def test_update(self):
1096 c = Counter()
1097 c.update(self=42)
1098 self.assertEqual(list(c.items()), [('self', 42)])
1099 c = Counter()
1100 c.update(iterable=42)
1101 self.assertEqual(list(c.items()), [('iterable', 42)])
1102 c = Counter()
1103 c.update(iterable=None)
1104 self.assertEqual(list(c.items()), [('iterable', None)])
1105 self.assertRaises(TypeError, Counter().update, 42)
1106 self.assertRaises(TypeError, Counter().update, {}, {})
1107 self.assertRaises(TypeError, Counter.update)
1108
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001109 def test_copying(self):
1110 # Check that counters are copyable, deepcopyable, picklable, and
1111 #have a repr/eval round-trip
1112 words = Counter('which witch had which witches wrist watch'.split())
1113 update_test = Counter()
1114 update_test.update(words)
Ezio Melotti0cb2aaf2013-07-07 13:37:20 +02001115 for label, dup in [
1116 ('words.copy()', words.copy()),
1117 ('copy.copy(words)', copy.copy(words)),
1118 ('copy.deepcopy(words)', copy.deepcopy(words)),
1119 ('pickle.loads(pickle.dumps(words, 0))',
1120 pickle.loads(pickle.dumps(words, 0))),
1121 ('pickle.loads(pickle.dumps(words, 1))',
1122 pickle.loads(pickle.dumps(words, 1))),
1123 ('pickle.loads(pickle.dumps(words, 2))',
1124 pickle.loads(pickle.dumps(words, 2))),
1125 ('pickle.loads(pickle.dumps(words, -1))',
1126 pickle.loads(pickle.dumps(words, -1))),
1127 ('eval(repr(words))', eval(repr(words))),
1128 ('update_test', update_test),
1129 ('Counter(words)', Counter(words)),
1130 ]:
1131 with self.subTest(label=label):
1132 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1133 self.assertIsNot(dup, words, msg)
1134 self.assertEqual(dup, words)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001135
Raymond Hettinger1c746c22011-04-15 13:16:46 -07001136 def test_copy_subclass(self):
1137 class MyCounter(Counter):
1138 pass
1139 c = MyCounter('slartibartfast')
1140 d = c.copy()
1141 self.assertEqual(d, c)
1142 self.assertEqual(len(d), len(c))
1143 self.assertEqual(type(d), type(c))
1144
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001145 def test_conversions(self):
1146 # Convert to: set, list, dict
1147 s = 'she sells sea shells by the sea shore'
1148 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
1149 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
1150 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
1151 self.assertEqual(set(Counter(s)), set(s))
1152
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001153 def test_invariant_for_the_in_operator(self):
1154 c = Counter(a=10, b=-2, c=0)
1155 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001156 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001157 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001158
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001159 def test_multiset_operations(self):
1160 # Verify that adding a zero counter will strip zeros and negatives
1161 c = Counter(a=10, b=-2, c=0) + Counter()
1162 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001163
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001164 elements = 'abcd'
1165 for i in range(1000):
1166 # test random pairs of multisets
1167 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001168 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001169 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001170 q.update(h=1, i=-1, j=0)
1171 for counterop, numberop in [
1172 (Counter.__add__, lambda x, y: max(0, x+y)),
1173 (Counter.__sub__, lambda x, y: max(0, x-y)),
1174 (Counter.__or__, lambda x, y: max(0,x,y)),
1175 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001176 ]:
1177 result = counterop(p, q)
1178 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001179 self.assertEqual(numberop(p[x], q[x]), result[x],
1180 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001181 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001182 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001183
1184 elements = 'abcdef'
1185 for i in range(100):
1186 # verify that random multisets with no repeats are exactly like sets
1187 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1188 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1189 for counterop, setop in [
1190 (Counter.__sub__, set.__sub__),
1191 (Counter.__or__, set.__or__),
1192 (Counter.__and__, set.__and__),
1193 ]:
1194 counter_result = counterop(p, q)
1195 set_result = setop(set(p.elements()), set(q.elements()))
1196 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001197
Raymond Hettingerbecd5682011-10-19 13:40:37 -07001198 def test_inplace_operations(self):
1199 elements = 'abcd'
1200 for i in range(1000):
1201 # test random pairs of multisets
1202 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1203 p.update(e=1, f=-1, g=0)
1204 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1205 q.update(h=1, i=-1, j=0)
1206 for inplace_op, regular_op in [
1207 (Counter.__iadd__, Counter.__add__),
1208 (Counter.__isub__, Counter.__sub__),
1209 (Counter.__ior__, Counter.__or__),
1210 (Counter.__iand__, Counter.__and__),
1211 ]:
1212 c = p.copy()
1213 c_id = id(c)
1214 regular_result = regular_op(c, q)
1215 inplace_result = inplace_op(c, q)
1216 self.assertEqual(inplace_result, regular_result)
1217 self.assertEqual(id(inplace_result), c_id)
1218
Raymond Hettinger9c01e442010-04-03 10:32:58 +00001219 def test_subtract(self):
1220 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1221 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
1222 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1223 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1224 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
1225 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1226 c = Counter('aaabbcd')
1227 c.subtract('aaaabbcce')
1228 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001229
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001230 c = Counter()
1231 c.subtract(self=42)
1232 self.assertEqual(list(c.items()), [('self', -42)])
1233 c = Counter()
1234 c.subtract(iterable=42)
1235 self.assertEqual(list(c.items()), [('iterable', -42)])
1236 self.assertRaises(TypeError, Counter().subtract, 42)
1237 self.assertRaises(TypeError, Counter().subtract, {}, {})
1238 self.assertRaises(TypeError, Counter.subtract)
1239
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07001240 def test_unary(self):
1241 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1242 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
1243 self.assertEqual(dict(-c), dict(a=5))
1244
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07001245 def test_repr_nonsortable(self):
1246 c = Counter(a=2, b=None)
1247 r = repr(c)
1248 self.assertIn("'a': 2", r)
1249 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07001250
Raymond Hettinger426e0522011-01-03 02:12:02 +00001251 def test_helper_function(self):
1252 # two paths, one for real dicts and one for other mappings
1253 elems = list('abracadabra')
1254
1255 d = dict()
1256 _count_elements(d, elems)
1257 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1258
1259 m = OrderedDict()
1260 _count_elements(m, elems)
1261 self.assertEqual(m,
1262 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
1263
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001264 # test fidelity to the pure python version
1265 c = CounterSubclassWithSetItem('abracadabra')
1266 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001267 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001268 c = CounterSubclassWithGet('abracadabra')
1269 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001270 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001271
Raymond Hettinger499e1932011-02-23 07:56:53 +00001272
1273################################################################################
1274### OrderedDict
1275################################################################################
1276
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001277class TestOrderedDict(unittest.TestCase):
1278
1279 def test_init(self):
1280 with self.assertRaises(TypeError):
1281 OrderedDict([('a', 1), ('b', 2)], None) # too many args
1282 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1283 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
1284 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
1285 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
1286 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
1287 c=3, e=5).items()), pairs) # mixed input
1288
1289 # make sure no positional args conflict with possible kwdargs
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001290 self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
1291 self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
1292 self.assertRaises(TypeError, OrderedDict, 42)
1293 self.assertRaises(TypeError, OrderedDict, (), ())
1294 self.assertRaises(TypeError, OrderedDict.__init__)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001295
1296 # Make sure that direct calls to __init__ do not clear previous contents
1297 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1298 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
1299 self.assertEqual(list(d.items()),
1300 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1301
1302 def test_update(self):
1303 with self.assertRaises(TypeError):
1304 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
1305 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1306 od = OrderedDict()
1307 od.update(dict(pairs))
1308 self.assertEqual(sorted(od.items()), pairs) # dict input
1309 od = OrderedDict()
1310 od.update(**dict(pairs))
1311 self.assertEqual(sorted(od.items()), pairs) # kwds input
1312 od = OrderedDict()
1313 od.update(pairs)
1314 self.assertEqual(list(od.items()), pairs) # pairs input
1315 od = OrderedDict()
1316 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1317 self.assertEqual(list(od.items()), pairs) # mixed input
1318
Mark Dickinsonb214e902010-07-11 18:53:06 +00001319 # Issue 9137: Named argument called 'other' or 'self'
1320 # shouldn't be treated specially.
1321 od = OrderedDict()
1322 od.update(self=23)
1323 self.assertEqual(list(od.items()), [('self', 23)])
1324 od = OrderedDict()
1325 od.update(other={})
1326 self.assertEqual(list(od.items()), [('other', {})])
1327 od = OrderedDict()
1328 od.update(red=5, blue=6, other=7, self=8)
1329 self.assertEqual(sorted(list(od.items())),
1330 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
1331
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001332 # Make sure that direct calls to update do not clear previous contents
1333 # add that updates items are not moved to the end
1334 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1335 d.update([('e', 5), ('f', 6)], g=7, d=4)
1336 self.assertEqual(list(d.items()),
1337 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1338
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001339 self.assertRaises(TypeError, OrderedDict().update, 42)
1340 self.assertRaises(TypeError, OrderedDict().update, (), ())
1341 self.assertRaises(TypeError, OrderedDict.update)
1342
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001343 def test_abc(self):
1344 self.assertIsInstance(OrderedDict(), MutableMapping)
1345 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1346
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001347 def test_clear(self):
1348 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1349 shuffle(pairs)
1350 od = OrderedDict(pairs)
1351 self.assertEqual(len(od), len(pairs))
1352 od.clear()
1353 self.assertEqual(len(od), 0)
1354
1355 def test_delitem(self):
1356 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1357 od = OrderedDict(pairs)
1358 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001359 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001360 with self.assertRaises(KeyError):
1361 del od['a']
1362 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1363
1364 def test_setitem(self):
1365 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1366 od['c'] = 10 # existing element
1367 od['f'] = 20 # new element
1368 self.assertEqual(list(od.items()),
1369 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1370
1371 def test_iterators(self):
1372 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1373 shuffle(pairs)
1374 od = OrderedDict(pairs)
1375 self.assertEqual(list(od), [t[0] for t in pairs])
1376 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1377 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1378 self.assertEqual(list(od.items()), pairs)
1379 self.assertEqual(list(reversed(od)),
1380 [t[0] for t in reversed(pairs)])
1381
1382 def test_popitem(self):
1383 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1384 shuffle(pairs)
1385 od = OrderedDict(pairs)
1386 while pairs:
1387 self.assertEqual(od.popitem(), pairs.pop())
1388 with self.assertRaises(KeyError):
1389 od.popitem()
1390 self.assertEqual(len(od), 0)
1391
1392 def test_pop(self):
1393 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1394 shuffle(pairs)
1395 od = OrderedDict(pairs)
1396 shuffle(pairs)
1397 while pairs:
1398 k, v = pairs.pop()
1399 self.assertEqual(od.pop(k), v)
1400 with self.assertRaises(KeyError):
1401 od.pop('xyz')
1402 self.assertEqual(len(od), 0)
1403 self.assertEqual(od.pop(k, 12345), 12345)
1404
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001405 # make sure pop still works when __missing__ is defined
1406 class Missing(OrderedDict):
1407 def __missing__(self, key):
1408 return 0
1409 m = Missing(a=1)
1410 self.assertEqual(m.pop('b', 5), 5)
1411 self.assertEqual(m.pop('a', 6), 1)
1412 self.assertEqual(m.pop('a', 6), 6)
1413 with self.assertRaises(KeyError):
1414 m.pop('a')
1415
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001416 def test_equality(self):
1417 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1418 shuffle(pairs)
1419 od1 = OrderedDict(pairs)
1420 od2 = OrderedDict(pairs)
1421 self.assertEqual(od1, od2) # same order implies equality
1422 pairs = pairs[2:] + pairs[:2]
1423 od2 = OrderedDict(pairs)
1424 self.assertNotEqual(od1, od2) # different order implies inequality
1425 # comparison to regular dict is not order sensitive
1426 self.assertEqual(od1, dict(od2))
1427 self.assertEqual(dict(od2), od1)
1428 # different length implied inequality
1429 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1430
1431 def test_copying(self):
1432 # Check that ordered dicts are copyable, deepcopyable, picklable,
1433 # and have a repr/eval round-trip
1434 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1435 od = OrderedDict(pairs)
1436 update_test = OrderedDict()
1437 update_test.update(od)
Ezio Melotti0cb2aaf2013-07-07 13:37:20 +02001438 for label, dup in [
1439 ('od.copy()', od.copy()),
1440 ('copy.copy(od)', copy.copy(od)),
1441 ('copy.deepcopy(od)', copy.deepcopy(od)),
1442 ('pickle.loads(pickle.dumps(od, 0))',
1443 pickle.loads(pickle.dumps(od, 0))),
1444 ('pickle.loads(pickle.dumps(od, 1))',
1445 pickle.loads(pickle.dumps(od, 1))),
1446 ('pickle.loads(pickle.dumps(od, 2))',
1447 pickle.loads(pickle.dumps(od, 2))),
1448 ('pickle.loads(pickle.dumps(od, 3))',
1449 pickle.loads(pickle.dumps(od, 3))),
1450 ('pickle.loads(pickle.dumps(od, -1))',
1451 pickle.loads(pickle.dumps(od, -1))),
1452 ('eval(repr(od))', eval(repr(od))),
1453 ('update_test', update_test),
1454 ('OrderedDict(od)', OrderedDict(od)),
1455 ]:
1456 with self.subTest(label=label):
1457 msg = "\ncopy: %s\nod: %s" % (dup, od)
1458 self.assertIsNot(dup, od, msg)
1459 self.assertEqual(dup, od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001460
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001461 def test_yaml_linkage(self):
1462 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1463 # In yaml, lists are native but tuples are not.
1464 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1465 od = OrderedDict(pairs)
1466 # yaml.dump(od) -->
1467 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001468 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001469
Raymond Hettingerb2121572009-03-03 22:50:04 +00001470 def test_reduce_not_too_fat(self):
1471 # do not save instance dictionary if not needed
1472 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1473 od = OrderedDict(pairs)
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001474 self.assertIsNone(od.__reduce__()[2])
Raymond Hettingerb2121572009-03-03 22:50:04 +00001475 od.x = 10
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001476 self.assertIsNotNone(od.__reduce__()[2])
1477
1478 def test_pickle_recursive(self):
1479 od = OrderedDict()
1480 od[1] = od
1481 for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
1482 dup = pickle.loads(pickle.dumps(od, proto))
1483 self.assertIsNot(dup, od)
1484 self.assertEqual(list(dup.keys()), [1])
1485 self.assertIs(dup[1], dup)
Raymond Hettingerb2121572009-03-03 22:50:04 +00001486
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001487 def test_repr(self):
1488 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1489 self.assertEqual(repr(od),
1490 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1491 self.assertEqual(eval(repr(od)), od)
1492 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1493
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001494 def test_repr_recursive(self):
1495 # See issue #9826
1496 od = OrderedDict.fromkeys('abc')
1497 od['x'] = od
1498 self.assertEqual(repr(od),
1499 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1500
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001501 def test_setdefault(self):
1502 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1503 shuffle(pairs)
1504 od = OrderedDict(pairs)
1505 pair_order = list(od.items())
1506 self.assertEqual(od.setdefault('a', 10), 3)
1507 # make sure order didn't change
1508 self.assertEqual(list(od.items()), pair_order)
1509 self.assertEqual(od.setdefault('x', 10), 10)
1510 # make sure 'x' is added to the end
1511 self.assertEqual(list(od.items())[-1], ('x', 10))
1512
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001513 # make sure setdefault still works when __missing__ is defined
1514 class Missing(OrderedDict):
1515 def __missing__(self, key):
1516 return 0
1517 self.assertEqual(Missing().setdefault(5, 9), 9)
1518
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001519 def test_reinsert(self):
1520 # Given insert a, insert b, delete a, re-insert a,
1521 # verify that a is now later than b.
1522 od = OrderedDict()
1523 od['a'] = 1
1524 od['b'] = 2
1525 del od['a']
1526 od['a'] = 1
1527 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1528
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001529 def test_move_to_end(self):
1530 od = OrderedDict.fromkeys('abcde')
1531 self.assertEqual(list(od), list('abcde'))
1532 od.move_to_end('c')
1533 self.assertEqual(list(od), list('abdec'))
1534 od.move_to_end('c', 0)
1535 self.assertEqual(list(od), list('cabde'))
1536 od.move_to_end('c', 0)
1537 self.assertEqual(list(od), list('cabde'))
1538 od.move_to_end('e')
1539 self.assertEqual(list(od), list('cabde'))
1540 with self.assertRaises(KeyError):
1541 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001542
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001543 def test_sizeof(self):
1544 # Wimpy test: Just verify the reported size is larger than a regular dict
1545 d = dict(a=1)
1546 od = OrderedDict(**d)
1547 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1548
Raymond Hettinger32062e92011-01-01 22:38:00 +00001549 def test_override_update(self):
1550 # Verify that subclasses can override update() without breaking __init__()
1551 class MyOD(OrderedDict):
1552 def update(self, *args, **kwds):
1553 raise Exception()
1554 items = [('a', 1), ('c', 3), ('b', 2)]
1555 self.assertEqual(list(MyOD(items).items()), items)
1556
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001557class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1558 type2test = OrderedDict
1559
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001560 def test_popitem(self):
1561 d = self._empty_mapping()
1562 self.assertRaises(KeyError, d.popitem)
1563
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001564class MyOrderedDict(OrderedDict):
1565 pass
1566
1567class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1568 type2test = MyOrderedDict
1569
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001570 def test_popitem(self):
1571 d = self._empty_mapping()
1572 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001573
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001574class TestUserDict(unittest.TestCase):
1575
1576 def test_init(self):
1577 self.assertEqual(list(UserDict(self=42).items()), [('self', 42)])
1578 self.assertEqual(list(UserDict(dict=42).items()), [('dict', 42)])
1579 self.assertEqual(list(UserDict(dict=None).items()), [('dict', None)])
1580 self.assertRaises(TypeError, UserDict, 42)
1581 self.assertRaises(TypeError, UserDict, (), ())
1582 self.assertRaises(TypeError, UserDict.__init__)
1583
1584 def test_update(self):
1585 d = UserDict()
1586 d.update(self=42)
1587 self.assertEqual(list(d.items()), [('self', 42)])
1588 self.assertRaises(TypeError, UserDict().update, 42)
1589 self.assertRaises(TypeError, UserDict().update, {}, {})
1590 self.assertRaises(TypeError, UserDict.update)
1591
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001592
Raymond Hettinger499e1932011-02-23 07:56:53 +00001593################################################################################
1594### Run tests
1595################################################################################
1596
Christian Heimes25bb7832008-01-11 16:17:00 +00001597import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001598
Guido van Rossumd8faa362007-04-27 19:54:29 +00001599def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001600 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001601 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001602 TestCollectionABCs, TestCounter, TestChainMap,
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001603 TestOrderedDict, GeneralMappingTests, SubclassMappingTests,
1604 TestUserDict,]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001605 support.run_unittest(*test_classes)
1606 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001607
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001608
Guido van Rossumd8faa362007-04-27 19:54:29 +00001609if __name__ == "__main__":
1610 test_main(verbose=True)