blob: e2d04d5b476196cfdc01583007899e73c352e22b [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
Joe Jevnikf36f8922019-02-21 16:00:40 -050016from collections import namedtuple, Counter, OrderedDict, _count_elements, _tuplegetter
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
427 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
428 self.assertEqual(list(p), [11, 22]) # coercable to a list
429 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
1475 class CustomEqualObject:
1476 def __eq__(self, other):
1477 return False
Xiang Zhangd5d32492017-03-08 11:04:24 +08001478 class CustomSequence(Sequence):
1479 def __init__(self, seq):
1480 self._seq = seq
1481 def __getitem__(self, index):
1482 return self._seq[index]
1483 def __len__(self):
1484 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001485
1486 nan = float('nan')
1487 obj = CustomEqualObject()
Xiang Zhangd5d32492017-03-08 11:04:24 +08001488 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001489 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001490 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001491 ItemsView({1: nan, 2: obj}),
1492 ValuesView({1: nan, 2: obj})
1493 ]
1494 for container in containers:
1495 for elem in container:
1496 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001497 self.assertEqual(seq.index(nan), 0)
1498 self.assertEqual(seq.index(obj), 1)
1499 self.assertEqual(seq.count(nan), 2)
1500 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001501
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001502 def assertSameSet(self, s1, s2):
1503 # coerce both to a real set then check equality
1504 self.assertSetEqual(set(s1), set(s2))
1505
1506 def test_Set_interoperability_with_real_sets(self):
1507 # Issue: 8743
1508 class ListSet(Set):
1509 def __init__(self, elements=()):
1510 self.data = []
1511 for elem in elements:
1512 if elem not in self.data:
1513 self.data.append(elem)
1514 def __contains__(self, elem):
1515 return elem in self.data
1516 def __iter__(self):
1517 return iter(self.data)
1518 def __len__(self):
1519 return len(self.data)
1520 def __repr__(self):
1521 return 'Set({!r})'.format(self.data)
1522
1523 r1 = set('abc')
1524 r2 = set('bcd')
1525 r3 = set('abcde')
1526 f1 = ListSet('abc')
1527 f2 = ListSet('bcd')
1528 f3 = ListSet('abcde')
1529 l1 = list('abccba')
1530 l2 = list('bcddcb')
1531 l3 = list('abcdeedcba')
1532
1533 target = r1 & r2
1534 self.assertSameSet(f1 & f2, target)
1535 self.assertSameSet(f1 & r2, target)
1536 self.assertSameSet(r2 & f1, target)
1537 self.assertSameSet(f1 & l2, target)
1538
1539 target = r1 | r2
1540 self.assertSameSet(f1 | f2, target)
1541 self.assertSameSet(f1 | r2, target)
1542 self.assertSameSet(r2 | f1, target)
1543 self.assertSameSet(f1 | l2, target)
1544
1545 fwd_target = r1 - r2
1546 rev_target = r2 - r1
1547 self.assertSameSet(f1 - f2, fwd_target)
1548 self.assertSameSet(f2 - f1, rev_target)
1549 self.assertSameSet(f1 - r2, fwd_target)
1550 self.assertSameSet(f2 - r1, rev_target)
1551 self.assertSameSet(r1 - f2, fwd_target)
1552 self.assertSameSet(r2 - f1, rev_target)
1553 self.assertSameSet(f1 - l2, fwd_target)
1554 self.assertSameSet(f2 - l1, rev_target)
1555
1556 target = r1 ^ r2
1557 self.assertSameSet(f1 ^ f2, target)
1558 self.assertSameSet(f1 ^ r2, target)
1559 self.assertSameSet(r2 ^ f1, target)
1560 self.assertSameSet(f1 ^ l2, target)
1561
1562 # Don't change the following to use assertLess or other
1563 # "more specific" unittest assertions. The current
1564 # assertTrue/assertFalse style makes the pattern of test
1565 # case combinations clear and allows us to know for sure
1566 # the exact operator being invoked.
1567
1568 # proper subset
1569 self.assertTrue(f1 < f3)
1570 self.assertFalse(f1 < f1)
1571 self.assertFalse(f1 < f2)
1572 self.assertTrue(r1 < f3)
1573 self.assertFalse(r1 < f1)
1574 self.assertFalse(r1 < f2)
1575 self.assertTrue(r1 < r3)
1576 self.assertFalse(r1 < r1)
1577 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001578 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001579 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001580 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001581 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001582 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001583 f1 < l2
1584
1585 # any subset
1586 self.assertTrue(f1 <= f3)
1587 self.assertTrue(f1 <= f1)
1588 self.assertFalse(f1 <= f2)
1589 self.assertTrue(r1 <= f3)
1590 self.assertTrue(r1 <= f1)
1591 self.assertFalse(r1 <= f2)
1592 self.assertTrue(r1 <= r3)
1593 self.assertTrue(r1 <= r1)
1594 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001595 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001596 f1 <= l3
1597 with self.assertRaises(TypeError):
1598 f1 <= l1
1599 with self.assertRaises(TypeError):
1600 f1 <= l2
1601
1602 # proper superset
1603 self.assertTrue(f3 > f1)
1604 self.assertFalse(f1 > f1)
1605 self.assertFalse(f2 > f1)
1606 self.assertTrue(r3 > r1)
1607 self.assertFalse(f1 > r1)
1608 self.assertFalse(f2 > r1)
1609 self.assertTrue(r3 > r1)
1610 self.assertFalse(r1 > r1)
1611 self.assertFalse(r2 > r1)
1612 with self.assertRaises(TypeError):
1613 f1 > l3
1614 with self.assertRaises(TypeError):
1615 f1 > l1
1616 with self.assertRaises(TypeError):
1617 f1 > l2
1618
1619 # any superset
1620 self.assertTrue(f3 >= f1)
1621 self.assertTrue(f1 >= f1)
1622 self.assertFalse(f2 >= f1)
1623 self.assertTrue(r3 >= r1)
1624 self.assertTrue(f1 >= r1)
1625 self.assertFalse(f2 >= r1)
1626 self.assertTrue(r3 >= r1)
1627 self.assertTrue(r1 >= r1)
1628 self.assertFalse(r2 >= r1)
1629 with self.assertRaises(TypeError):
1630 f1 >= l3
1631 with self.assertRaises(TypeError):
1632 f1 >=l1
1633 with self.assertRaises(TypeError):
1634 f1 >= l2
1635
1636 # equality
1637 self.assertTrue(f1 == f1)
1638 self.assertTrue(r1 == f1)
1639 self.assertTrue(f1 == r1)
1640 self.assertFalse(f1 == f3)
1641 self.assertFalse(r1 == f3)
1642 self.assertFalse(f1 == r3)
1643 self.assertFalse(f1 == l3)
1644 self.assertFalse(f1 == l1)
1645 self.assertFalse(f1 == l2)
1646
1647 # inequality
1648 self.assertFalse(f1 != f1)
1649 self.assertFalse(r1 != f1)
1650 self.assertFalse(f1 != r1)
1651 self.assertTrue(f1 != f3)
1652 self.assertTrue(r1 != f3)
1653 self.assertTrue(f1 != r3)
1654 self.assertTrue(f1 != l3)
1655 self.assertTrue(f1 != l1)
1656 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001657
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001658 def test_Mapping(self):
1659 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001660 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001661 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001662 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1663 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001664 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001665 def __len__(self):
1666 return 0
1667 def __getitem__(self, i):
1668 raise IndexError
1669 def __iter__(self):
1670 return iter(())
1671 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001672 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001673
1674 def test_MutableMapping(self):
1675 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001676 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001677 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001678 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1679 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001680
Raymond Hettinger9117c752010-08-22 07:44:24 +00001681 def test_MutableMapping_subclass(self):
1682 # Test issue 9214
1683 mymap = UserDict()
1684 mymap['red'] = 5
1685 self.assertIsInstance(mymap.keys(), Set)
1686 self.assertIsInstance(mymap.keys(), KeysView)
1687 self.assertIsInstance(mymap.items(), Set)
1688 self.assertIsInstance(mymap.items(), ItemsView)
1689
1690 mymap = UserDict()
1691 mymap['red'] = 5
1692 z = mymap.keys() | {'orange'}
1693 self.assertIsInstance(z, set)
1694 list(z)
1695 mymap['blue'] = 7 # Shouldn't affect 'z'
1696 self.assertEqual(sorted(z), ['orange', 'red'])
1697
1698 mymap = UserDict()
1699 mymap['red'] = 5
1700 z = mymap.items() | {('orange', 3)}
1701 self.assertIsInstance(z, set)
1702 list(z)
1703 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001704 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001705
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001706 def test_Sequence(self):
1707 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001708 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001709 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001710 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001711 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001712 self.assertIsInstance(memoryview(b""), Sequence)
1713 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001714 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001715 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1716 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001717
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001718 def test_Sequence_mixins(self):
1719 class SequenceSubclass(Sequence):
1720 def __init__(self, seq=()):
1721 self.seq = seq
1722
1723 def __getitem__(self, index):
1724 return self.seq[index]
1725
1726 def __len__(self):
1727 return len(self.seq)
1728
1729 # Compare Sequence.index() behavior to (list|str).index() behavior
1730 def assert_index_same(seq1, seq2, index_args):
1731 try:
1732 expected = seq1.index(*index_args)
1733 except ValueError:
1734 with self.assertRaises(ValueError):
1735 seq2.index(*index_args)
1736 else:
1737 actual = seq2.index(*index_args)
1738 self.assertEqual(
1739 actual, expected, '%r.index%s' % (seq1, index_args))
1740
1741 for ty in list, str:
1742 nativeseq = ty('abracadabra')
1743 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1744 seqseq = SequenceSubclass(nativeseq)
1745 for letter in set(nativeseq) | {'z'}:
1746 assert_index_same(nativeseq, seqseq, (letter,))
1747 for start in range(-3, len(nativeseq) + 3):
1748 assert_index_same(nativeseq, seqseq, (letter, start))
1749 for stop in range(-3, len(nativeseq) + 3):
1750 assert_index_same(
1751 nativeseq, seqseq, (letter, start, stop))
1752
Guido van Rossumd05eb002007-11-21 22:26:24 +00001753 def test_ByteString(self):
1754 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001755 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001756 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001757 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001758 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001759 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001760 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001761 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001762
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001763 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001764 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001765 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001766 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001767 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001768 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001769 self.assertTrue(issubclass(sample, MutableSequence))
1770 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001771 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1772 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001773
Eli Bendersky0716a572011-03-04 10:38:14 +00001774 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001775 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001776 # class inherited from it.
1777 class MutableSequenceSubclass(MutableSequence):
1778 def __init__(self):
1779 self.lst = []
1780
1781 def __setitem__(self, index, value):
1782 self.lst[index] = value
1783
1784 def __getitem__(self, index):
1785 return self.lst[index]
1786
1787 def __len__(self):
1788 return len(self.lst)
1789
1790 def __delitem__(self, index):
1791 del self.lst[index]
1792
1793 def insert(self, index, value):
1794 self.lst.insert(index, value)
1795
1796 mss = MutableSequenceSubclass()
1797 mss.append(0)
1798 mss.extend((1, 2, 3, 4))
1799 self.assertEqual(len(mss), 5)
1800 self.assertEqual(mss[3], 3)
1801 mss.reverse()
1802 self.assertEqual(mss[3], 1)
1803 mss.pop()
1804 self.assertEqual(len(mss), 4)
1805 mss.remove(3)
1806 self.assertEqual(len(mss), 3)
1807 mss += (10, 20, 30)
1808 self.assertEqual(len(mss), 6)
1809 self.assertEqual(mss[-1], 30)
1810 mss.clear()
1811 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001812
Naris R1b5f9c92018-08-31 02:56:14 +10001813 # issue 34427
1814 # extending self should not cause infinite loop
1815 items = 'ABCD'
1816 mss2 = MutableSequenceSubclass()
1817 mss2.extend(items + items)
1818 mss.clear()
1819 mss.extend(items)
1820 mss.extend(mss)
1821 self.assertEqual(len(mss), len(mss2))
1822 self.assertEqual(list(mss), list(mss2))
1823
1824
Raymond Hettinger499e1932011-02-23 07:56:53 +00001825################################################################################
1826### Counter
1827################################################################################
1828
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001829class CounterSubclassWithSetItem(Counter):
1830 # Test a counter subclass that overrides __setitem__
1831 def __init__(self, *args, **kwds):
1832 self.called = False
1833 Counter.__init__(self, *args, **kwds)
1834 def __setitem__(self, key, value):
1835 self.called = True
1836 Counter.__setitem__(self, key, value)
1837
1838class CounterSubclassWithGet(Counter):
1839 # Test a counter subclass that overrides get()
1840 def __init__(self, *args, **kwds):
1841 self.called = False
1842 Counter.__init__(self, *args, **kwds)
1843 def get(self, key, default):
1844 self.called = True
1845 return Counter.get(self, key, default)
1846
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001847class TestCounter(unittest.TestCase):
1848
1849 def test_basics(self):
1850 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001851 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1852 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001853 self.assertIsInstance(c, dict)
1854 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001855 self.assertTrue(issubclass(Counter, dict))
1856 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001857 self.assertEqual(len(c), 3)
1858 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001859 self.assertEqual(list(c.values()), [3, 2, 1])
1860 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1861 self.assertEqual(list(c), ['a', 'b', 'c'])
1862 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001863 [('a', 3), ('b', 2), ('c', 1)])
1864 self.assertEqual(c['b'], 2)
1865 self.assertEqual(c['z'], 0)
1866 self.assertEqual(c.__contains__('c'), True)
1867 self.assertEqual(c.__contains__('z'), False)
1868 self.assertEqual(c.get('b', 10), 2)
1869 self.assertEqual(c.get('z', 10), 10)
1870 self.assertEqual(c, dict(a=3, b=2, c=1))
1871 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1872 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1873 for i in range(5):
1874 self.assertEqual(c.most_common(i),
1875 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001876 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001877 c['a'] += 1 # increment an existing value
1878 c['b'] -= 2 # sub existing value to zero
1879 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001880 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001881 c['d'] -= 2 # sub from a missing value
1882 c['e'] = -5 # directly assign a missing value
1883 c['f'] += 4 # add to a missing value
1884 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001885 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001886 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001887 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001888 for i in range(3):
1889 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001890 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001891 c.clear()
1892 self.assertEqual(c, {})
1893 self.assertEqual(repr(c), 'Counter()')
1894 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1895 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001896 c.update(dict(a=5, b=3))
1897 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001898 c.update(Counter('a' * 50 + 'b' * 30))
1899 c.update() # test case with no args
1900 c.__init__('a' * 500 + 'b' * 300)
1901 c.__init__('cdc')
1902 c.__init__()
1903 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1904 self.assertEqual(c.setdefault('d', 5), 1)
1905 self.assertEqual(c['d'], 1)
1906 self.assertEqual(c.setdefault('e', 5), 5)
1907 self.assertEqual(c['e'], 5)
1908
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001909 def test_init(self):
1910 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1911 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1912 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1913 self.assertRaises(TypeError, Counter, 42)
1914 self.assertRaises(TypeError, Counter, (), ())
1915 self.assertRaises(TypeError, Counter.__init__)
1916
Raymond Hettinger407c7342019-02-21 09:19:00 -08001917 def test_order_preservation(self):
1918 # Input order dictates items() order
1919 self.assertEqual(list(Counter('abracadabra').items()),
1920 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
1921 # letters with same count: ^----------^ ^---------^
1922
1923 # Verify retention of order even when all counts are equal
1924 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
1925 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
1926
1927 # Input order dictates elements() order
1928 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
1929 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
1930 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
1931
1932 # Math operations order first by the order encountered in the left
1933 # operand and then by the order encounted in the right operand.
1934 ps = 'aaabbcdddeefggghhijjjkkl'
1935 qs = 'abbcccdeefffhkkllllmmnno'
1936 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
1937 def correctly_ordered(seq):
1938 'Return true if the letters occur in the expected order'
1939 positions = [order[letter] for letter in seq]
1940 return positions == sorted(positions)
1941
1942 p, q = Counter(ps), Counter(qs)
1943 self.assertTrue(correctly_ordered(+p))
1944 self.assertTrue(correctly_ordered(-p))
1945 self.assertTrue(correctly_ordered(p + q))
1946 self.assertTrue(correctly_ordered(p - q))
1947 self.assertTrue(correctly_ordered(p | q))
1948 self.assertTrue(correctly_ordered(p & q))
1949
1950 p, q = Counter(ps), Counter(qs)
1951 p += q
1952 self.assertTrue(correctly_ordered(p))
1953
1954 p, q = Counter(ps), Counter(qs)
1955 p -= q
1956 self.assertTrue(correctly_ordered(p))
1957
1958 p, q = Counter(ps), Counter(qs)
1959 p |= q
1960 self.assertTrue(correctly_ordered(p))
1961
1962 p, q = Counter(ps), Counter(qs)
1963 p &= q
1964 self.assertTrue(correctly_ordered(p))
1965
1966 p, q = Counter(ps), Counter(qs)
1967 p.update(q)
1968 self.assertTrue(correctly_ordered(p))
1969
1970 p, q = Counter(ps), Counter(qs)
1971 p.subtract(q)
1972 self.assertTrue(correctly_ordered(p))
1973
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001974 def test_update(self):
1975 c = Counter()
1976 c.update(self=42)
1977 self.assertEqual(list(c.items()), [('self', 42)])
1978 c = Counter()
1979 c.update(iterable=42)
1980 self.assertEqual(list(c.items()), [('iterable', 42)])
1981 c = Counter()
1982 c.update(iterable=None)
1983 self.assertEqual(list(c.items()), [('iterable', None)])
1984 self.assertRaises(TypeError, Counter().update, 42)
1985 self.assertRaises(TypeError, Counter().update, {}, {})
1986 self.assertRaises(TypeError, Counter.update)
1987
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001988 def test_copying(self):
1989 # Check that counters are copyable, deepcopyable, picklable, and
1990 #have a repr/eval round-trip
1991 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02001992 def check(dup):
1993 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1994 self.assertIsNot(dup, words, msg)
1995 self.assertEqual(dup, words)
1996 check(words.copy())
1997 check(copy.copy(words))
1998 check(copy.deepcopy(words))
1999 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2000 with self.subTest(proto=proto):
2001 check(pickle.loads(pickle.dumps(words, proto)))
2002 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002003 update_test = Counter()
2004 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002005 check(update_test)
2006 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002007
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002008 def test_copy_subclass(self):
2009 class MyCounter(Counter):
2010 pass
2011 c = MyCounter('slartibartfast')
2012 d = c.copy()
2013 self.assertEqual(d, c)
2014 self.assertEqual(len(d), len(c))
2015 self.assertEqual(type(d), type(c))
2016
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002017 def test_conversions(self):
2018 # Convert to: set, list, dict
2019 s = 'she sells sea shells by the sea shore'
2020 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2021 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2022 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2023 self.assertEqual(set(Counter(s)), set(s))
2024
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002025 def test_invariant_for_the_in_operator(self):
2026 c = Counter(a=10, b=-2, c=0)
2027 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002028 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002029 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002030
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002031 def test_multiset_operations(self):
2032 # Verify that adding a zero counter will strip zeros and negatives
2033 c = Counter(a=10, b=-2, c=0) + Counter()
2034 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002035
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002036 elements = 'abcd'
2037 for i in range(1000):
2038 # test random pairs of multisets
2039 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002040 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002041 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002042 q.update(h=1, i=-1, j=0)
2043 for counterop, numberop in [
2044 (Counter.__add__, lambda x, y: max(0, x+y)),
2045 (Counter.__sub__, lambda x, y: max(0, x-y)),
2046 (Counter.__or__, lambda x, y: max(0,x,y)),
2047 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002048 ]:
2049 result = counterop(p, q)
2050 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002051 self.assertEqual(numberop(p[x], q[x]), result[x],
2052 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002053 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002054 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002055
2056 elements = 'abcdef'
2057 for i in range(100):
2058 # verify that random multisets with no repeats are exactly like sets
2059 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2060 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2061 for counterop, setop in [
2062 (Counter.__sub__, set.__sub__),
2063 (Counter.__or__, set.__or__),
2064 (Counter.__and__, set.__and__),
2065 ]:
2066 counter_result = counterop(p, q)
2067 set_result = setop(set(p.elements()), set(q.elements()))
2068 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002069
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002070 def test_inplace_operations(self):
2071 elements = 'abcd'
2072 for i in range(1000):
2073 # test random pairs of multisets
2074 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2075 p.update(e=1, f=-1, g=0)
2076 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2077 q.update(h=1, i=-1, j=0)
2078 for inplace_op, regular_op in [
2079 (Counter.__iadd__, Counter.__add__),
2080 (Counter.__isub__, Counter.__sub__),
2081 (Counter.__ior__, Counter.__or__),
2082 (Counter.__iand__, Counter.__and__),
2083 ]:
2084 c = p.copy()
2085 c_id = id(c)
2086 regular_result = regular_op(c, q)
2087 inplace_result = inplace_op(c, q)
2088 self.assertEqual(inplace_result, regular_result)
2089 self.assertEqual(id(inplace_result), c_id)
2090
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002091 def test_subtract(self):
2092 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2093 c.subtract(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(a=-5, b=0, c=5, d=10, e=15,g=40)
2096 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2097 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2098 c = Counter('aaabbcd')
2099 c.subtract('aaaabbcce')
2100 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002101
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002102 c = Counter()
2103 c.subtract(self=42)
2104 self.assertEqual(list(c.items()), [('self', -42)])
2105 c = Counter()
2106 c.subtract(iterable=42)
2107 self.assertEqual(list(c.items()), [('iterable', -42)])
2108 self.assertRaises(TypeError, Counter().subtract, 42)
2109 self.assertRaises(TypeError, Counter().subtract, {}, {})
2110 self.assertRaises(TypeError, Counter.subtract)
2111
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002112 def test_unary(self):
2113 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2114 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2115 self.assertEqual(dict(-c), dict(a=5))
2116
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002117 def test_repr_nonsortable(self):
2118 c = Counter(a=2, b=None)
2119 r = repr(c)
2120 self.assertIn("'a': 2", r)
2121 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002122
Raymond Hettinger426e0522011-01-03 02:12:02 +00002123 def test_helper_function(self):
2124 # two paths, one for real dicts and one for other mappings
2125 elems = list('abracadabra')
2126
2127 d = dict()
2128 _count_elements(d, elems)
2129 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2130
2131 m = OrderedDict()
2132 _count_elements(m, elems)
2133 self.assertEqual(m,
2134 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2135
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002136 # test fidelity to the pure python version
2137 c = CounterSubclassWithSetItem('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 c = CounterSubclassWithGet('abracadabra')
2141 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002142 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002143
Raymond Hettinger499e1932011-02-23 07:56:53 +00002144
2145################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002146### Run tests
2147################################################################################
2148
Guido van Rossumd8faa362007-04-27 19:54:29 +00002149def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002150 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002151 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002152 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002153 TestUserObjects,
2154 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002155 support.run_unittest(*test_classes)
2156 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002157
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002158
Guido van Rossumd8faa362007-04-27 19:54:29 +00002159if __name__ == "__main__":
2160 test_main(verbose=True)