blob: 7f01de6f433d1cf4ee60b1efbd90d3d0b906cdf5 [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +02003import collections
4import copy
5import doctest
Serhiy Storchaka052b2df2018-12-31 14:15:16 +02006import inspect
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +02007import operator
8import pickle
9from random import choice, randrange
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020010import string
R. David Murray378c0cf2010-02-24 01:46:21 +000011import sys
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020012from test import support
Yury Selivanov75445082015-05-11 22:57:16 -040013import types
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020014import unittest
15
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020016from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger573b44c2015-05-22 16:56:32 -070017from collections import UserDict, UserString, UserList
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000018from collections import ChainMap
Raymond Hettinger32ea1652015-03-21 01:37:37 -070019from collections import deque
Yury Selivanov22214ab2016-11-16 18:25:04 -050020from collections.abc import Awaitable, Coroutine
21from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator
Guido van Rossum16ca06b2016-04-04 10:59:29 -070022from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
Guido van Rossumf0666942016-08-23 10:47:07 -070023from collections.abc import Sized, Container, Callable, Collection
Raymond Hettinger57d1a882011-02-23 00:46:28 +000024from collections.abc import Set, MutableSet
Raymond Hettinger584e8ae2016-05-05 11:14:06 +030025from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
Raymond Hettinger57d1a882011-02-23 00:46:28 +000026from collections.abc import Sequence, MutableSequence
27from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000028
Raymond Hettinger499e1932011-02-23 07:56:53 +000029
Raymond Hettinger573b44c2015-05-22 16:56:32 -070030class TestUserObjects(unittest.TestCase):
31 def _superset_test(self, a, b):
32 self.assertGreaterEqual(
33 set(dir(a)),
34 set(dir(b)),
35 '{a} should have all the methods of {b}'.format(
36 a=a.__name__,
37 b=b.__name__,
38 ),
39 )
Bar Harelf4e1bab2019-05-19 16:57:13 +030040
41 def _copy_test(self, obj):
42 # Test internal copy
43 obj_copy = obj.copy()
44 self.assertIsNot(obj.data, obj_copy.data)
45 self.assertEqual(obj.data, obj_copy.data)
46
47 # Test copy.copy
48 obj.test = [1234] # Make sure instance vars are also copied.
49 obj_copy = copy.copy(obj)
50 self.assertIsNot(obj.data, obj_copy.data)
51 self.assertEqual(obj.data, obj_copy.data)
52 self.assertIs(obj.test, obj_copy.test)
53
Raymond Hettinger573b44c2015-05-22 16:56:32 -070054 def test_str_protocol(self):
55 self._superset_test(UserString, str)
56
57 def test_list_protocol(self):
58 self._superset_test(UserList, list)
59
60 def test_dict_protocol(self):
61 self._superset_test(UserDict, dict)
62
Bar Harelf4e1bab2019-05-19 16:57:13 +030063 def test_list_copy(self):
64 obj = UserList()
65 obj.append(123)
66 self._copy_test(obj)
67
68 def test_dict_copy(self):
69 obj = UserDict()
70 obj[123] = "abc"
71 self._copy_test(obj)
72
Raymond Hettinger573b44c2015-05-22 16:56:32 -070073
Raymond Hettinger499e1932011-02-23 07:56:53 +000074################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000075### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000076################################################################################
77
78class TestChainMap(unittest.TestCase):
79
80 def test_basics(self):
81 c = ChainMap()
82 c['a'] = 1
83 c['b'] = 2
84 d = c.new_child()
85 d['b'] = 20
86 d['c'] = 30
87 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
88 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
89 self.assertEqual(len(d), 3) # check len
90 for key in 'abc': # check contains
91 self.assertIn(key, d)
92 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
93 self.assertEqual(d.get(k, 100), v)
94
95 del d['b'] # unmask a value
96 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
97 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
98 self.assertEqual(len(d), 3) # check len
99 for key in 'abc': # check contains
100 self.assertIn(key, d)
101 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
102 self.assertEqual(d.get(k, 100), v)
103 self.assertIn(repr(d), [ # check repr
104 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
105 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
106 ])
107
108 for e in d.copy(), copy.copy(d): # check shallow copies
109 self.assertEqual(d, e)
110 self.assertEqual(d.maps, e.maps)
111 self.assertIsNot(d, e)
112 self.assertIsNot(d.maps[0], e.maps[0])
113 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
114 self.assertIs(m1, m2)
115
Serhiy Storchakabad12572014-12-15 14:03:42 +0200116 # check deep copies
117 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
118 e = pickle.loads(pickle.dumps(d, proto))
119 self.assertEqual(d, e)
120 self.assertEqual(d.maps, e.maps)
121 self.assertIsNot(d, e)
122 for m1, m2 in zip(d.maps, e.maps):
123 self.assertIsNot(m1, m2, e)
124 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +0000125 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +0200126 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +0000127 self.assertEqual(d, e)
128 self.assertEqual(d.maps, e.maps)
129 self.assertIsNot(d, e)
130 for m1, m2 in zip(d.maps, e.maps):
131 self.assertIsNot(m1, m2, e)
132
Raymond Hettingerd0321312011-02-26 06:53:58 +0000133 f = d.new_child()
134 f['b'] = 5
135 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
136 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
137 self.assertEqual(f['b'], 5) # find first in chain
138 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +0000139
Raymond Hettinger86f093f2019-02-21 09:12:15 -0800140 def test_ordering(self):
141 # Combined order matches a series of dict updates from last to first.
142 # This test relies on the ordering of the underlying dicts.
143
144 baseline = {'music': 'bach', 'art': 'rembrandt'}
145 adjustments = {'art': 'van gogh', 'opera': 'carmen'}
146
147 cm = ChainMap(adjustments, baseline)
148
149 combined = baseline.copy()
150 combined.update(adjustments)
151
152 self.assertEqual(list(combined.items()), list(cm.items()))
153
Martin Pantereb995702016-07-28 01:11:04 +0000154 def test_constructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +0000155 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +0000156 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
157
Raymond Hettingerd0321312011-02-26 06:53:58 +0000158 def test_bool(self):
159 self.assertFalse(ChainMap())
160 self.assertFalse(ChainMap({}, {}))
161 self.assertTrue(ChainMap({1:2}, {}))
162 self.assertTrue(ChainMap({}, {1:2}))
163
Raymond Hettinger499e1932011-02-23 07:56:53 +0000164 def test_missing(self):
165 class DefaultChainMap(ChainMap):
166 def __missing__(self, key):
167 return 999
168 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
169 for k, v in dict(a=1, b=2, c=30, d=999).items():
170 self.assertEqual(d[k], v) # check __getitem__ w/missing
171 for k, v in dict(a=1, b=2, c=30, d=77).items():
172 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
173 for k, v in dict(a=True, b=True, c=True, d=False).items():
174 self.assertEqual(k in d, v) # check __contains__ w/missing
175 self.assertEqual(d.pop('a', 1001), 1, d)
176 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
177 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
178 with self.assertRaises(KeyError):
179 d.popitem()
180
Raymond Hettinger3793f952018-02-11 00:30:31 -0800181 def test_order_preservation(self):
182 d = ChainMap(
183 OrderedDict(j=0, h=88888),
184 OrderedDict(),
185 OrderedDict(i=9999, d=4444, c=3333),
186 OrderedDict(f=666, b=222, g=777, c=333, h=888),
187 OrderedDict(),
188 OrderedDict(e=55, b=22),
189 OrderedDict(a=1, b=2, c=3, d=4, e=5),
190 OrderedDict(),
191 )
192 self.assertEqual(''.join(d), 'abcdefghij')
193 self.assertEqual(list(d.items()),
194 [('a', 1), ('b', 222), ('c', 3333), ('d', 4444),
195 ('e', 55), ('f', 666), ('g', 777), ('h', 88888),
196 ('i', 9999), ('j', 0)])
197
Raymond Hettinger499e1932011-02-23 07:56:53 +0000198 def test_dict_coercion(self):
199 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
200 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
201 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
202
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000203 def test_new_child(self):
204 'Tests for changes for issue #16613.'
205 c = ChainMap()
206 c['a'] = 1
207 c['b'] = 2
208 m = {'b':20, 'c': 30}
209 d = c.new_child(m)
210 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
211 self.assertIs(m, d.maps[0])
212
213 # Use a different map than a dict
214 class lowerdict(dict):
215 def __getitem__(self, key):
216 if isinstance(key, str):
217 key = key.lower()
218 return dict.__getitem__(self, key)
219 def __contains__(self, key):
220 if isinstance(key, str):
221 key = key.lower()
222 return dict.__contains__(self, key)
223
224 c = ChainMap()
225 c['a'] = 1
226 c['b'] = 2
227 m = lowerdict(b=20, c=30)
228 d = c.new_child(m)
229 self.assertIs(m, d.maps[0])
230 for key in 'abc': # check contains
231 self.assertIn(key, d)
232 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
233 self.assertEqual(d.get(k, 100), v)
234
Raymond Hettinger499e1932011-02-23 07:56:53 +0000235
236################################################################################
237### Named Tuples
238################################################################################
239
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000240TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000241
242class TestNamedTuple(unittest.TestCase):
243
244 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000245 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000246 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000247 self.assertEqual(Point.__slots__, ())
248 self.assertEqual(Point.__module__, __name__)
249 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000250 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000251
252 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
253 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
254 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
255
256 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
257 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
258 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000259 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000260 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
261
262 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000263 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000264
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000265 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000266 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000267 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000268 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000269
Christian Heimesfaf2f632008-01-06 16:59:19 +0000270 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
271 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
272
Raymond Hettinger39482072018-01-10 21:45:19 -0800273 def test_defaults(self):
274 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700275 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800276 self.assertEqual(Point(1, 2), (1, 2))
277 self.assertEqual(Point(1), (1, 20))
278 self.assertEqual(Point(), (10, 20))
279
280 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700281 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800282 self.assertEqual(Point(1, 2), (1, 2))
283 self.assertEqual(Point(1), (1, 20))
284
285 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700286 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800287 self.assertEqual(Point(1, 2), (1, 2))
288 with self.assertRaises(TypeError):
289 Point(1)
290
291 with self.assertRaises(TypeError): # catch too few args
292 Point()
293 with self.assertRaises(TypeError): # catch too many args
294 Point(1, 2, 3)
295 with self.assertRaises(TypeError): # too many defaults
296 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
297 with self.assertRaises(TypeError): # non-iterable defaults
298 Point = namedtuple('Point', 'x y', defaults=10)
299 with self.assertRaises(TypeError): # another non-iterable default
300 Point = namedtuple('Point', 'x y', defaults=False)
301
302 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700303 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800304 self.assertIsNone(Point.__new__.__defaults__, None)
305 self.assertEqual(Point(10, 20), (10, 20))
306 with self.assertRaises(TypeError): # catch too few args
307 Point(10)
308
309 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700310 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800311 self.assertEqual(Point.__new__.__defaults__, (10, 20))
312 self.assertEqual(Point(1, 2), (1, 2))
313 self.assertEqual(Point(1), (1, 20))
314 self.assertEqual(Point(), (10, 20))
315
316 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700317 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800318 self.assertEqual(Point.__new__.__defaults__, (10, 20))
319 self.assertEqual(Point(1, 2), (1, 2))
320 self.assertEqual(Point(1), (1, 20))
321 self.assertEqual(Point(), (10, 20))
322
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200323 def test_readonly(self):
324 Point = namedtuple('Point', 'x y')
325 p = Point(11, 22)
326 with self.assertRaises(AttributeError):
327 p.x = 33
328 with self.assertRaises(AttributeError):
329 del p.x
330 with self.assertRaises(TypeError):
331 p[0] = 33
332 with self.assertRaises(TypeError):
333 del p[0]
334 self.assertEqual(p.x, 11)
335 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800336
R. David Murray378c0cf2010-02-24 01:46:21 +0000337 @unittest.skipIf(sys.flags.optimize >= 2,
338 "Docstrings are omitted with -O2 and above")
339 def test_factory_doc_attr(self):
340 Point = namedtuple('Point', 'x y')
341 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200342 Point.__doc__ = '2D point'
343 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000344
Raymond Hettingereac503a2015-05-13 01:09:59 -0700345 @unittest.skipIf(sys.flags.optimize >= 2,
346 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200347 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700348 Point = namedtuple('Point', 'x y')
349 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200350 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700351 Point.x.__doc__ = 'docstring for Point.x'
352 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200353 # namedtuple can mutate doc of descriptors independently
354 Vector = namedtuple('Vector', 'x y')
355 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
356 Vector.x.__doc__ = 'docstring for Vector.x'
357 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
358
359 @support.cpython_only
360 @unittest.skipIf(sys.flags.optimize >= 2,
361 "Docstrings are omitted with -O2 and above")
362 def test_field_doc_reuse(self):
363 P = namedtuple('P', ['m', 'n'])
364 Q = namedtuple('Q', ['o', 'p'])
365 self.assertIs(P.m.__doc__, Q.o.__doc__)
366 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700367
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000368 def test_name_fixer(self):
369 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000370 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
371 [('abc', 'class'), ('abc', '_1')], # field has keyword
372 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
373 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
374 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
375 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000376 ]:
377 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
378
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700379 def test_module_parameter(self):
380 NT = namedtuple('NT', ['x', 'y'], module=collections)
381 self.assertEqual(NT.__module__, collections)
382
Guido van Rossumd8faa362007-04-27 19:54:29 +0000383 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000384 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000385 p = Point(11, 22)
386 self.assertEqual(p, Point(x=11, y=22))
387 self.assertEqual(p, Point(11, y=22))
388 self.assertEqual(p, Point(y=22, x=11))
389 self.assertEqual(p, Point(*(11, 22)))
390 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200391 self.assertRaises(TypeError, Point, 1) # too few args
392 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
393 with self.assertRaises(TypeError): # wrong keyword argument
394 Point(XXX=1, y=2)
395 with self.assertRaises(TypeError): # missing keyword argument
396 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000397 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000398 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200399 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
400 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
401 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
402 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000403
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000404 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000405 p._replace(x=1, error=2)
406 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000407 pass
408 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000409 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000410
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000411 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000412 Point = namedtuple('Point', 'x, y')
413 p = Point(x=11, y=22)
414 self.assertEqual(repr(p), 'Point(x=11, y=22)')
415
416 # verify that fieldspec can be a non-string sequence
417 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000418 p = Point(x=11, y=22)
419 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000420
421 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000422 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000423 p = Point(11, 22)
424
Ezio Melottie9615932010-01-24 19:26:24 +0000425 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000426 self.assertEqual(p, (11, 22)) # matches a real tuple
Min ho Kimc4cacc82019-07-31 08:16:13 +1000427 self.assertEqual(tuple(p), (11, 22)) # coercible to a real tuple
428 self.assertEqual(list(p), [11, 22]) # coercible to a list
Guido van Rossumd8faa362007-04-27 19:54:29 +0000429 self.assertEqual(max(p), 22) # iterable
430 self.assertEqual(max(*p), 22) # star-able
431 x, y = p
432 self.assertEqual(p, (x, y)) # unpacks like a tuple
433 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200434 with self.assertRaises(IndexError):
435 p[3]
436 self.assertEqual(p[-1], 22)
437 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000438
439 self.assertEqual(p.x, x)
440 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200441 with self.assertRaises(AttributeError):
442 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000443
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000444 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000445 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000446 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000447 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000448 self.assertEqual(repr(Zero()), 'Zero()')
449 self.assertEqual(Zero()._asdict(), {})
450 self.assertEqual(Zero()._fields, ())
451
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000452 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000453 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000454 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000455 self.assertEqual(Dot(1).d, 1)
456 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
457 self.assertEqual(Dot(1)._asdict(), {'d':1})
458 self.assertEqual(Dot(1)._replace(d=999), (999,))
459 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000460
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200461 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200462 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000463 for j in range(10)]) for i in range(n)))
464 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000465 Big = namedtuple('Big', names)
466 b = Big(*range(n))
467 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000468 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000469 for pos, name in enumerate(names):
470 self.assertEqual(getattr(b, name), pos)
471 repr(b) # make sure repr() doesn't blow-up
472 d = b._asdict()
473 d_expected = dict(zip(names, range(n)))
474 self.assertEqual(d, d_expected)
475 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
476 b2_expected = list(range(n))
477 b2_expected[1] = 999
478 b2_expected[-5] = 42
479 self.assertEqual(b2, tuple(b2_expected))
480 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000481
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000482 def test_pickle(self):
483 p = TestNT(x=10, y=20, z=30)
484 for module in (pickle,):
485 loads = getattr(module, 'loads')
486 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500487 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000488 q = loads(dumps(p, protocol))
489 self.assertEqual(p, q)
490 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700491 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000492
493 def test_copy(self):
494 p = TestNT(x=10, y=20, z=30)
495 for copier in copy.copy, copy.deepcopy:
496 q = copier(p)
497 self.assertEqual(p, q)
498 self.assertEqual(p._fields, q._fields)
499
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000500 def test_name_conflicts(self):
501 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
502 # failed when used as field names. Test to make sure these now work.
503 T = namedtuple('T', 'itemgetter property self cls tuple')
504 t = T(1, 2, 3, 4, 5)
505 self.assertEqual(t, (1,2,3,4,5))
506 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
507 self.assertEqual(newt, (10,20,30,40,50))
508
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700509 # Broader test of all interesting names taken from the code, old
510 # template, and an example
511 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
512 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
513 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
514 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
515 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
516 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
517 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
518 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
519 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
520 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
521 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
522 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
523 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
524 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
525 'instantiate', 'interning', 'introspection', 'isidentifier',
526 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
527 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
528 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
529 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
530 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
531 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
532 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
533 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
534 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
535 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
536 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
537 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
538 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
539 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000540 T = namedtuple('T', words)
541 # test __new__
542 values = tuple(range(len(words)))
543 t = T(*values)
544 self.assertEqual(t, values)
545 t = T(**dict(zip(T._fields, values)))
546 self.assertEqual(t, values)
547 # test _make
548 t = T._make(values)
549 self.assertEqual(t, values)
550 # exercise __repr__
551 repr(t)
552 # test _asdict
553 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
554 # test _replace
555 t = T._make(values)
556 newvalues = tuple(v*10 for v in values)
557 newt = t._replace(**dict(zip(T._fields, newvalues)))
558 self.assertEqual(newt, newvalues)
559 # test _fields
560 self.assertEqual(T._fields, tuple(words))
561 # test __getnewargs__
562 self.assertEqual(t.__getnewargs__(), values)
563
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000564 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700565 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000566 self.assertEqual(repr(A(1)), 'A(x=1)')
567 # repr should show the name of the subclass
568 class B(A):
569 pass
570 self.assertEqual(repr(B(1)), 'B(x=1)')
571
Raymond Hettinger6538b432016-08-16 10:55:43 -0700572 def test_keyword_only_arguments(self):
573 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700574 with self.assertRaises(TypeError):
575 NT = namedtuple('NT', ['x', 'y'], True)
576
577 NT = namedtuple('NT', ['abc', 'def'], rename=True)
578 self.assertEqual(NT._fields, ('abc', '_1'))
579 with self.assertRaises(TypeError):
580 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000581
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700582 def test_namedtuple_subclass_issue_24931(self):
583 class Point(namedtuple('_Point', ['x', 'y'])):
584 pass
585
586 a = Point(3, 4)
587 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
588
589 a.w = 5
590 self.assertEqual(a.__dict__, {'w': 5})
591
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200592 def test_field_descriptor(self):
593 Point = namedtuple('Point', 'x y')
594 p = Point(11, 22)
595 self.assertTrue(inspect.isdatadescriptor(Point.x))
596 self.assertEqual(Point.x.__get__(p), 11)
597 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
598 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000599
Joe Jevnikf36f8922019-02-21 16:00:40 -0500600 class NewPoint(tuple):
601 x = pickle.loads(pickle.dumps(Point.x))
602 y = pickle.loads(pickle.dumps(Point.y))
603
604 np = NewPoint([1, 2])
605
606 self.assertEqual(np.x, 1)
607 self.assertEqual(np.y, 2)
608
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700609
Raymond Hettinger499e1932011-02-23 07:56:53 +0000610################################################################################
611### Abstract Base Classes
612################################################################################
613
Raymond Hettingerae650182009-01-28 23:33:59 +0000614class ABCTestCase(unittest.TestCase):
615
616 def validate_abstract_methods(self, abc, *names):
617 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
618
619 # everything should work will all required methods are present
620 C = type('C', (abc,), methodstubs)
621 C()
622
623 # instantiation should fail if a required method is missing
624 for name in names:
625 stubs = methodstubs.copy()
626 del stubs[name]
627 C = type('C', (abc,), stubs)
628 self.assertRaises(TypeError, C, name)
629
Florent Xiclunace153f62010-03-08 15:34:35 +0000630 def validate_isinstance(self, abc, name):
631 stub = lambda s, *args: 0
632
633 C = type('C', (object,), {'__hash__': None})
634 setattr(C, name, stub)
635 self.assertIsInstance(C(), abc)
636 self.assertTrue(issubclass(C, abc))
637
638 C = type('C', (object,), {'__hash__': None})
639 self.assertNotIsInstance(C(), abc)
640 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000641
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000642 def validate_comparison(self, instance):
643 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
644 operators = {}
645 for op in ops:
646 name = '__' + op + '__'
647 operators[name] = getattr(operator, name)
648
649 class Other:
650 def __init__(self):
651 self.right_side = False
652 def __eq__(self, other):
653 self.right_side = True
654 return True
655 __lt__ = __eq__
656 __gt__ = __eq__
657 __le__ = __eq__
658 __ge__ = __eq__
659 __ne__ = __eq__
660 __ror__ = __eq__
661 __rand__ = __eq__
662 __rxor__ = __eq__
663 __rsub__ = __eq__
664
665 for name, op in operators.items():
666 if not hasattr(instance, name):
667 continue
668 other = Other()
669 op(instance, other)
670 self.assertTrue(other.right_side,'Right side not called for %s.%s'
671 % (type(instance), name))
672
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700673def _test_gen():
674 yield
675
Raymond Hettingerae650182009-01-28 23:33:59 +0000676class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000677
Yury Selivanov75445082015-05-11 22:57:16 -0400678 def test_Awaitable(self):
679 def gen():
680 yield
681
682 @types.coroutine
683 def coro():
684 yield
685
686 async def new_coro():
687 pass
688
689 class Bar:
690 def __await__(self):
691 yield
692
693 class MinimalCoro(Coroutine):
694 def send(self, value):
695 return value
696 def throw(self, typ, val=None, tb=None):
697 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400698 def __await__(self):
699 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400700
701 non_samples = [None, int(), gen(), object()]
702 for x in non_samples:
703 self.assertNotIsInstance(x, Awaitable)
704 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
705
706 samples = [Bar(), MinimalCoro()]
707 for x in samples:
708 self.assertIsInstance(x, Awaitable)
709 self.assertTrue(issubclass(type(x), Awaitable))
710
711 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400712 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
713 # flag don't have '__await__' method, hence can't be instances
714 # of Awaitable. Use inspect.isawaitable to detect them.
715 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400716
717 c = new_coro()
718 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300719 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400720
Yury Selivanov56fc6142015-05-29 09:01:29 -0400721 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400722 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400723 self.assertTrue(isinstance(CoroLike(), Awaitable))
724 self.assertTrue(issubclass(CoroLike, Awaitable))
725 CoroLike = None
726 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400727
Yury Selivanov75445082015-05-11 22:57:16 -0400728 def test_Coroutine(self):
729 def gen():
730 yield
731
732 @types.coroutine
733 def coro():
734 yield
735
736 async def new_coro():
737 pass
738
739 class Bar:
740 def __await__(self):
741 yield
742
743 class MinimalCoro(Coroutine):
744 def send(self, value):
745 return value
746 def throw(self, typ, val=None, tb=None):
747 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400748 def __await__(self):
749 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400750
751 non_samples = [None, int(), gen(), object(), Bar()]
752 for x in non_samples:
753 self.assertNotIsInstance(x, Coroutine)
754 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
755
756 samples = [MinimalCoro()]
757 for x in samples:
758 self.assertIsInstance(x, Awaitable)
759 self.assertTrue(issubclass(type(x), Awaitable))
760
761 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400762 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
763 # flag don't have '__await__' method, hence can't be instances
764 # of Coroutine. Use inspect.isawaitable to detect them.
765 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400766
767 c = new_coro()
768 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300769 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400770
Yury Selivanov56fc6142015-05-29 09:01:29 -0400771 class CoroLike:
772 def send(self, value):
773 pass
774 def throw(self, typ, val=None, tb=None):
775 pass
776 def close(self):
777 pass
778 def __await__(self):
779 pass
780 self.assertTrue(isinstance(CoroLike(), Coroutine))
781 self.assertTrue(issubclass(CoroLike, Coroutine))
782
783 class CoroLike:
784 def send(self, value):
785 pass
786 def close(self):
787 pass
788 def __await__(self):
789 pass
790 self.assertFalse(isinstance(CoroLike(), Coroutine))
791 self.assertFalse(issubclass(CoroLike, Coroutine))
792
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000793 def test_Hashable(self):
794 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000795 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000796 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000797 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000798 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000799 # Check some hashables
800 samples = [None,
801 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000802 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000803 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000804 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000805 ]
806 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000807 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000808 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000809 self.assertRaises(TypeError, Hashable)
810 # Check direct subclassing
811 class H(Hashable):
812 def __hash__(self):
813 return super().__hash__()
814 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000815 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000816 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000817 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000818
Yury Selivanove0104ae2015-05-14 12:19:16 -0400819 def test_AsyncIterable(self):
820 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400821 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400822 return self
823 self.assertTrue(isinstance(AI(), AsyncIterable))
824 self.assertTrue(issubclass(AI, AsyncIterable))
825 # Check some non-iterables
826 non_samples = [None, object, []]
827 for x in non_samples:
828 self.assertNotIsInstance(x, AsyncIterable)
829 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
830 self.validate_abstract_methods(AsyncIterable, '__aiter__')
831 self.validate_isinstance(AsyncIterable, '__aiter__')
832
833 def test_AsyncIterator(self):
834 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400835 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400836 return self
837 async def __anext__(self):
838 raise StopAsyncIteration
839 self.assertTrue(isinstance(AI(), AsyncIterator))
840 self.assertTrue(issubclass(AI, AsyncIterator))
841 non_samples = [None, object, []]
842 # Check some non-iterables
843 for x in non_samples:
844 self.assertNotIsInstance(x, AsyncIterator)
845 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
846 # Similarly to regular iterators (see issue 10565)
847 class AnextOnly:
848 async def __anext__(self):
849 raise StopAsyncIteration
850 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
851 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
852
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000853 def test_Iterable(self):
854 # Check some non-iterables
855 non_samples = [None, 42, 3.14, 1j]
856 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000857 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000858 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000859 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000860 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000861 tuple(), list(), set(), frozenset(), dict(),
862 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700863 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000864 (x for x in []),
865 ]
866 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000867 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000868 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000869 # Check direct subclassing
870 class I(Iterable):
871 def __iter__(self):
872 return super().__iter__()
873 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000874 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000875 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000876 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700877 # Check None blocking
878 class It:
879 def __iter__(self): return iter([])
880 class ItBlocked(It):
881 __iter__ = None
882 self.assertTrue(issubclass(It, Iterable))
883 self.assertTrue(isinstance(It(), Iterable))
884 self.assertFalse(issubclass(ItBlocked, Iterable))
885 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000886
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700887 def test_Reversible(self):
888 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100889 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700890 for x in non_samples:
891 self.assertNotIsInstance(x, Reversible)
892 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700893 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100894 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700895 for x in non_reversibles:
896 self.assertNotIsInstance(x, Reversible)
897 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
898 # Check some reversible iterables
899 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
900 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100901 OrderedDict().values(), Counter(), Counter().keys(),
902 Counter().items(), Counter().values(), dict(),
903 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700904 for x in samples:
905 self.assertIsInstance(x, Reversible)
906 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
907 # Check also Mapping, MutableMapping, and Sequence
908 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
909 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
910 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
911 # Check direct subclassing
912 class R(Reversible):
913 def __iter__(self):
914 return iter(list())
915 def __reversed__(self):
916 return iter(list())
917 self.assertEqual(list(reversed(R())), [])
918 self.assertFalse(issubclass(float, R))
919 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700920 # Check reversible non-iterable (which is not Reversible)
921 class RevNoIter:
922 def __reversed__(self): return reversed([])
923 class RevPlusIter(RevNoIter):
924 def __iter__(self): return iter([])
925 self.assertFalse(issubclass(RevNoIter, Reversible))
926 self.assertFalse(isinstance(RevNoIter(), Reversible))
927 self.assertTrue(issubclass(RevPlusIter, Reversible))
928 self.assertTrue(isinstance(RevPlusIter(), Reversible))
929 # Check None blocking
930 class Rev:
931 def __iter__(self): return iter([])
932 def __reversed__(self): return reversed([])
933 class RevItBlocked(Rev):
934 __iter__ = None
935 class RevRevBlocked(Rev):
936 __reversed__ = None
937 self.assertTrue(issubclass(Rev, Reversible))
938 self.assertTrue(isinstance(Rev(), Reversible))
939 self.assertFalse(issubclass(RevItBlocked, Reversible))
940 self.assertFalse(isinstance(RevItBlocked(), Reversible))
941 self.assertFalse(issubclass(RevRevBlocked, Reversible))
942 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700943
Guido van Rossumf0666942016-08-23 10:47:07 -0700944 def test_Collection(self):
945 # Check some non-collections
946 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
947 for x in non_collections:
948 self.assertNotIsInstance(x, Collection)
949 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
950 # Check some non-collection iterables
951 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -0800952 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -0700953 for x in non_col_iterables:
954 self.assertNotIsInstance(x, Collection)
955 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
956 # Check some collections
957 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -0800958 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -0700959 for x in samples:
960 self.assertIsInstance(x, Collection)
961 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
962 # Check also Mapping, MutableMapping, etc.
963 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
964 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
965 self.assertTrue(issubclass(MutableMapping, Collection),
966 repr(MutableMapping))
967 self.assertTrue(issubclass(Set, Collection), repr(Set))
968 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
969 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
970 # Check direct subclassing
971 class Col(Collection):
972 def __iter__(self):
973 return iter(list())
974 def __len__(self):
975 return 0
976 def __contains__(self, item):
977 return False
978 class DerCol(Col): pass
979 self.assertEqual(list(iter(Col())), [])
980 self.assertFalse(issubclass(list, Col))
981 self.assertFalse(issubclass(set, Col))
982 self.assertFalse(issubclass(float, Col))
983 self.assertEqual(list(iter(DerCol())), [])
984 self.assertFalse(issubclass(list, DerCol))
985 self.assertFalse(issubclass(set, DerCol))
986 self.assertFalse(issubclass(float, DerCol))
987 self.validate_abstract_methods(Collection, '__len__', '__iter__',
988 '__contains__')
989 # Check sized container non-iterable (which is not Collection) etc.
990 class ColNoIter:
991 def __len__(self): return 0
992 def __contains__(self, item): return False
993 class ColNoSize:
994 def __iter__(self): return iter([])
995 def __contains__(self, item): return False
996 class ColNoCont:
997 def __iter__(self): return iter([])
998 def __len__(self): return 0
999 self.assertFalse(issubclass(ColNoIter, Collection))
1000 self.assertFalse(isinstance(ColNoIter(), Collection))
1001 self.assertFalse(issubclass(ColNoSize, Collection))
1002 self.assertFalse(isinstance(ColNoSize(), Collection))
1003 self.assertFalse(issubclass(ColNoCont, Collection))
1004 self.assertFalse(isinstance(ColNoCont(), Collection))
1005 # Check None blocking
1006 class SizeBlock:
1007 def __iter__(self): return iter([])
1008 def __contains__(self): return False
1009 __len__ = None
1010 class IterBlock:
1011 def __len__(self): return 0
1012 def __contains__(self): return True
1013 __iter__ = None
1014 self.assertFalse(issubclass(SizeBlock, Collection))
1015 self.assertFalse(isinstance(SizeBlock(), Collection))
1016 self.assertFalse(issubclass(IterBlock, Collection))
1017 self.assertFalse(isinstance(IterBlock(), Collection))
1018 # Check None blocking in subclass
1019 class ColImpl:
1020 def __iter__(self):
1021 return iter(list())
1022 def __len__(self):
1023 return 0
1024 def __contains__(self, item):
1025 return False
1026 class NonCol(ColImpl):
1027 __contains__ = None
1028 self.assertFalse(issubclass(NonCol, Collection))
1029 self.assertFalse(isinstance(NonCol(), Collection))
1030
1031
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001032 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001033 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001034 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001035 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001036 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001037 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001038 iter(tuple()), iter(list()), iter(dict()),
1039 iter(set()), iter(frozenset()),
1040 iter(dict().keys()), iter(dict().items()),
1041 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001042 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001043 (x for x in []),
1044 ]
1045 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001046 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001047 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001048 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1049
1050 # Issue 10565
1051 class NextOnly:
1052 def __next__(self):
1053 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001054 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001055 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001056
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001057 def test_Generator(self):
1058 class NonGen1:
1059 def __iter__(self): return self
1060 def __next__(self): return None
1061 def close(self): pass
1062 def throw(self, typ, val=None, tb=None): pass
1063
1064 class NonGen2:
1065 def __iter__(self): return self
1066 def __next__(self): return None
1067 def close(self): pass
1068 def send(self, value): return value
1069
1070 class NonGen3:
1071 def close(self): pass
1072 def send(self, value): return value
1073 def throw(self, typ, val=None, tb=None): pass
1074
1075 non_samples = [
1076 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1077 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1078 for x in non_samples:
1079 self.assertNotIsInstance(x, Generator)
1080 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1081
1082 class Gen:
1083 def __iter__(self): return self
1084 def __next__(self): return None
1085 def close(self): pass
1086 def send(self, value): return value
1087 def throw(self, typ, val=None, tb=None): pass
1088
1089 class MinimalGen(Generator):
1090 def send(self, value):
1091 return value
1092 def throw(self, typ, val=None, tb=None):
1093 super().throw(typ, val, tb)
1094
1095 def gen():
1096 yield 1
1097
1098 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1099 for x in samples:
1100 self.assertIsInstance(x, Iterator)
1101 self.assertIsInstance(x, Generator)
1102 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1103 self.validate_abstract_methods(Generator, 'send', 'throw')
1104
1105 # mixin tests
1106 mgen = MinimalGen()
1107 self.assertIs(mgen, iter(mgen))
1108 self.assertIs(mgen.send(None), next(mgen))
1109 self.assertEqual(2, mgen.send(2))
1110 self.assertIsNone(mgen.close())
1111 self.assertRaises(ValueError, mgen.throw, ValueError)
1112 self.assertRaisesRegex(ValueError, "^huhu$",
1113 mgen.throw, ValueError, ValueError("huhu"))
1114 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1115
1116 class FailOnClose(Generator):
1117 def send(self, value): return value
1118 def throw(self, *args): raise ValueError
1119
1120 self.assertRaises(ValueError, FailOnClose().close)
1121
1122 class IgnoreGeneratorExit(Generator):
1123 def send(self, value): return value
1124 def throw(self, *args): pass
1125
1126 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1127
Yury Selivanov22214ab2016-11-16 18:25:04 -05001128 def test_AsyncGenerator(self):
1129 class NonAGen1:
1130 def __aiter__(self): return self
1131 def __anext__(self): return None
1132 def aclose(self): pass
1133 def athrow(self, typ, val=None, tb=None): pass
1134
1135 class NonAGen2:
1136 def __aiter__(self): return self
1137 def __anext__(self): return None
1138 def aclose(self): pass
1139 def asend(self, value): return value
1140
1141 class NonAGen3:
1142 def aclose(self): pass
1143 def asend(self, value): return value
1144 def athrow(self, typ, val=None, tb=None): pass
1145
1146 non_samples = [
1147 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1148 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1149 for x in non_samples:
1150 self.assertNotIsInstance(x, AsyncGenerator)
1151 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1152
1153 class Gen:
1154 def __aiter__(self): return self
1155 async def __anext__(self): return None
1156 async def aclose(self): pass
1157 async def asend(self, value): return value
1158 async def athrow(self, typ, val=None, tb=None): pass
1159
1160 class MinimalAGen(AsyncGenerator):
1161 async def asend(self, value):
1162 return value
1163 async def athrow(self, typ, val=None, tb=None):
1164 await super().athrow(typ, val, tb)
1165
1166 async def gen():
1167 yield 1
1168
1169 samples = [gen(), Gen(), MinimalAGen()]
1170 for x in samples:
1171 self.assertIsInstance(x, AsyncIterator)
1172 self.assertIsInstance(x, AsyncGenerator)
1173 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1174 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1175
1176 def run_async(coro):
1177 result = None
1178 while True:
1179 try:
1180 coro.send(None)
1181 except StopIteration as ex:
1182 result = ex.args[0] if ex.args else None
1183 break
1184 return result
1185
1186 # mixin tests
1187 mgen = MinimalAGen()
1188 self.assertIs(mgen, mgen.__aiter__())
1189 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1190 self.assertEqual(2, run_async(mgen.asend(2)))
1191 self.assertIsNone(run_async(mgen.aclose()))
1192 with self.assertRaises(ValueError):
1193 run_async(mgen.athrow(ValueError))
1194
1195 class FailOnClose(AsyncGenerator):
1196 async def asend(self, value): return value
1197 async def athrow(self, *args): raise ValueError
1198
1199 with self.assertRaises(ValueError):
1200 run_async(FailOnClose().aclose())
1201
1202 class IgnoreGeneratorExit(AsyncGenerator):
1203 async def asend(self, value): return value
1204 async def athrow(self, *args): pass
1205
1206 with self.assertRaises(RuntimeError):
1207 run_async(IgnoreGeneratorExit().aclose())
1208
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001209 def test_Sized(self):
1210 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001211 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001212 (x for x in []),
1213 ]
1214 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001215 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001216 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001217 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001218 tuple(), list(), set(), frozenset(), dict(),
1219 dict().keys(), dict().items(), dict().values(),
1220 ]
1221 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001222 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001223 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001224 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001225 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001226
1227 def test_Container(self):
1228 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001229 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001230 (x for x in []),
1231 ]
1232 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001233 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001234 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001235 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001236 tuple(), list(), set(), frozenset(), dict(),
1237 dict().keys(), dict().items(),
1238 ]
1239 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001240 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001241 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001242 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001243 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001244
1245 def test_Callable(self):
1246 non_samples = [None, 42, 3.14, 1j,
1247 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001248 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001249 (x for x in []),
1250 ]
1251 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001252 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001253 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001254 samples = [lambda: None,
1255 type, int, object,
1256 len,
1257 list.append, [].append,
1258 ]
1259 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001260 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001261 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001262 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001263 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001264
1265 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001266 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001267 class C(B):
1268 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001269 self.assertTrue(issubclass(C, B))
1270 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001271
1272 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001273 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001274 class C:
1275 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001276 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001277 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001278 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001279
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001280class WithSet(MutableSet):
1281
1282 def __init__(self, it=()):
1283 self.data = set(it)
1284
1285 def __len__(self):
1286 return len(self.data)
1287
1288 def __iter__(self):
1289 return iter(self.data)
1290
1291 def __contains__(self, item):
1292 return item in self.data
1293
1294 def add(self, item):
1295 self.data.add(item)
1296
1297 def discard(self, item):
1298 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001299
Raymond Hettingerae650182009-01-28 23:33:59 +00001300class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001301
1302 # XXX For now, we only test some virtual inheritance properties.
1303 # We should also test the proper behavior of the collection ABCs
1304 # as real base classes or mix-in classes.
1305
1306 def test_Set(self):
1307 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001308 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001309 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001310 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001311 class MySet(Set):
1312 def __contains__(self, x):
1313 return False
1314 def __len__(self):
1315 return 0
1316 def __iter__(self):
1317 return iter([])
1318 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001319
Benjamin Peterson41181742008-07-02 20:22:54 +00001320 def test_hash_Set(self):
1321 class OneTwoThreeSet(Set):
1322 def __init__(self):
1323 self.contents = [1, 2, 3]
1324 def __contains__(self, x):
1325 return x in self.contents
1326 def __len__(self):
1327 return len(self.contents)
1328 def __iter__(self):
1329 return iter(self.contents)
1330 def __hash__(self):
1331 return self._hash()
1332 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001333 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001334
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001335 def test_isdisjoint_Set(self):
1336 class MySet(Set):
1337 def __init__(self, itr):
1338 self.contents = itr
1339 def __contains__(self, x):
1340 return x in self.contents
1341 def __iter__(self):
1342 return iter(self.contents)
1343 def __len__(self):
1344 return len([x for x in self.contents])
1345 s1 = MySet((1, 2, 3))
1346 s2 = MySet((4, 5, 6))
1347 s3 = MySet((1, 5, 6))
1348 self.assertTrue(s1.isdisjoint(s2))
1349 self.assertFalse(s1.isdisjoint(s3))
1350
1351 def test_equality_Set(self):
1352 class MySet(Set):
1353 def __init__(self, itr):
1354 self.contents = itr
1355 def __contains__(self, x):
1356 return x in self.contents
1357 def __iter__(self):
1358 return iter(self.contents)
1359 def __len__(self):
1360 return len([x for x in self.contents])
1361 s1 = MySet((1,))
1362 s2 = MySet((1, 2))
1363 s3 = MySet((3, 4))
1364 s4 = MySet((3, 4))
1365 self.assertTrue(s2 > s1)
1366 self.assertTrue(s1 < s2)
1367 self.assertFalse(s2 <= s1)
1368 self.assertFalse(s2 <= s3)
1369 self.assertFalse(s1 >= s2)
1370 self.assertEqual(s3, s4)
1371 self.assertNotEqual(s2, s3)
1372
1373 def test_arithmetic_Set(self):
1374 class MySet(Set):
1375 def __init__(self, itr):
1376 self.contents = itr
1377 def __contains__(self, x):
1378 return x in self.contents
1379 def __iter__(self):
1380 return iter(self.contents)
1381 def __len__(self):
1382 return len([x for x in self.contents])
1383 s1 = MySet((1, 2, 3))
1384 s2 = MySet((3, 4, 5))
1385 s3 = s1 & s2
1386 self.assertEqual(s3, MySet((3,)))
1387
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001388 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001389 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001390 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001391 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001392 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001393 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1394 'add', 'discard')
1395
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001396 def test_issue_5647(self):
1397 # MutableSet.__iand__ mutated the set during iteration
1398 s = WithSet('abcd')
1399 s &= WithSet('cdef') # This used to fail
1400 self.assertEqual(set(s), set('cd'))
1401
Raymond Hettingerae650182009-01-28 23:33:59 +00001402 def test_issue_4920(self):
1403 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001404 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001405 __slots__=['__s']
1406 def __init__(self,items=None):
1407 if items is None:
1408 items=[]
1409 self.__s=set(items)
1410 def __contains__(self,v):
1411 return v in self.__s
1412 def __iter__(self):
1413 return iter(self.__s)
1414 def __len__(self):
1415 return len(self.__s)
1416 def add(self,v):
1417 result=v not in self.__s
1418 self.__s.add(v)
1419 return result
1420 def discard(self,v):
1421 result=v in self.__s
1422 self.__s.discard(v)
1423 return result
1424 def __repr__(self):
1425 return "MySet(%s)" % repr(list(self))
1426 s = MySet([5,43,2,1])
1427 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001428
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001429 def test_issue8750(self):
1430 empty = WithSet()
1431 full = WithSet(range(10))
1432 s = WithSet(full)
1433 s -= s
1434 self.assertEqual(s, empty)
1435 s = WithSet(full)
1436 s ^= s
1437 self.assertEqual(s, empty)
1438 s = WithSet(full)
1439 s &= s
1440 self.assertEqual(s, full)
1441 s |= s
1442 self.assertEqual(s, full)
1443
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001444 def test_issue16373(self):
1445 # Recursion error comparing comparable and noncomparable
1446 # Set instances
1447 class MyComparableSet(Set):
1448 def __contains__(self, x):
1449 return False
1450 def __len__(self):
1451 return 0
1452 def __iter__(self):
1453 return iter([])
1454 class MyNonComparableSet(Set):
1455 def __contains__(self, x):
1456 return False
1457 def __len__(self):
1458 return 0
1459 def __iter__(self):
1460 return iter([])
1461 def __le__(self, x):
1462 return NotImplemented
1463 def __lt__(self, x):
1464 return NotImplemented
1465
1466 cs = MyComparableSet()
1467 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001468 self.assertFalse(ncs < cs)
1469 self.assertTrue(ncs <= cs)
1470 self.assertFalse(ncs > cs)
1471 self.assertTrue(ncs >= cs)
1472
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001473 def test_issue26915(self):
1474 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001475 class CustomSequence(Sequence):
1476 def __init__(self, seq):
1477 self._seq = seq
1478 def __getitem__(self, index):
1479 return self._seq[index]
1480 def __len__(self):
1481 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001482
1483 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001484 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001485 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001486 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001487 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001488 ItemsView({1: nan, 2: obj}),
1489 ValuesView({1: nan, 2: obj})
1490 ]
1491 for container in containers:
1492 for elem in container:
1493 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001494 self.assertEqual(seq.index(nan), 0)
1495 self.assertEqual(seq.index(obj), 1)
1496 self.assertEqual(seq.count(nan), 2)
1497 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001498
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001499 def assertSameSet(self, s1, s2):
1500 # coerce both to a real set then check equality
1501 self.assertSetEqual(set(s1), set(s2))
1502
1503 def test_Set_interoperability_with_real_sets(self):
1504 # Issue: 8743
1505 class ListSet(Set):
1506 def __init__(self, elements=()):
1507 self.data = []
1508 for elem in elements:
1509 if elem not in self.data:
1510 self.data.append(elem)
1511 def __contains__(self, elem):
1512 return elem in self.data
1513 def __iter__(self):
1514 return iter(self.data)
1515 def __len__(self):
1516 return len(self.data)
1517 def __repr__(self):
1518 return 'Set({!r})'.format(self.data)
1519
1520 r1 = set('abc')
1521 r2 = set('bcd')
1522 r3 = set('abcde')
1523 f1 = ListSet('abc')
1524 f2 = ListSet('bcd')
1525 f3 = ListSet('abcde')
1526 l1 = list('abccba')
1527 l2 = list('bcddcb')
1528 l3 = list('abcdeedcba')
1529
1530 target = r1 & r2
1531 self.assertSameSet(f1 & f2, target)
1532 self.assertSameSet(f1 & r2, target)
1533 self.assertSameSet(r2 & f1, target)
1534 self.assertSameSet(f1 & l2, target)
1535
1536 target = r1 | r2
1537 self.assertSameSet(f1 | f2, target)
1538 self.assertSameSet(f1 | r2, target)
1539 self.assertSameSet(r2 | f1, target)
1540 self.assertSameSet(f1 | l2, target)
1541
1542 fwd_target = r1 - r2
1543 rev_target = r2 - r1
1544 self.assertSameSet(f1 - f2, fwd_target)
1545 self.assertSameSet(f2 - f1, rev_target)
1546 self.assertSameSet(f1 - r2, fwd_target)
1547 self.assertSameSet(f2 - r1, rev_target)
1548 self.assertSameSet(r1 - f2, fwd_target)
1549 self.assertSameSet(r2 - f1, rev_target)
1550 self.assertSameSet(f1 - l2, fwd_target)
1551 self.assertSameSet(f2 - l1, rev_target)
1552
1553 target = r1 ^ r2
1554 self.assertSameSet(f1 ^ f2, target)
1555 self.assertSameSet(f1 ^ r2, target)
1556 self.assertSameSet(r2 ^ f1, target)
1557 self.assertSameSet(f1 ^ l2, target)
1558
1559 # Don't change the following to use assertLess or other
1560 # "more specific" unittest assertions. The current
1561 # assertTrue/assertFalse style makes the pattern of test
1562 # case combinations clear and allows us to know for sure
1563 # the exact operator being invoked.
1564
1565 # proper subset
1566 self.assertTrue(f1 < f3)
1567 self.assertFalse(f1 < f1)
1568 self.assertFalse(f1 < f2)
1569 self.assertTrue(r1 < f3)
1570 self.assertFalse(r1 < f1)
1571 self.assertFalse(r1 < f2)
1572 self.assertTrue(r1 < r3)
1573 self.assertFalse(r1 < r1)
1574 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001575 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001576 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001577 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001578 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001579 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001580 f1 < l2
1581
1582 # any subset
1583 self.assertTrue(f1 <= f3)
1584 self.assertTrue(f1 <= f1)
1585 self.assertFalse(f1 <= f2)
1586 self.assertTrue(r1 <= f3)
1587 self.assertTrue(r1 <= f1)
1588 self.assertFalse(r1 <= f2)
1589 self.assertTrue(r1 <= r3)
1590 self.assertTrue(r1 <= r1)
1591 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001592 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001593 f1 <= l3
1594 with self.assertRaises(TypeError):
1595 f1 <= l1
1596 with self.assertRaises(TypeError):
1597 f1 <= l2
1598
1599 # proper superset
1600 self.assertTrue(f3 > f1)
1601 self.assertFalse(f1 > f1)
1602 self.assertFalse(f2 > f1)
1603 self.assertTrue(r3 > r1)
1604 self.assertFalse(f1 > r1)
1605 self.assertFalse(f2 > r1)
1606 self.assertTrue(r3 > r1)
1607 self.assertFalse(r1 > r1)
1608 self.assertFalse(r2 > r1)
1609 with self.assertRaises(TypeError):
1610 f1 > l3
1611 with self.assertRaises(TypeError):
1612 f1 > l1
1613 with self.assertRaises(TypeError):
1614 f1 > l2
1615
1616 # any superset
1617 self.assertTrue(f3 >= f1)
1618 self.assertTrue(f1 >= f1)
1619 self.assertFalse(f2 >= f1)
1620 self.assertTrue(r3 >= r1)
1621 self.assertTrue(f1 >= r1)
1622 self.assertFalse(f2 >= r1)
1623 self.assertTrue(r3 >= r1)
1624 self.assertTrue(r1 >= r1)
1625 self.assertFalse(r2 >= r1)
1626 with self.assertRaises(TypeError):
1627 f1 >= l3
1628 with self.assertRaises(TypeError):
1629 f1 >=l1
1630 with self.assertRaises(TypeError):
1631 f1 >= l2
1632
1633 # equality
1634 self.assertTrue(f1 == f1)
1635 self.assertTrue(r1 == f1)
1636 self.assertTrue(f1 == r1)
1637 self.assertFalse(f1 == f3)
1638 self.assertFalse(r1 == f3)
1639 self.assertFalse(f1 == r3)
1640 self.assertFalse(f1 == l3)
1641 self.assertFalse(f1 == l1)
1642 self.assertFalse(f1 == l2)
1643
1644 # inequality
1645 self.assertFalse(f1 != f1)
1646 self.assertFalse(r1 != f1)
1647 self.assertFalse(f1 != r1)
1648 self.assertTrue(f1 != f3)
1649 self.assertTrue(r1 != f3)
1650 self.assertTrue(f1 != r3)
1651 self.assertTrue(f1 != l3)
1652 self.assertTrue(f1 != l1)
1653 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001654
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001655 def test_Mapping(self):
1656 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001657 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001658 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001659 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1660 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001661 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001662 def __len__(self):
1663 return 0
1664 def __getitem__(self, i):
1665 raise IndexError
1666 def __iter__(self):
1667 return iter(())
1668 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001669 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001670
1671 def test_MutableMapping(self):
1672 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001673 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001674 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001675 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1676 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001677
Raymond Hettinger9117c752010-08-22 07:44:24 +00001678 def test_MutableMapping_subclass(self):
1679 # Test issue 9214
1680 mymap = UserDict()
1681 mymap['red'] = 5
1682 self.assertIsInstance(mymap.keys(), Set)
1683 self.assertIsInstance(mymap.keys(), KeysView)
1684 self.assertIsInstance(mymap.items(), Set)
1685 self.assertIsInstance(mymap.items(), ItemsView)
1686
1687 mymap = UserDict()
1688 mymap['red'] = 5
1689 z = mymap.keys() | {'orange'}
1690 self.assertIsInstance(z, set)
1691 list(z)
1692 mymap['blue'] = 7 # Shouldn't affect 'z'
1693 self.assertEqual(sorted(z), ['orange', 'red'])
1694
1695 mymap = UserDict()
1696 mymap['red'] = 5
1697 z = mymap.items() | {('orange', 3)}
1698 self.assertIsInstance(z, set)
1699 list(z)
1700 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001701 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001702
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001703 def test_Sequence(self):
1704 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001705 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001706 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001707 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001708 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001709 self.assertIsInstance(memoryview(b""), Sequence)
1710 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001711 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001712 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1713 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001714
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001715 def test_Sequence_mixins(self):
1716 class SequenceSubclass(Sequence):
1717 def __init__(self, seq=()):
1718 self.seq = seq
1719
1720 def __getitem__(self, index):
1721 return self.seq[index]
1722
1723 def __len__(self):
1724 return len(self.seq)
1725
1726 # Compare Sequence.index() behavior to (list|str).index() behavior
1727 def assert_index_same(seq1, seq2, index_args):
1728 try:
1729 expected = seq1.index(*index_args)
1730 except ValueError:
1731 with self.assertRaises(ValueError):
1732 seq2.index(*index_args)
1733 else:
1734 actual = seq2.index(*index_args)
1735 self.assertEqual(
1736 actual, expected, '%r.index%s' % (seq1, index_args))
1737
1738 for ty in list, str:
1739 nativeseq = ty('abracadabra')
1740 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1741 seqseq = SequenceSubclass(nativeseq)
1742 for letter in set(nativeseq) | {'z'}:
1743 assert_index_same(nativeseq, seqseq, (letter,))
1744 for start in range(-3, len(nativeseq) + 3):
1745 assert_index_same(nativeseq, seqseq, (letter, start))
1746 for stop in range(-3, len(nativeseq) + 3):
1747 assert_index_same(
1748 nativeseq, seqseq, (letter, start, stop))
1749
Guido van Rossumd05eb002007-11-21 22:26:24 +00001750 def test_ByteString(self):
1751 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001752 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001753 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001754 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001755 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001756 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001757 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001758 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001759
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001760 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001761 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001762 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001763 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001764 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001765 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001766 self.assertTrue(issubclass(sample, MutableSequence))
1767 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001768 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1769 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001770
Eli Bendersky0716a572011-03-04 10:38:14 +00001771 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001772 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001773 # class inherited from it.
1774 class MutableSequenceSubclass(MutableSequence):
1775 def __init__(self):
1776 self.lst = []
1777
1778 def __setitem__(self, index, value):
1779 self.lst[index] = value
1780
1781 def __getitem__(self, index):
1782 return self.lst[index]
1783
1784 def __len__(self):
1785 return len(self.lst)
1786
1787 def __delitem__(self, index):
1788 del self.lst[index]
1789
1790 def insert(self, index, value):
1791 self.lst.insert(index, value)
1792
1793 mss = MutableSequenceSubclass()
1794 mss.append(0)
1795 mss.extend((1, 2, 3, 4))
1796 self.assertEqual(len(mss), 5)
1797 self.assertEqual(mss[3], 3)
1798 mss.reverse()
1799 self.assertEqual(mss[3], 1)
1800 mss.pop()
1801 self.assertEqual(len(mss), 4)
1802 mss.remove(3)
1803 self.assertEqual(len(mss), 3)
1804 mss += (10, 20, 30)
1805 self.assertEqual(len(mss), 6)
1806 self.assertEqual(mss[-1], 30)
1807 mss.clear()
1808 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001809
Naris R1b5f9c92018-08-31 02:56:14 +10001810 # issue 34427
1811 # extending self should not cause infinite loop
1812 items = 'ABCD'
1813 mss2 = MutableSequenceSubclass()
1814 mss2.extend(items + items)
1815 mss.clear()
1816 mss.extend(items)
1817 mss.extend(mss)
1818 self.assertEqual(len(mss), len(mss2))
1819 self.assertEqual(list(mss), list(mss2))
1820
1821
Raymond Hettinger499e1932011-02-23 07:56:53 +00001822################################################################################
1823### Counter
1824################################################################################
1825
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001826class CounterSubclassWithSetItem(Counter):
1827 # Test a counter subclass that overrides __setitem__
1828 def __init__(self, *args, **kwds):
1829 self.called = False
1830 Counter.__init__(self, *args, **kwds)
1831 def __setitem__(self, key, value):
1832 self.called = True
1833 Counter.__setitem__(self, key, value)
1834
1835class CounterSubclassWithGet(Counter):
1836 # Test a counter subclass that overrides get()
1837 def __init__(self, *args, **kwds):
1838 self.called = False
1839 Counter.__init__(self, *args, **kwds)
1840 def get(self, key, default):
1841 self.called = True
1842 return Counter.get(self, key, default)
1843
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001844class TestCounter(unittest.TestCase):
1845
1846 def test_basics(self):
1847 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001848 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1849 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001850 self.assertIsInstance(c, dict)
1851 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001852 self.assertTrue(issubclass(Counter, dict))
1853 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001854 self.assertEqual(len(c), 3)
1855 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001856 self.assertEqual(list(c.values()), [3, 2, 1])
1857 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1858 self.assertEqual(list(c), ['a', 'b', 'c'])
1859 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001860 [('a', 3), ('b', 2), ('c', 1)])
1861 self.assertEqual(c['b'], 2)
1862 self.assertEqual(c['z'], 0)
1863 self.assertEqual(c.__contains__('c'), True)
1864 self.assertEqual(c.__contains__('z'), False)
1865 self.assertEqual(c.get('b', 10), 2)
1866 self.assertEqual(c.get('z', 10), 10)
1867 self.assertEqual(c, dict(a=3, b=2, c=1))
1868 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1869 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1870 for i in range(5):
1871 self.assertEqual(c.most_common(i),
1872 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001873 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001874 c['a'] += 1 # increment an existing value
1875 c['b'] -= 2 # sub existing value to zero
1876 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001877 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001878 c['d'] -= 2 # sub from a missing value
1879 c['e'] = -5 # directly assign a missing value
1880 c['f'] += 4 # add to a missing value
1881 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001882 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001883 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001884 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001885 for i in range(3):
1886 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001887 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001888 c.clear()
1889 self.assertEqual(c, {})
1890 self.assertEqual(repr(c), 'Counter()')
1891 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1892 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001893 c.update(dict(a=5, b=3))
1894 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001895 c.update(Counter('a' * 50 + 'b' * 30))
1896 c.update() # test case with no args
1897 c.__init__('a' * 500 + 'b' * 300)
1898 c.__init__('cdc')
1899 c.__init__()
1900 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1901 self.assertEqual(c.setdefault('d', 5), 1)
1902 self.assertEqual(c['d'], 1)
1903 self.assertEqual(c.setdefault('e', 5), 5)
1904 self.assertEqual(c['e'], 5)
1905
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001906 def test_init(self):
1907 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1908 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1909 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1910 self.assertRaises(TypeError, Counter, 42)
1911 self.assertRaises(TypeError, Counter, (), ())
1912 self.assertRaises(TypeError, Counter.__init__)
1913
Raymond Hettinger407c7342019-02-21 09:19:00 -08001914 def test_order_preservation(self):
1915 # Input order dictates items() order
1916 self.assertEqual(list(Counter('abracadabra').items()),
1917 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
1918 # letters with same count: ^----------^ ^---------^
1919
1920 # Verify retention of order even when all counts are equal
1921 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
1922 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
1923
1924 # Input order dictates elements() order
1925 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
1926 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
1927 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
1928
1929 # Math operations order first by the order encountered in the left
1930 # operand and then by the order encounted in the right operand.
1931 ps = 'aaabbcdddeefggghhijjjkkl'
1932 qs = 'abbcccdeefffhkkllllmmnno'
1933 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
1934 def correctly_ordered(seq):
1935 'Return true if the letters occur in the expected order'
1936 positions = [order[letter] for letter in seq]
1937 return positions == sorted(positions)
1938
1939 p, q = Counter(ps), Counter(qs)
1940 self.assertTrue(correctly_ordered(+p))
1941 self.assertTrue(correctly_ordered(-p))
1942 self.assertTrue(correctly_ordered(p + q))
1943 self.assertTrue(correctly_ordered(p - q))
1944 self.assertTrue(correctly_ordered(p | q))
1945 self.assertTrue(correctly_ordered(p & q))
1946
1947 p, q = Counter(ps), Counter(qs)
1948 p += q
1949 self.assertTrue(correctly_ordered(p))
1950
1951 p, q = Counter(ps), Counter(qs)
1952 p -= q
1953 self.assertTrue(correctly_ordered(p))
1954
1955 p, q = Counter(ps), Counter(qs)
1956 p |= q
1957 self.assertTrue(correctly_ordered(p))
1958
1959 p, q = Counter(ps), Counter(qs)
1960 p &= q
1961 self.assertTrue(correctly_ordered(p))
1962
1963 p, q = Counter(ps), Counter(qs)
1964 p.update(q)
1965 self.assertTrue(correctly_ordered(p))
1966
1967 p, q = Counter(ps), Counter(qs)
1968 p.subtract(q)
1969 self.assertTrue(correctly_ordered(p))
1970
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001971 def test_update(self):
1972 c = Counter()
1973 c.update(self=42)
1974 self.assertEqual(list(c.items()), [('self', 42)])
1975 c = Counter()
1976 c.update(iterable=42)
1977 self.assertEqual(list(c.items()), [('iterable', 42)])
1978 c = Counter()
1979 c.update(iterable=None)
1980 self.assertEqual(list(c.items()), [('iterable', None)])
1981 self.assertRaises(TypeError, Counter().update, 42)
1982 self.assertRaises(TypeError, Counter().update, {}, {})
1983 self.assertRaises(TypeError, Counter.update)
1984
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001985 def test_copying(self):
1986 # Check that counters are copyable, deepcopyable, picklable, and
1987 #have a repr/eval round-trip
1988 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02001989 def check(dup):
1990 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1991 self.assertIsNot(dup, words, msg)
1992 self.assertEqual(dup, words)
1993 check(words.copy())
1994 check(copy.copy(words))
1995 check(copy.deepcopy(words))
1996 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1997 with self.subTest(proto=proto):
1998 check(pickle.loads(pickle.dumps(words, proto)))
1999 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002000 update_test = Counter()
2001 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002002 check(update_test)
2003 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002004
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002005 def test_copy_subclass(self):
2006 class MyCounter(Counter):
2007 pass
2008 c = MyCounter('slartibartfast')
2009 d = c.copy()
2010 self.assertEqual(d, c)
2011 self.assertEqual(len(d), len(c))
2012 self.assertEqual(type(d), type(c))
2013
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002014 def test_conversions(self):
2015 # Convert to: set, list, dict
2016 s = 'she sells sea shells by the sea shore'
2017 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2018 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2019 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2020 self.assertEqual(set(Counter(s)), set(s))
2021
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002022 def test_invariant_for_the_in_operator(self):
2023 c = Counter(a=10, b=-2, c=0)
2024 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002025 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002026 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002027
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002028 def test_multiset_operations(self):
2029 # Verify that adding a zero counter will strip zeros and negatives
2030 c = Counter(a=10, b=-2, c=0) + Counter()
2031 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002032
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002033 elements = 'abcd'
2034 for i in range(1000):
2035 # test random pairs of multisets
2036 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002037 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002038 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002039 q.update(h=1, i=-1, j=0)
2040 for counterop, numberop in [
2041 (Counter.__add__, lambda x, y: max(0, x+y)),
2042 (Counter.__sub__, lambda x, y: max(0, x-y)),
2043 (Counter.__or__, lambda x, y: max(0,x,y)),
2044 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002045 ]:
2046 result = counterop(p, q)
2047 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002048 self.assertEqual(numberop(p[x], q[x]), result[x],
2049 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002050 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002051 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002052
2053 elements = 'abcdef'
2054 for i in range(100):
2055 # verify that random multisets with no repeats are exactly like sets
2056 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2057 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2058 for counterop, setop in [
2059 (Counter.__sub__, set.__sub__),
2060 (Counter.__or__, set.__or__),
2061 (Counter.__and__, set.__and__),
2062 ]:
2063 counter_result = counterop(p, q)
2064 set_result = setop(set(p.elements()), set(q.elements()))
2065 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002066
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002067 def test_inplace_operations(self):
2068 elements = 'abcd'
2069 for i in range(1000):
2070 # test random pairs of multisets
2071 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2072 p.update(e=1, f=-1, g=0)
2073 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2074 q.update(h=1, i=-1, j=0)
2075 for inplace_op, regular_op in [
2076 (Counter.__iadd__, Counter.__add__),
2077 (Counter.__isub__, Counter.__sub__),
2078 (Counter.__ior__, Counter.__or__),
2079 (Counter.__iand__, Counter.__and__),
2080 ]:
2081 c = p.copy()
2082 c_id = id(c)
2083 regular_result = regular_op(c, q)
2084 inplace_result = inplace_op(c, q)
2085 self.assertEqual(inplace_result, regular_result)
2086 self.assertEqual(id(inplace_result), c_id)
2087
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002088 def test_subtract(self):
2089 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2090 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2091 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2092 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2093 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2094 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2095 c = Counter('aaabbcd')
2096 c.subtract('aaaabbcce')
2097 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002098
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002099 c = Counter()
2100 c.subtract(self=42)
2101 self.assertEqual(list(c.items()), [('self', -42)])
2102 c = Counter()
2103 c.subtract(iterable=42)
2104 self.assertEqual(list(c.items()), [('iterable', -42)])
2105 self.assertRaises(TypeError, Counter().subtract, 42)
2106 self.assertRaises(TypeError, Counter().subtract, {}, {})
2107 self.assertRaises(TypeError, Counter.subtract)
2108
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002109 def test_unary(self):
2110 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2111 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2112 self.assertEqual(dict(-c), dict(a=5))
2113
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002114 def test_repr_nonsortable(self):
2115 c = Counter(a=2, b=None)
2116 r = repr(c)
2117 self.assertIn("'a': 2", r)
2118 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002119
Raymond Hettinger426e0522011-01-03 02:12:02 +00002120 def test_helper_function(self):
2121 # two paths, one for real dicts and one for other mappings
2122 elems = list('abracadabra')
2123
2124 d = dict()
2125 _count_elements(d, elems)
2126 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2127
2128 m = OrderedDict()
2129 _count_elements(m, elems)
2130 self.assertEqual(m,
2131 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2132
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002133 # test fidelity to the pure python version
2134 c = CounterSubclassWithSetItem('abracadabra')
2135 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002136 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002137 c = CounterSubclassWithGet('abracadabra')
2138 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002139 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002140
Raymond Hettinger499e1932011-02-23 07:56:53 +00002141
2142################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002143### Run tests
2144################################################################################
2145
Guido van Rossumd8faa362007-04-27 19:54:29 +00002146def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002147 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002148 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002149 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002150 TestUserObjects,
2151 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002152 support.run_unittest(*test_classes)
2153 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002154
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002155
Guido van Rossumd8faa362007-04-27 19:54:29 +00002156if __name__ == "__main__":
2157 test_main(verbose=True)