blob: 66db90f993f1416a770469f6a839cff441d01ace [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00003import unittest, doctest, operator
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -07004from test.support import TESTFN, forget, unlink
Raymond Hettinger2d32f632009-03-02 21:24:57 +00005import inspect
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006from test import support
Raymond Hettinger426e0522011-01-03 02:12:02 +00007from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger2d32f632009-03-02 21:24:57 +00008from test import mapping_tests
Georg Brandlc28e1fa2008-06-10 19:20:26 +00009import pickle, copy
Raymond Hettinger2d32f632009-03-02 21:24:57 +000010from random import randrange, shuffle
Raymond Hettinger499b2ee2009-05-27 01:53:46 +000011import keyword
12import re
R. David Murray378c0cf2010-02-24 01:46:21 +000013import sys
Raymond Hettinger57d1a882011-02-23 00:46:28 +000014from collections import UserDict
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000015from collections import ChainMap
Raymond Hettinger57d1a882011-02-23 00:46:28 +000016from collections.abc import Hashable, Iterable, Iterator
17from collections.abc import Sized, Container, Callable
18from collections.abc import Set, MutableSet
19from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
20from collections.abc import Sequence, MutableSequence
21from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000022
Raymond Hettinger499e1932011-02-23 07:56:53 +000023
24################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000025### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000026################################################################################
27
28class TestChainMap(unittest.TestCase):
29
30 def test_basics(self):
31 c = ChainMap()
32 c['a'] = 1
33 c['b'] = 2
34 d = c.new_child()
35 d['b'] = 20
36 d['c'] = 30
37 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
38 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
39 self.assertEqual(len(d), 3) # check len
40 for key in 'abc': # check contains
41 self.assertIn(key, d)
42 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
43 self.assertEqual(d.get(k, 100), v)
44
45 del d['b'] # unmask a value
46 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
47 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
48 self.assertEqual(len(d), 3) # check len
49 for key in 'abc': # check contains
50 self.assertIn(key, d)
51 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
52 self.assertEqual(d.get(k, 100), v)
53 self.assertIn(repr(d), [ # check repr
54 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
55 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
56 ])
57
58 for e in d.copy(), copy.copy(d): # check shallow copies
59 self.assertEqual(d, e)
60 self.assertEqual(d.maps, e.maps)
61 self.assertIsNot(d, e)
62 self.assertIsNot(d.maps[0], e.maps[0])
63 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
64 self.assertIs(m1, m2)
65
Serhiy Storchakabad12572014-12-15 14:03:42 +020066 # check deep copies
67 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
68 e = pickle.loads(pickle.dumps(d, proto))
69 self.assertEqual(d, e)
70 self.assertEqual(d.maps, e.maps)
71 self.assertIsNot(d, e)
72 for m1, m2 in zip(d.maps, e.maps):
73 self.assertIsNot(m1, m2, e)
74 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +000075 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +020076 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +000077 self.assertEqual(d, e)
78 self.assertEqual(d.maps, e.maps)
79 self.assertIsNot(d, e)
80 for m1, m2 in zip(d.maps, e.maps):
81 self.assertIsNot(m1, m2, e)
82
Raymond Hettingerd0321312011-02-26 06:53:58 +000083 f = d.new_child()
84 f['b'] = 5
85 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
86 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
87 self.assertEqual(f['b'], 5) # find first in chain
88 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +000089
90 def test_contructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +000091 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +000092 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
93
Raymond Hettingerd0321312011-02-26 06:53:58 +000094 def test_bool(self):
95 self.assertFalse(ChainMap())
96 self.assertFalse(ChainMap({}, {}))
97 self.assertTrue(ChainMap({1:2}, {}))
98 self.assertTrue(ChainMap({}, {1:2}))
99
Raymond Hettinger499e1932011-02-23 07:56:53 +0000100 def test_missing(self):
101 class DefaultChainMap(ChainMap):
102 def __missing__(self, key):
103 return 999
104 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
105 for k, v in dict(a=1, b=2, c=30, d=999).items():
106 self.assertEqual(d[k], v) # check __getitem__ w/missing
107 for k, v in dict(a=1, b=2, c=30, d=77).items():
108 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
109 for k, v in dict(a=True, b=True, c=True, d=False).items():
110 self.assertEqual(k in d, v) # check __contains__ w/missing
111 self.assertEqual(d.pop('a', 1001), 1, d)
112 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
113 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
114 with self.assertRaises(KeyError):
115 d.popitem()
116
117 def test_dict_coercion(self):
118 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
119 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
120 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
121
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000122 def test_new_child(self):
123 'Tests for changes for issue #16613.'
124 c = ChainMap()
125 c['a'] = 1
126 c['b'] = 2
127 m = {'b':20, 'c': 30}
128 d = c.new_child(m)
129 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
130 self.assertIs(m, d.maps[0])
131
132 # Use a different map than a dict
133 class lowerdict(dict):
134 def __getitem__(self, key):
135 if isinstance(key, str):
136 key = key.lower()
137 return dict.__getitem__(self, key)
138 def __contains__(self, key):
139 if isinstance(key, str):
140 key = key.lower()
141 return dict.__contains__(self, key)
142
143 c = ChainMap()
144 c['a'] = 1
145 c['b'] = 2
146 m = lowerdict(b=20, c=30)
147 d = c.new_child(m)
148 self.assertIs(m, d.maps[0])
149 for key in 'abc': # check contains
150 self.assertIn(key, d)
151 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
152 self.assertEqual(d.get(k, 100), v)
153
Raymond Hettinger499e1932011-02-23 07:56:53 +0000154
155################################################################################
156### Named Tuples
157################################################################################
158
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000159TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000160
161class TestNamedTuple(unittest.TestCase):
162
163 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000164 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000165 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000166 self.assertEqual(Point.__slots__, ())
167 self.assertEqual(Point.__module__, __name__)
168 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000169 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettinger2ebea412011-03-23 12:52:23 -0700170 self.assertIn('class Point(tuple)', Point._source)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000171
172 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
173 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
174 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
175
176 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
177 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
178 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000179 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000180 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
181
182 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000183 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000184
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000185 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000186 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000187 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000188 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000189
Christian Heimesfaf2f632008-01-06 16:59:19 +0000190 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
191 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
192
R. David Murray378c0cf2010-02-24 01:46:21 +0000193 @unittest.skipIf(sys.flags.optimize >= 2,
194 "Docstrings are omitted with -O2 and above")
195 def test_factory_doc_attr(self):
196 Point = namedtuple('Point', 'x y')
197 self.assertEqual(Point.__doc__, 'Point(x, y)')
198
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000199 def test_name_fixer(self):
200 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000201 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
202 [('abc', 'class'), ('abc', '_1')], # field has keyword
203 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
204 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
205 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
206 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000207 ]:
208 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
209
Guido van Rossumd8faa362007-04-27 19:54:29 +0000210 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000211 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000212 p = Point(11, 22)
213 self.assertEqual(p, Point(x=11, y=22))
214 self.assertEqual(p, Point(11, y=22))
215 self.assertEqual(p, Point(y=22, x=11))
216 self.assertEqual(p, Point(*(11, 22)))
217 self.assertEqual(p, Point(**dict(x=11, y=22)))
218 self.assertRaises(TypeError, Point, 1) # too few args
219 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
220 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
221 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
222 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000223 self.assertNotIn('__weakref__', dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000224 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +0000225 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
226 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
Raymond Hettinger163e9822013-05-18 00:05:20 -0700227 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000228
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000229 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000230 p._replace(x=1, error=2)
231 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000232 pass
233 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000234 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000235
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000236 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000237 Point = namedtuple('Point', 'x, y')
238 p = Point(x=11, y=22)
239 self.assertEqual(repr(p), 'Point(x=11, y=22)')
240
241 # verify that fieldspec can be a non-string sequence
242 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000243 p = Point(x=11, y=22)
244 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000245
246 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000247 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000248 p = Point(11, 22)
249
Ezio Melottie9615932010-01-24 19:26:24 +0000250 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000251 self.assertEqual(p, (11, 22)) # matches a real tuple
252 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
253 self.assertEqual(list(p), [11, 22]) # coercable to a list
254 self.assertEqual(max(p), 22) # iterable
255 self.assertEqual(max(*p), 22) # star-able
256 x, y = p
257 self.assertEqual(p, (x, y)) # unpacks like a tuple
258 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
259 self.assertRaises(IndexError, p.__getitem__, 3)
260
261 self.assertEqual(p.x, x)
262 self.assertEqual(p.y, y)
263 self.assertRaises(AttributeError, eval, 'p.z', locals())
264
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000265 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000266 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000267 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000268 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000269 self.assertEqual(repr(Zero()), 'Zero()')
270 self.assertEqual(Zero()._asdict(), {})
271 self.assertEqual(Zero()._fields, ())
272
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000273 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000274 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000275 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000276 self.assertEqual(Dot(1).d, 1)
277 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
278 self.assertEqual(Dot(1)._asdict(), {'d':1})
279 self.assertEqual(Dot(1)._replace(d=999), (999,))
280 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000281
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000282 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000283 n = 254 # SyntaxError: more than 255 arguments:
284 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000285 names = list(set(''.join([random.choice(string.ascii_letters)
286 for j in range(10)]) for i in range(n)))
287 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000288 Big = namedtuple('Big', names)
289 b = Big(*range(n))
290 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000291 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000292 for pos, name in enumerate(names):
293 self.assertEqual(getattr(b, name), pos)
294 repr(b) # make sure repr() doesn't blow-up
295 d = b._asdict()
296 d_expected = dict(zip(names, range(n)))
297 self.assertEqual(d, d_expected)
298 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
299 b2_expected = list(range(n))
300 b2_expected[1] = 999
301 b2_expected[-5] = 42
302 self.assertEqual(b2, tuple(b2_expected))
303 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000304
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000305 def test_pickle(self):
306 p = TestNT(x=10, y=20, z=30)
307 for module in (pickle,):
308 loads = getattr(module, 'loads')
309 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500310 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000311 q = loads(dumps(p, protocol))
312 self.assertEqual(p, q)
313 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700314 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000315
316 def test_copy(self):
317 p = TestNT(x=10, y=20, z=30)
318 for copier in copy.copy, copy.deepcopy:
319 q = copier(p)
320 self.assertEqual(p, q)
321 self.assertEqual(p._fields, q._fields)
322
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000323 def test_name_conflicts(self):
324 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
325 # failed when used as field names. Test to make sure these now work.
326 T = namedtuple('T', 'itemgetter property self cls tuple')
327 t = T(1, 2, 3, 4, 5)
328 self.assertEqual(t, (1,2,3,4,5))
329 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
330 self.assertEqual(newt, (10,20,30,40,50))
331
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000332 # Broader test of all interesting names in a template
333 with support.captured_stdout() as template:
334 T = namedtuple('T', 'x', verbose=True)
335 words = set(re.findall('[A-Za-z]+', template.getvalue()))
336 words -= set(keyword.kwlist)
337 T = namedtuple('T', words)
338 # test __new__
339 values = tuple(range(len(words)))
340 t = T(*values)
341 self.assertEqual(t, values)
342 t = T(**dict(zip(T._fields, values)))
343 self.assertEqual(t, values)
344 # test _make
345 t = T._make(values)
346 self.assertEqual(t, values)
347 # exercise __repr__
348 repr(t)
349 # test _asdict
350 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
351 # test _replace
352 t = T._make(values)
353 newvalues = tuple(v*10 for v in values)
354 newt = t._replace(**dict(zip(T._fields, newvalues)))
355 self.assertEqual(newt, newvalues)
356 # test _fields
357 self.assertEqual(T._fields, tuple(words))
358 # test __getnewargs__
359 self.assertEqual(t.__getnewargs__(), values)
360
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000361 def test_repr(self):
362 with support.captured_stdout() as template:
363 A = namedtuple('A', 'x', verbose=True)
364 self.assertEqual(repr(A(1)), 'A(x=1)')
365 # repr should show the name of the subclass
366 class B(A):
367 pass
368 self.assertEqual(repr(B(1)), 'B(x=1)')
369
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700370 def test_source(self):
371 # verify that _source can be run through exec()
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700372 tmp = namedtuple('NTColor', 'red green blue')
373 globals().pop('NTColor', None) # remove artifacts from other tests
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700374 exec(tmp._source, globals())
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700375 self.assertIn('NTColor', globals())
376 c = NTColor(10, 20, 30)
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700377 self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
Raymond Hettingerd4652fa2011-03-24 09:45:43 -0700378 self.assertEqual(NTColor._fields, ('red', 'green', 'blue'))
379 globals().pop('NTColor', None) # clean-up after this test
Raymond Hettingerf6d3e8e2011-03-23 20:33:30 -0700380
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000381
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700382 def test_namedtuple_subclass_issue_24931(self):
383 class Point(namedtuple('_Point', ['x', 'y'])):
384 pass
385
386 a = Point(3, 4)
387 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
388
389 a.w = 5
390 self.assertEqual(a.__dict__, {'w': 5})
391
392
Raymond Hettinger499e1932011-02-23 07:56:53 +0000393################################################################################
394### Abstract Base Classes
395################################################################################
396
Raymond Hettingerae650182009-01-28 23:33:59 +0000397class ABCTestCase(unittest.TestCase):
398
399 def validate_abstract_methods(self, abc, *names):
400 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
401
402 # everything should work will all required methods are present
403 C = type('C', (abc,), methodstubs)
404 C()
405
406 # instantiation should fail if a required method is missing
407 for name in names:
408 stubs = methodstubs.copy()
409 del stubs[name]
410 C = type('C', (abc,), stubs)
411 self.assertRaises(TypeError, C, name)
412
Florent Xiclunace153f62010-03-08 15:34:35 +0000413 def validate_isinstance(self, abc, name):
414 stub = lambda s, *args: 0
415
416 C = type('C', (object,), {'__hash__': None})
417 setattr(C, name, stub)
418 self.assertIsInstance(C(), abc)
419 self.assertTrue(issubclass(C, abc))
420
421 C = type('C', (object,), {'__hash__': None})
422 self.assertNotIsInstance(C(), abc)
423 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000424
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000425 def validate_comparison(self, instance):
426 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
427 operators = {}
428 for op in ops:
429 name = '__' + op + '__'
430 operators[name] = getattr(operator, name)
431
432 class Other:
433 def __init__(self):
434 self.right_side = False
435 def __eq__(self, other):
436 self.right_side = True
437 return True
438 __lt__ = __eq__
439 __gt__ = __eq__
440 __le__ = __eq__
441 __ge__ = __eq__
442 __ne__ = __eq__
443 __ror__ = __eq__
444 __rand__ = __eq__
445 __rxor__ = __eq__
446 __rsub__ = __eq__
447
448 for name, op in operators.items():
449 if not hasattr(instance, name):
450 continue
451 other = Other()
452 op(instance, other)
453 self.assertTrue(other.right_side,'Right side not called for %s.%s'
454 % (type(instance), name))
455
Raymond Hettingerae650182009-01-28 23:33:59 +0000456class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000457
458 def test_Hashable(self):
459 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000460 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000461 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000462 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000463 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000464 # Check some hashables
465 samples = [None,
466 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000467 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000468 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000469 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000470 ]
471 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000472 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000473 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000474 self.assertRaises(TypeError, Hashable)
475 # Check direct subclassing
476 class H(Hashable):
477 def __hash__(self):
478 return super().__hash__()
479 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000480 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000481 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000482 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000483
484 def test_Iterable(self):
485 # Check some non-iterables
486 non_samples = [None, 42, 3.14, 1j]
487 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000488 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000489 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000490 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000491 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000492 tuple(), list(), set(), frozenset(), dict(),
493 dict().keys(), dict().items(), dict().values(),
494 (lambda: (yield))(),
495 (x for x in []),
496 ]
497 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000498 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000499 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000500 # Check direct subclassing
501 class I(Iterable):
502 def __iter__(self):
503 return super().__iter__()
504 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000505 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000506 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000507 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000508
509 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000510 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000511 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000512 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000513 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000514 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000515 iter(tuple()), iter(list()), iter(dict()),
516 iter(set()), iter(frozenset()),
517 iter(dict().keys()), iter(dict().items()),
518 iter(dict().values()),
519 (lambda: (yield))(),
520 (x for x in []),
521 ]
522 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000523 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000524 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +0000525 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
526
527 # Issue 10565
528 class NextOnly:
529 def __next__(self):
530 yield 1
531 raise StopIteration
532 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000533
534 def test_Sized(self):
535 non_samples = [None, 42, 3.14, 1j,
536 (lambda: (yield))(),
537 (x for x in []),
538 ]
539 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000540 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000541 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000542 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000543 tuple(), list(), set(), frozenset(), dict(),
544 dict().keys(), dict().items(), dict().values(),
545 ]
546 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000547 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000548 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000549 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000550 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000551
552 def test_Container(self):
553 non_samples = [None, 42, 3.14, 1j,
554 (lambda: (yield))(),
555 (x for x in []),
556 ]
557 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000558 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000559 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000560 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000561 tuple(), list(), set(), frozenset(), dict(),
562 dict().keys(), dict().items(),
563 ]
564 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000565 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000566 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000567 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000568 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000569
570 def test_Callable(self):
571 non_samples = [None, 42, 3.14, 1j,
572 "", b"", (), [], {}, set(),
573 (lambda: (yield))(),
574 (x for x in []),
575 ]
576 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000577 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000578 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000579 samples = [lambda: None,
580 type, int, object,
581 len,
582 list.append, [].append,
583 ]
584 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000585 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000586 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +0000587 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000588 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000589
590 def test_direct_subclassing(self):
591 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
592 class C(B):
593 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000594 self.assertTrue(issubclass(C, B))
595 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000596
597 def test_registration(self):
598 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
599 class C:
600 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000601 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000602 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000603 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000604
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000605class WithSet(MutableSet):
606
607 def __init__(self, it=()):
608 self.data = set(it)
609
610 def __len__(self):
611 return len(self.data)
612
613 def __iter__(self):
614 return iter(self.data)
615
616 def __contains__(self, item):
617 return item in self.data
618
619 def add(self, item):
620 self.data.add(item)
621
622 def discard(self, item):
623 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000624
Raymond Hettingerae650182009-01-28 23:33:59 +0000625class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000626
627 # XXX For now, we only test some virtual inheritance properties.
628 # We should also test the proper behavior of the collection ABCs
629 # as real base classes or mix-in classes.
630
631 def test_Set(self):
632 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +0000633 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000634 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +0000635 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000636 class MySet(Set):
637 def __contains__(self, x):
638 return False
639 def __len__(self):
640 return 0
641 def __iter__(self):
642 return iter([])
643 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000644
Benjamin Peterson41181742008-07-02 20:22:54 +0000645 def test_hash_Set(self):
646 class OneTwoThreeSet(Set):
647 def __init__(self):
648 self.contents = [1, 2, 3]
649 def __contains__(self, x):
650 return x in self.contents
651 def __len__(self):
652 return len(self.contents)
653 def __iter__(self):
654 return iter(self.contents)
655 def __hash__(self):
656 return self._hash()
657 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000658 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +0000659
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000660 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +0000661 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000662 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +0000663 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000664 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +0000665 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
666 'add', 'discard')
667
Raymond Hettinger3f10a952009-04-01 19:05:50 +0000668 def test_issue_5647(self):
669 # MutableSet.__iand__ mutated the set during iteration
670 s = WithSet('abcd')
671 s &= WithSet('cdef') # This used to fail
672 self.assertEqual(set(s), set('cd'))
673
Raymond Hettingerae650182009-01-28 23:33:59 +0000674 def test_issue_4920(self):
675 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000676 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +0000677 __slots__=['__s']
678 def __init__(self,items=None):
679 if items is None:
680 items=[]
681 self.__s=set(items)
682 def __contains__(self,v):
683 return v in self.__s
684 def __iter__(self):
685 return iter(self.__s)
686 def __len__(self):
687 return len(self.__s)
688 def add(self,v):
689 result=v not in self.__s
690 self.__s.add(v)
691 return result
692 def discard(self,v):
693 result=v in self.__s
694 self.__s.discard(v)
695 return result
696 def __repr__(self):
697 return "MySet(%s)" % repr(list(self))
698 s = MySet([5,43,2,1])
699 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000700
Daniel Stutzbach31da5b22010-08-24 20:49:57 +0000701 def test_issue8750(self):
702 empty = WithSet()
703 full = WithSet(range(10))
704 s = WithSet(full)
705 s -= s
706 self.assertEqual(s, empty)
707 s = WithSet(full)
708 s ^= s
709 self.assertEqual(s, empty)
710 s = WithSet(full)
711 s &= s
712 self.assertEqual(s, full)
713 s |= s
714 self.assertEqual(s, full)
715
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200716 def test_issue16373(self):
717 # Recursion error comparing comparable and noncomparable
718 # Set instances
719 class MyComparableSet(Set):
720 def __contains__(self, x):
721 return False
722 def __len__(self):
723 return 0
724 def __iter__(self):
725 return iter([])
726 class MyNonComparableSet(Set):
727 def __contains__(self, x):
728 return False
729 def __len__(self):
730 return 0
731 def __iter__(self):
732 return iter([])
733 def __le__(self, x):
734 return NotImplemented
735 def __lt__(self, x):
736 return NotImplemented
737
738 cs = MyComparableSet()
739 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700740 self.assertFalse(ncs < cs)
741 self.assertTrue(ncs <= cs)
742 self.assertFalse(ncs > cs)
743 self.assertTrue(ncs >= cs)
744
745 def assertSameSet(self, s1, s2):
746 # coerce both to a real set then check equality
747 self.assertSetEqual(set(s1), set(s2))
748
749 def test_Set_interoperability_with_real_sets(self):
750 # Issue: 8743
751 class ListSet(Set):
752 def __init__(self, elements=()):
753 self.data = []
754 for elem in elements:
755 if elem not in self.data:
756 self.data.append(elem)
757 def __contains__(self, elem):
758 return elem in self.data
759 def __iter__(self):
760 return iter(self.data)
761 def __len__(self):
762 return len(self.data)
763 def __repr__(self):
764 return 'Set({!r})'.format(self.data)
765
766 r1 = set('abc')
767 r2 = set('bcd')
768 r3 = set('abcde')
769 f1 = ListSet('abc')
770 f2 = ListSet('bcd')
771 f3 = ListSet('abcde')
772 l1 = list('abccba')
773 l2 = list('bcddcb')
774 l3 = list('abcdeedcba')
775
776 target = r1 & r2
777 self.assertSameSet(f1 & f2, target)
778 self.assertSameSet(f1 & r2, target)
779 self.assertSameSet(r2 & f1, target)
780 self.assertSameSet(f1 & l2, 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 fwd_target = r1 - r2
789 rev_target = r2 - r1
790 self.assertSameSet(f1 - f2, fwd_target)
791 self.assertSameSet(f2 - f1, rev_target)
792 self.assertSameSet(f1 - r2, fwd_target)
793 self.assertSameSet(f2 - r1, rev_target)
794 self.assertSameSet(r1 - f2, fwd_target)
795 self.assertSameSet(r2 - f1, rev_target)
796 self.assertSameSet(f1 - l2, fwd_target)
797 self.assertSameSet(f2 - l1, rev_target)
798
799 target = r1 ^ r2
800 self.assertSameSet(f1 ^ f2, target)
801 self.assertSameSet(f1 ^ r2, target)
802 self.assertSameSet(r2 ^ f1, target)
803 self.assertSameSet(f1 ^ l2, target)
804
805 # Don't change the following to use assertLess or other
806 # "more specific" unittest assertions. The current
807 # assertTrue/assertFalse style makes the pattern of test
808 # case combinations clear and allows us to know for sure
809 # the exact operator being invoked.
810
811 # proper subset
812 self.assertTrue(f1 < f3)
813 self.assertFalse(f1 < f1)
814 self.assertFalse(f1 < f2)
815 self.assertTrue(r1 < f3)
816 self.assertFalse(r1 < f1)
817 self.assertFalse(r1 < f2)
818 self.assertTrue(r1 < r3)
819 self.assertFalse(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
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200823 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700824 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200825 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700826 f1 < l2
827
828 # any subset
829 self.assertTrue(f1 <= f3)
830 self.assertTrue(f1 <= f1)
831 self.assertFalse(f1 <= f2)
832 self.assertTrue(r1 <= f3)
833 self.assertTrue(r1 <= f1)
834 self.assertFalse(r1 <= f2)
835 self.assertTrue(r1 <= r3)
836 self.assertTrue(r1 <= r1)
837 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200838 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -0700839 f1 <= l3
840 with self.assertRaises(TypeError):
841 f1 <= l1
842 with self.assertRaises(TypeError):
843 f1 <= l2
844
845 # proper superset
846 self.assertTrue(f3 > f1)
847 self.assertFalse(f1 > f1)
848 self.assertFalse(f2 > f1)
849 self.assertTrue(r3 > r1)
850 self.assertFalse(f1 > r1)
851 self.assertFalse(f2 > r1)
852 self.assertTrue(r3 > r1)
853 self.assertFalse(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 # any superset
863 self.assertTrue(f3 >= f1)
864 self.assertTrue(f1 >= f1)
865 self.assertFalse(f2 >= f1)
866 self.assertTrue(r3 >= r1)
867 self.assertTrue(f1 >= r1)
868 self.assertFalse(f2 >= r1)
869 self.assertTrue(r3 >= r1)
870 self.assertTrue(r1 >= r1)
871 self.assertFalse(r2 >= r1)
872 with self.assertRaises(TypeError):
873 f1 >= l3
874 with self.assertRaises(TypeError):
875 f1 >=l1
876 with self.assertRaises(TypeError):
877 f1 >= l2
878
879 # equality
880 self.assertTrue(f1 == f1)
881 self.assertTrue(r1 == f1)
882 self.assertTrue(f1 == r1)
883 self.assertFalse(f1 == f3)
884 self.assertFalse(r1 == f3)
885 self.assertFalse(f1 == r3)
886 self.assertFalse(f1 == l3)
887 self.assertFalse(f1 == l1)
888 self.assertFalse(f1 == l2)
889
890 # inequality
891 self.assertFalse(f1 != f1)
892 self.assertFalse(r1 != f1)
893 self.assertFalse(f1 != r1)
894 self.assertTrue(f1 != f3)
895 self.assertTrue(r1 != f3)
896 self.assertTrue(f1 != r3)
897 self.assertTrue(f1 != l3)
898 self.assertTrue(f1 != l1)
899 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +0200900
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000901 def test_Mapping(self):
902 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000903 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000904 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000905 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
906 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +0000907 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000908 def __len__(self):
909 return 0
910 def __getitem__(self, i):
911 raise IndexError
912 def __iter__(self):
913 return iter(())
914 self.validate_comparison(MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000915
916 def test_MutableMapping(self):
917 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +0000918 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000919 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +0000920 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
921 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000922
Raymond Hettinger9117c752010-08-22 07:44:24 +0000923 def test_MutableMapping_subclass(self):
924 # Test issue 9214
925 mymap = UserDict()
926 mymap['red'] = 5
927 self.assertIsInstance(mymap.keys(), Set)
928 self.assertIsInstance(mymap.keys(), KeysView)
929 self.assertIsInstance(mymap.items(), Set)
930 self.assertIsInstance(mymap.items(), ItemsView)
931
932 mymap = UserDict()
933 mymap['red'] = 5
934 z = mymap.keys() | {'orange'}
935 self.assertIsInstance(z, set)
936 list(z)
937 mymap['blue'] = 7 # Shouldn't affect 'z'
938 self.assertEqual(sorted(z), ['orange', 'red'])
939
940 mymap = UserDict()
941 mymap['red'] = 5
942 z = mymap.items() | {('orange', 3)}
943 self.assertIsInstance(z, set)
944 list(z)
945 mymap['blue'] = 7 # Shouldn't affect 'z'
946 self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
947
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000948 def test_Sequence(self):
949 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +0000950 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000951 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +0000952 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000953 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +1000954 self.assertIsInstance(memoryview(b""), Sequence)
955 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000956 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000957 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
958 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000959
Guido van Rossumd05eb002007-11-21 22:26:24 +0000960 def test_ByteString(self):
961 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000962 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000963 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000964 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +0000965 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000966 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +0000967 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000968 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000969
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000970 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000971 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +0000972 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000973 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000974 for sample in [list, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +0000975 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000976 self.assertTrue(issubclass(sample, MutableSequence))
977 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +0000978 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
979 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000980
Eli Bendersky0716a572011-03-04 10:38:14 +0000981 def test_MutableSequence_mixins(self):
982 # Test the mixins of MutableSequence by creating a miminal concrete
983 # class inherited from it.
984 class MutableSequenceSubclass(MutableSequence):
985 def __init__(self):
986 self.lst = []
987
988 def __setitem__(self, index, value):
989 self.lst[index] = value
990
991 def __getitem__(self, index):
992 return self.lst[index]
993
994 def __len__(self):
995 return len(self.lst)
996
997 def __delitem__(self, index):
998 del self.lst[index]
999
1000 def insert(self, index, value):
1001 self.lst.insert(index, value)
1002
1003 mss = MutableSequenceSubclass()
1004 mss.append(0)
1005 mss.extend((1, 2, 3, 4))
1006 self.assertEqual(len(mss), 5)
1007 self.assertEqual(mss[3], 3)
1008 mss.reverse()
1009 self.assertEqual(mss[3], 1)
1010 mss.pop()
1011 self.assertEqual(len(mss), 4)
1012 mss.remove(3)
1013 self.assertEqual(len(mss), 3)
1014 mss += (10, 20, 30)
1015 self.assertEqual(len(mss), 6)
1016 self.assertEqual(mss[-1], 30)
1017 mss.clear()
1018 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001019
1020################################################################################
1021### Counter
1022################################################################################
1023
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001024class CounterSubclassWithSetItem(Counter):
1025 # Test a counter subclass that overrides __setitem__
1026 def __init__(self, *args, **kwds):
1027 self.called = False
1028 Counter.__init__(self, *args, **kwds)
1029 def __setitem__(self, key, value):
1030 self.called = True
1031 Counter.__setitem__(self, key, value)
1032
1033class CounterSubclassWithGet(Counter):
1034 # Test a counter subclass that overrides get()
1035 def __init__(self, *args, **kwds):
1036 self.called = False
1037 Counter.__init__(self, *args, **kwds)
1038 def get(self, key, default):
1039 self.called = True
1040 return Counter.get(self, key, default)
1041
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001042class TestCounter(unittest.TestCase):
1043
1044 def test_basics(self):
1045 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001046 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1047 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001048 self.assertIsInstance(c, dict)
1049 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001050 self.assertTrue(issubclass(Counter, dict))
1051 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001052 self.assertEqual(len(c), 3)
1053 self.assertEqual(sum(c.values()), 6)
1054 self.assertEqual(sorted(c.values()), [1, 2, 3])
1055 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
1056 self.assertEqual(sorted(c), ['a', 'b', 'c'])
1057 self.assertEqual(sorted(c.items()),
1058 [('a', 3), ('b', 2), ('c', 1)])
1059 self.assertEqual(c['b'], 2)
1060 self.assertEqual(c['z'], 0)
1061 self.assertEqual(c.__contains__('c'), True)
1062 self.assertEqual(c.__contains__('z'), False)
1063 self.assertEqual(c.get('b', 10), 2)
1064 self.assertEqual(c.get('z', 10), 10)
1065 self.assertEqual(c, dict(a=3, b=2, c=1))
1066 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1067 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1068 for i in range(5):
1069 self.assertEqual(c.most_common(i),
1070 [('a', 3), ('b', 2), ('c', 1)][:i])
1071 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
1072 c['a'] += 1 # increment an existing value
1073 c['b'] -= 2 # sub existing value to zero
1074 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001075 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001076 c['d'] -= 2 # sub from a missing value
1077 c['e'] = -5 # directly assign a missing value
1078 c['f'] += 4 # add to a missing value
1079 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
1080 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
1081 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001082 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001083 for i in range(3):
1084 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001085 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001086 c.clear()
1087 self.assertEqual(c, {})
1088 self.assertEqual(repr(c), 'Counter()')
1089 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1090 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001091 c.update(dict(a=5, b=3))
1092 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001093 c.update(Counter('a' * 50 + 'b' * 30))
1094 c.update() # test case with no args
1095 c.__init__('a' * 500 + 'b' * 300)
1096 c.__init__('cdc')
1097 c.__init__()
1098 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1099 self.assertEqual(c.setdefault('d', 5), 1)
1100 self.assertEqual(c['d'], 1)
1101 self.assertEqual(c.setdefault('e', 5), 5)
1102 self.assertEqual(c['e'], 5)
1103
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001104 def test_init(self):
1105 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1106 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1107 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1108 self.assertRaises(TypeError, Counter, 42)
1109 self.assertRaises(TypeError, Counter, (), ())
1110 self.assertRaises(TypeError, Counter.__init__)
1111
1112 def test_update(self):
1113 c = Counter()
1114 c.update(self=42)
1115 self.assertEqual(list(c.items()), [('self', 42)])
1116 c = Counter()
1117 c.update(iterable=42)
1118 self.assertEqual(list(c.items()), [('iterable', 42)])
1119 c = Counter()
1120 c.update(iterable=None)
1121 self.assertEqual(list(c.items()), [('iterable', None)])
1122 self.assertRaises(TypeError, Counter().update, 42)
1123 self.assertRaises(TypeError, Counter().update, {}, {})
1124 self.assertRaises(TypeError, Counter.update)
1125
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001126 def test_copying(self):
1127 # Check that counters are copyable, deepcopyable, picklable, and
1128 #have a repr/eval round-trip
1129 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02001130 def check(dup):
1131 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1132 self.assertIsNot(dup, words, msg)
1133 self.assertEqual(dup, words)
1134 check(words.copy())
1135 check(copy.copy(words))
1136 check(copy.deepcopy(words))
1137 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1138 with self.subTest(proto=proto):
1139 check(pickle.loads(pickle.dumps(words, proto)))
1140 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001141 update_test = Counter()
1142 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001143 check(update_test)
1144 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001145
Raymond Hettinger1c746c22011-04-15 13:16:46 -07001146 def test_copy_subclass(self):
1147 class MyCounter(Counter):
1148 pass
1149 c = MyCounter('slartibartfast')
1150 d = c.copy()
1151 self.assertEqual(d, c)
1152 self.assertEqual(len(d), len(c))
1153 self.assertEqual(type(d), type(c))
1154
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001155 def test_conversions(self):
1156 # Convert to: set, list, dict
1157 s = 'she sells sea shells by the sea shore'
1158 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
1159 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
1160 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
1161 self.assertEqual(set(Counter(s)), set(s))
1162
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001163 def test_invariant_for_the_in_operator(self):
1164 c = Counter(a=10, b=-2, c=0)
1165 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001166 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00001167 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00001168
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001169 def test_multiset_operations(self):
1170 # Verify that adding a zero counter will strip zeros and negatives
1171 c = Counter(a=10, b=-2, c=0) + Counter()
1172 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001173
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001174 elements = 'abcd'
1175 for i in range(1000):
1176 # test random pairs of multisets
1177 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001178 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001179 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001180 q.update(h=1, i=-1, j=0)
1181 for counterop, numberop in [
1182 (Counter.__add__, lambda x, y: max(0, x+y)),
1183 (Counter.__sub__, lambda x, y: max(0, x-y)),
1184 (Counter.__or__, lambda x, y: max(0,x,y)),
1185 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001186 ]:
1187 result = counterop(p, q)
1188 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00001189 self.assertEqual(numberop(p[x], q[x]), result[x],
1190 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001191 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001192 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001193
1194 elements = 'abcdef'
1195 for i in range(100):
1196 # verify that random multisets with no repeats are exactly like sets
1197 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1198 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
1199 for counterop, setop in [
1200 (Counter.__sub__, set.__sub__),
1201 (Counter.__or__, set.__or__),
1202 (Counter.__and__, set.__and__),
1203 ]:
1204 counter_result = counterop(p, q)
1205 set_result = setop(set(p.elements()), set(q.elements()))
1206 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001207
Raymond Hettingerbecd5682011-10-19 13:40:37 -07001208 def test_inplace_operations(self):
1209 elements = 'abcd'
1210 for i in range(1000):
1211 # test random pairs of multisets
1212 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1213 p.update(e=1, f=-1, g=0)
1214 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
1215 q.update(h=1, i=-1, j=0)
1216 for inplace_op, regular_op in [
1217 (Counter.__iadd__, Counter.__add__),
1218 (Counter.__isub__, Counter.__sub__),
1219 (Counter.__ior__, Counter.__or__),
1220 (Counter.__iand__, Counter.__and__),
1221 ]:
1222 c = p.copy()
1223 c_id = id(c)
1224 regular_result = regular_op(c, q)
1225 inplace_result = inplace_op(c, q)
1226 self.assertEqual(inplace_result, regular_result)
1227 self.assertEqual(id(inplace_result), c_id)
1228
Raymond Hettinger9c01e442010-04-03 10:32:58 +00001229 def test_subtract(self):
1230 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1231 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
1232 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1233 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1234 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
1235 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
1236 c = Counter('aaabbcd')
1237 c.subtract('aaaabbcce')
1238 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001239
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001240 c = Counter()
1241 c.subtract(self=42)
1242 self.assertEqual(list(c.items()), [('self', -42)])
1243 c = Counter()
1244 c.subtract(iterable=42)
1245 self.assertEqual(list(c.items()), [('iterable', -42)])
1246 self.assertRaises(TypeError, Counter().subtract, 42)
1247 self.assertRaises(TypeError, Counter().subtract, {}, {})
1248 self.assertRaises(TypeError, Counter.subtract)
1249
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07001250 def test_unary(self):
1251 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
1252 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
1253 self.assertEqual(dict(-c), dict(a=5))
1254
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07001255 def test_repr_nonsortable(self):
1256 c = Counter(a=2, b=None)
1257 r = repr(c)
1258 self.assertIn("'a': 2", r)
1259 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07001260
Raymond Hettinger426e0522011-01-03 02:12:02 +00001261 def test_helper_function(self):
1262 # two paths, one for real dicts and one for other mappings
1263 elems = list('abracadabra')
1264
1265 d = dict()
1266 _count_elements(d, elems)
1267 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1268
1269 m = OrderedDict()
1270 _count_elements(m, elems)
1271 self.assertEqual(m,
1272 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
1273
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001274 # test fidelity to the pure python version
1275 c = CounterSubclassWithSetItem('abracadabra')
1276 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001277 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001278 c = CounterSubclassWithGet('abracadabra')
1279 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07001280 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001281
Raymond Hettinger499e1932011-02-23 07:56:53 +00001282
1283################################################################################
1284### OrderedDict
1285################################################################################
1286
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001287class TestOrderedDict(unittest.TestCase):
1288
1289 def test_init(self):
1290 with self.assertRaises(TypeError):
1291 OrderedDict([('a', 1), ('b', 2)], None) # too many args
1292 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1293 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
1294 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
1295 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
1296 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
1297 c=3, e=5).items()), pairs) # mixed input
1298
1299 # make sure no positional args conflict with possible kwdargs
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001300 self.assertEqual(list(OrderedDict(self=42).items()), [('self', 42)])
1301 self.assertEqual(list(OrderedDict(other=42).items()), [('other', 42)])
1302 self.assertRaises(TypeError, OrderedDict, 42)
1303 self.assertRaises(TypeError, OrderedDict, (), ())
1304 self.assertRaises(TypeError, OrderedDict.__init__)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001305
1306 # Make sure that direct calls to __init__ do not clear previous contents
1307 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1308 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
1309 self.assertEqual(list(d.items()),
1310 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1311
1312 def test_update(self):
1313 with self.assertRaises(TypeError):
1314 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
1315 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
1316 od = OrderedDict()
1317 od.update(dict(pairs))
1318 self.assertEqual(sorted(od.items()), pairs) # dict input
1319 od = OrderedDict()
1320 od.update(**dict(pairs))
1321 self.assertEqual(sorted(od.items()), pairs) # kwds input
1322 od = OrderedDict()
1323 od.update(pairs)
1324 self.assertEqual(list(od.items()), pairs) # pairs input
1325 od = OrderedDict()
1326 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1327 self.assertEqual(list(od.items()), pairs) # mixed input
1328
Mark Dickinsonb214e902010-07-11 18:53:06 +00001329 # Issue 9137: Named argument called 'other' or 'self'
1330 # shouldn't be treated specially.
1331 od = OrderedDict()
1332 od.update(self=23)
1333 self.assertEqual(list(od.items()), [('self', 23)])
1334 od = OrderedDict()
1335 od.update(other={})
1336 self.assertEqual(list(od.items()), [('other', {})])
1337 od = OrderedDict()
1338 od.update(red=5, blue=6, other=7, self=8)
1339 self.assertEqual(sorted(list(od.items())),
1340 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
1341
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001342 # Make sure that direct calls to update do not clear previous contents
1343 # add that updates items are not moved to the end
1344 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
1345 d.update([('e', 5), ('f', 6)], g=7, d=4)
1346 self.assertEqual(list(d.items()),
1347 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
1348
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001349 self.assertRaises(TypeError, OrderedDict().update, 42)
1350 self.assertRaises(TypeError, OrderedDict().update, (), ())
1351 self.assertRaises(TypeError, OrderedDict.update)
1352
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001353 def test_abc(self):
1354 self.assertIsInstance(OrderedDict(), MutableMapping)
1355 self.assertTrue(issubclass(OrderedDict, MutableMapping))
1356
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001357 def test_clear(self):
1358 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1359 shuffle(pairs)
1360 od = OrderedDict(pairs)
1361 self.assertEqual(len(od), len(pairs))
1362 od.clear()
1363 self.assertEqual(len(od), 0)
1364
1365 def test_delitem(self):
1366 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1367 od = OrderedDict(pairs)
1368 del od['a']
Benjamin Peterson577473f2010-01-19 00:09:57 +00001369 self.assertNotIn('a', od)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001370 with self.assertRaises(KeyError):
1371 del od['a']
1372 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
1373
1374 def test_setitem(self):
1375 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
1376 od['c'] = 10 # existing element
1377 od['f'] = 20 # new element
1378 self.assertEqual(list(od.items()),
1379 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
1380
1381 def test_iterators(self):
1382 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1383 shuffle(pairs)
1384 od = OrderedDict(pairs)
1385 self.assertEqual(list(od), [t[0] for t in pairs])
1386 self.assertEqual(list(od.keys()), [t[0] for t in pairs])
1387 self.assertEqual(list(od.values()), [t[1] for t in pairs])
1388 self.assertEqual(list(od.items()), pairs)
1389 self.assertEqual(list(reversed(od)),
1390 [t[0] for t in reversed(pairs)])
1391
1392 def test_popitem(self):
1393 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1394 shuffle(pairs)
1395 od = OrderedDict(pairs)
1396 while pairs:
1397 self.assertEqual(od.popitem(), pairs.pop())
1398 with self.assertRaises(KeyError):
1399 od.popitem()
1400 self.assertEqual(len(od), 0)
1401
1402 def test_pop(self):
1403 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1404 shuffle(pairs)
1405 od = OrderedDict(pairs)
1406 shuffle(pairs)
1407 while pairs:
1408 k, v = pairs.pop()
1409 self.assertEqual(od.pop(k), v)
1410 with self.assertRaises(KeyError):
1411 od.pop('xyz')
1412 self.assertEqual(len(od), 0)
1413 self.assertEqual(od.pop(k, 12345), 12345)
1414
Raymond Hettinger345c49b2011-01-01 23:51:55 +00001415 # make sure pop still works when __missing__ is defined
1416 class Missing(OrderedDict):
1417 def __missing__(self, key):
1418 return 0
1419 m = Missing(a=1)
1420 self.assertEqual(m.pop('b', 5), 5)
1421 self.assertEqual(m.pop('a', 6), 1)
1422 self.assertEqual(m.pop('a', 6), 6)
1423 with self.assertRaises(KeyError):
1424 m.pop('a')
1425
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001426 def test_equality(self):
1427 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1428 shuffle(pairs)
1429 od1 = OrderedDict(pairs)
1430 od2 = OrderedDict(pairs)
1431 self.assertEqual(od1, od2) # same order implies equality
1432 pairs = pairs[2:] + pairs[:2]
1433 od2 = OrderedDict(pairs)
1434 self.assertNotEqual(od1, od2) # different order implies inequality
1435 # comparison to regular dict is not order sensitive
1436 self.assertEqual(od1, dict(od2))
1437 self.assertEqual(dict(od2), od1)
1438 # different length implied inequality
1439 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
1440
1441 def test_copying(self):
1442 # Check that ordered dicts are copyable, deepcopyable, picklable,
1443 # and have a repr/eval round-trip
1444 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1445 od = OrderedDict(pairs)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001446 def check(dup):
1447 msg = "\ncopy: %s\nod: %s" % (dup, od)
1448 self.assertIsNot(dup, od, msg)
1449 self.assertEqual(dup, od)
1450 check(od.copy())
1451 check(copy.copy(od))
1452 check(copy.deepcopy(od))
1453 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1454 with self.subTest(proto=proto):
1455 check(pickle.loads(pickle.dumps(od, proto)))
1456 check(eval(repr(od)))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001457 update_test = OrderedDict()
1458 update_test.update(od)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001459 check(update_test)
1460 check(OrderedDict(od))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001461
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001462 def test_yaml_linkage(self):
1463 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1464 # In yaml, lists are native but tuples are not.
1465 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1466 od = OrderedDict(pairs)
1467 # yaml.dump(od) -->
1468 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001469 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger5b26fb52009-03-03 22:38:22 +00001470
Raymond Hettingerb2121572009-03-03 22:50:04 +00001471 def test_reduce_not_too_fat(self):
1472 # do not save instance dictionary if not needed
1473 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1474 od = OrderedDict(pairs)
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001475 self.assertIsNone(od.__reduce__()[2])
Raymond Hettingerb2121572009-03-03 22:50:04 +00001476 od.x = 10
Serhiy Storchaka3ee6dab2013-05-21 12:47:57 +03001477 self.assertIsNotNone(od.__reduce__()[2])
1478
1479 def test_pickle_recursive(self):
1480 od = OrderedDict()
1481 od[1] = od
1482 for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
1483 dup = pickle.loads(pickle.dumps(od, proto))
1484 self.assertIsNot(dup, od)
1485 self.assertEqual(list(dup.keys()), [1])
1486 self.assertIs(dup[1], dup)
Raymond Hettingerb2121572009-03-03 22:50:04 +00001487
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001488 def test_repr(self):
1489 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1490 self.assertEqual(repr(od),
1491 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1492 self.assertEqual(eval(repr(od)), od)
1493 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1494
Raymond Hettingerdc08a142010-09-12 05:15:22 +00001495 def test_repr_recursive(self):
1496 # See issue #9826
1497 od = OrderedDict.fromkeys('abc')
1498 od['x'] = od
1499 self.assertEqual(repr(od),
1500 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1501
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001502 def test_setdefault(self):
1503 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1504 shuffle(pairs)
1505 od = OrderedDict(pairs)
1506 pair_order = list(od.items())
1507 self.assertEqual(od.setdefault('a', 10), 3)
1508 # make sure order didn't change
1509 self.assertEqual(list(od.items()), pair_order)
1510 self.assertEqual(od.setdefault('x', 10), 10)
1511 # make sure 'x' is added to the end
1512 self.assertEqual(list(od.items())[-1], ('x', 10))
1513
Raymond Hettingera673b1f2010-12-31 23:16:17 +00001514 # make sure setdefault still works when __missing__ is defined
1515 class Missing(OrderedDict):
1516 def __missing__(self, key):
1517 return 0
1518 self.assertEqual(Missing().setdefault(5, 9), 9)
1519
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001520 def test_reinsert(self):
1521 # Given insert a, insert b, delete a, re-insert a,
1522 # verify that a is now later than b.
1523 od = OrderedDict()
1524 od['a'] = 1
1525 od['b'] = 2
1526 del od['a']
1527 od['a'] = 1
1528 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1529
Raymond Hettingerf45abc92010-09-06 21:26:09 +00001530 def test_move_to_end(self):
1531 od = OrderedDict.fromkeys('abcde')
1532 self.assertEqual(list(od), list('abcde'))
1533 od.move_to_end('c')
1534 self.assertEqual(list(od), list('abdec'))
1535 od.move_to_end('c', 0)
1536 self.assertEqual(list(od), list('cabde'))
1537 od.move_to_end('c', 0)
1538 self.assertEqual(list(od), list('cabde'))
1539 od.move_to_end('e')
1540 self.assertEqual(list(od), list('cabde'))
1541 with self.assertRaises(KeyError):
1542 od.move_to_end('x')
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001543
Raymond Hettinger35c87f22010-09-16 19:10:17 +00001544 def test_sizeof(self):
1545 # Wimpy test: Just verify the reported size is larger than a regular dict
1546 d = dict(a=1)
1547 od = OrderedDict(**d)
1548 self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
1549
Raymond Hettinger32062e92011-01-01 22:38:00 +00001550 def test_override_update(self):
1551 # Verify that subclasses can override update() without breaking __init__()
1552 class MyOD(OrderedDict):
1553 def update(self, *args, **kwds):
1554 raise Exception()
1555 items = [('a', 1), ('c', 3), ('b', 2)]
1556 self.assertEqual(list(MyOD(items).items()), items)
1557
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001558class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1559 type2test = OrderedDict
1560
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001561 def test_popitem(self):
1562 d = self._empty_mapping()
1563 self.assertRaises(KeyError, d.popitem)
1564
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001565class MyOrderedDict(OrderedDict):
1566 pass
1567
1568class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1569 type2test = MyOrderedDict
1570
Raymond Hettingerdc879f02009-03-19 20:30:56 +00001571 def test_popitem(self):
1572 d = self._empty_mapping()
1573 self.assertRaises(KeyError, d.popitem)
Raymond Hettinger2d32f632009-03-02 21:24:57 +00001574
1575
Raymond Hettinger499e1932011-02-23 07:56:53 +00001576################################################################################
1577### Run tests
1578################################################################################
1579
Christian Heimes25bb7832008-01-11 16:17:00 +00001580import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001581
Guido van Rossumd8faa362007-04-27 19:54:29 +00001582def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00001583 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001584 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00001585 TestCollectionABCs, TestCounter, TestChainMap,
Serhiy Storchakaa86700a2014-11-27 17:45:44 +02001586 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00001587 support.run_unittest(*test_classes)
1588 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001589
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001590
Guido van Rossumd8faa362007-04-27 19:54:29 +00001591if __name__ == "__main__":
1592 test_main(verbose=True)