blob: 1f619bcdac9203e2739b709787e8f6b2429dfb41 [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 )
40 def test_str_protocol(self):
41 self._superset_test(UserString, str)
42
43 def test_list_protocol(self):
44 self._superset_test(UserList, list)
45
46 def test_dict_protocol(self):
47 self._superset_test(UserDict, dict)
48
49
Raymond Hettinger499e1932011-02-23 07:56:53 +000050################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000051### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000052################################################################################
53
54class TestChainMap(unittest.TestCase):
55
56 def test_basics(self):
57 c = ChainMap()
58 c['a'] = 1
59 c['b'] = 2
60 d = c.new_child()
61 d['b'] = 20
62 d['c'] = 30
63 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
64 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
65 self.assertEqual(len(d), 3) # check len
66 for key in 'abc': # check contains
67 self.assertIn(key, d)
68 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
69 self.assertEqual(d.get(k, 100), v)
70
71 del d['b'] # unmask a value
72 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
73 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
74 self.assertEqual(len(d), 3) # check len
75 for key in 'abc': # check contains
76 self.assertIn(key, d)
77 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
78 self.assertEqual(d.get(k, 100), v)
79 self.assertIn(repr(d), [ # check repr
80 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
81 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
82 ])
83
84 for e in d.copy(), copy.copy(d): # check shallow copies
85 self.assertEqual(d, e)
86 self.assertEqual(d.maps, e.maps)
87 self.assertIsNot(d, e)
88 self.assertIsNot(d.maps[0], e.maps[0])
89 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
90 self.assertIs(m1, m2)
91
Serhiy Storchakabad12572014-12-15 14:03:42 +020092 # check deep copies
93 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
94 e = pickle.loads(pickle.dumps(d, proto))
95 self.assertEqual(d, e)
96 self.assertEqual(d.maps, e.maps)
97 self.assertIsNot(d, e)
98 for m1, m2 in zip(d.maps, e.maps):
99 self.assertIsNot(m1, m2, e)
100 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +0000101 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +0200102 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +0000103 self.assertEqual(d, e)
104 self.assertEqual(d.maps, e.maps)
105 self.assertIsNot(d, e)
106 for m1, m2 in zip(d.maps, e.maps):
107 self.assertIsNot(m1, m2, e)
108
Raymond Hettingerd0321312011-02-26 06:53:58 +0000109 f = d.new_child()
110 f['b'] = 5
111 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
112 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
113 self.assertEqual(f['b'], 5) # find first in chain
114 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +0000115
Raymond Hettinger86f093f2019-02-21 09:12:15 -0800116 def test_ordering(self):
117 # Combined order matches a series of dict updates from last to first.
118 # This test relies on the ordering of the underlying dicts.
119
120 baseline = {'music': 'bach', 'art': 'rembrandt'}
121 adjustments = {'art': 'van gogh', 'opera': 'carmen'}
122
123 cm = ChainMap(adjustments, baseline)
124
125 combined = baseline.copy()
126 combined.update(adjustments)
127
128 self.assertEqual(list(combined.items()), list(cm.items()))
129
Martin Pantereb995702016-07-28 01:11:04 +0000130 def test_constructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +0000131 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +0000132 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
133
Raymond Hettingerd0321312011-02-26 06:53:58 +0000134 def test_bool(self):
135 self.assertFalse(ChainMap())
136 self.assertFalse(ChainMap({}, {}))
137 self.assertTrue(ChainMap({1:2}, {}))
138 self.assertTrue(ChainMap({}, {1:2}))
139
Raymond Hettinger499e1932011-02-23 07:56:53 +0000140 def test_missing(self):
141 class DefaultChainMap(ChainMap):
142 def __missing__(self, key):
143 return 999
144 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
145 for k, v in dict(a=1, b=2, c=30, d=999).items():
146 self.assertEqual(d[k], v) # check __getitem__ w/missing
147 for k, v in dict(a=1, b=2, c=30, d=77).items():
148 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
149 for k, v in dict(a=True, b=True, c=True, d=False).items():
150 self.assertEqual(k in d, v) # check __contains__ w/missing
151 self.assertEqual(d.pop('a', 1001), 1, d)
152 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
153 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
154 with self.assertRaises(KeyError):
155 d.popitem()
156
Raymond Hettinger3793f952018-02-11 00:30:31 -0800157 def test_order_preservation(self):
158 d = ChainMap(
159 OrderedDict(j=0, h=88888),
160 OrderedDict(),
161 OrderedDict(i=9999, d=4444, c=3333),
162 OrderedDict(f=666, b=222, g=777, c=333, h=888),
163 OrderedDict(),
164 OrderedDict(e=55, b=22),
165 OrderedDict(a=1, b=2, c=3, d=4, e=5),
166 OrderedDict(),
167 )
168 self.assertEqual(''.join(d), 'abcdefghij')
169 self.assertEqual(list(d.items()),
170 [('a', 1), ('b', 222), ('c', 3333), ('d', 4444),
171 ('e', 55), ('f', 666), ('g', 777), ('h', 88888),
172 ('i', 9999), ('j', 0)])
173
Raymond Hettinger499e1932011-02-23 07:56:53 +0000174 def test_dict_coercion(self):
175 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
176 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
177 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
178
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000179 def test_new_child(self):
180 'Tests for changes for issue #16613.'
181 c = ChainMap()
182 c['a'] = 1
183 c['b'] = 2
184 m = {'b':20, 'c': 30}
185 d = c.new_child(m)
186 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
187 self.assertIs(m, d.maps[0])
188
189 # Use a different map than a dict
190 class lowerdict(dict):
191 def __getitem__(self, key):
192 if isinstance(key, str):
193 key = key.lower()
194 return dict.__getitem__(self, key)
195 def __contains__(self, key):
196 if isinstance(key, str):
197 key = key.lower()
198 return dict.__contains__(self, key)
199
200 c = ChainMap()
201 c['a'] = 1
202 c['b'] = 2
203 m = lowerdict(b=20, c=30)
204 d = c.new_child(m)
205 self.assertIs(m, d.maps[0])
206 for key in 'abc': # check contains
207 self.assertIn(key, d)
208 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
209 self.assertEqual(d.get(k, 100), v)
210
Raymond Hettinger499e1932011-02-23 07:56:53 +0000211
212################################################################################
213### Named Tuples
214################################################################################
215
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000216TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000217
218class TestNamedTuple(unittest.TestCase):
219
220 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000221 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000222 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000223 self.assertEqual(Point.__slots__, ())
224 self.assertEqual(Point.__module__, __name__)
225 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000226 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000227
228 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
229 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
230 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
231
232 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
233 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
234 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000235 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000236 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
237
238 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000239 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000240
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000241 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000242 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000243 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000244 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000245
Christian Heimesfaf2f632008-01-06 16:59:19 +0000246 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
247 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
248
Raymond Hettinger39482072018-01-10 21:45:19 -0800249 def test_defaults(self):
250 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700251 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800252 self.assertEqual(Point(1, 2), (1, 2))
253 self.assertEqual(Point(1), (1, 20))
254 self.assertEqual(Point(), (10, 20))
255
256 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700257 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800258 self.assertEqual(Point(1, 2), (1, 2))
259 self.assertEqual(Point(1), (1, 20))
260
261 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700262 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800263 self.assertEqual(Point(1, 2), (1, 2))
264 with self.assertRaises(TypeError):
265 Point(1)
266
267 with self.assertRaises(TypeError): # catch too few args
268 Point()
269 with self.assertRaises(TypeError): # catch too many args
270 Point(1, 2, 3)
271 with self.assertRaises(TypeError): # too many defaults
272 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
273 with self.assertRaises(TypeError): # non-iterable defaults
274 Point = namedtuple('Point', 'x y', defaults=10)
275 with self.assertRaises(TypeError): # another non-iterable default
276 Point = namedtuple('Point', 'x y', defaults=False)
277
278 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700279 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800280 self.assertIsNone(Point.__new__.__defaults__, None)
281 self.assertEqual(Point(10, 20), (10, 20))
282 with self.assertRaises(TypeError): # catch too few args
283 Point(10)
284
285 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700286 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800287 self.assertEqual(Point.__new__.__defaults__, (10, 20))
288 self.assertEqual(Point(1, 2), (1, 2))
289 self.assertEqual(Point(1), (1, 20))
290 self.assertEqual(Point(), (10, 20))
291
292 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700293 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800294 self.assertEqual(Point.__new__.__defaults__, (10, 20))
295 self.assertEqual(Point(1, 2), (1, 2))
296 self.assertEqual(Point(1), (1, 20))
297 self.assertEqual(Point(), (10, 20))
298
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200299 def test_readonly(self):
300 Point = namedtuple('Point', 'x y')
301 p = Point(11, 22)
302 with self.assertRaises(AttributeError):
303 p.x = 33
304 with self.assertRaises(AttributeError):
305 del p.x
306 with self.assertRaises(TypeError):
307 p[0] = 33
308 with self.assertRaises(TypeError):
309 del p[0]
310 self.assertEqual(p.x, 11)
311 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800312
R. David Murray378c0cf2010-02-24 01:46:21 +0000313 @unittest.skipIf(sys.flags.optimize >= 2,
314 "Docstrings are omitted with -O2 and above")
315 def test_factory_doc_attr(self):
316 Point = namedtuple('Point', 'x y')
317 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200318 Point.__doc__ = '2D point'
319 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000320
Raymond Hettingereac503a2015-05-13 01:09:59 -0700321 @unittest.skipIf(sys.flags.optimize >= 2,
322 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200323 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700324 Point = namedtuple('Point', 'x y')
325 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200326 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700327 Point.x.__doc__ = 'docstring for Point.x'
328 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200329 # namedtuple can mutate doc of descriptors independently
330 Vector = namedtuple('Vector', 'x y')
331 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
332 Vector.x.__doc__ = 'docstring for Vector.x'
333 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
334
335 @support.cpython_only
336 @unittest.skipIf(sys.flags.optimize >= 2,
337 "Docstrings are omitted with -O2 and above")
338 def test_field_doc_reuse(self):
339 P = namedtuple('P', ['m', 'n'])
340 Q = namedtuple('Q', ['o', 'p'])
341 self.assertIs(P.m.__doc__, Q.o.__doc__)
342 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700343
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000344 def test_name_fixer(self):
345 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000346 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
347 [('abc', 'class'), ('abc', '_1')], # field has keyword
348 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
349 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
350 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
351 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000352 ]:
353 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
354
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700355 def test_module_parameter(self):
356 NT = namedtuple('NT', ['x', 'y'], module=collections)
357 self.assertEqual(NT.__module__, collections)
358
Guido van Rossumd8faa362007-04-27 19:54:29 +0000359 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000360 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000361 p = Point(11, 22)
362 self.assertEqual(p, Point(x=11, y=22))
363 self.assertEqual(p, Point(11, y=22))
364 self.assertEqual(p, Point(y=22, x=11))
365 self.assertEqual(p, Point(*(11, 22)))
366 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200367 self.assertRaises(TypeError, Point, 1) # too few args
368 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
369 with self.assertRaises(TypeError): # wrong keyword argument
370 Point(XXX=1, y=2)
371 with self.assertRaises(TypeError): # missing keyword argument
372 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000373 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000374 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200375 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
376 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
377 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
378 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000379
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000380 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000381 p._replace(x=1, error=2)
382 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000383 pass
384 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000385 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000386
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000387 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000388 Point = namedtuple('Point', 'x, y')
389 p = Point(x=11, y=22)
390 self.assertEqual(repr(p), 'Point(x=11, y=22)')
391
392 # verify that fieldspec can be a non-string sequence
393 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000394 p = Point(x=11, y=22)
395 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000396
397 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000398 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000399 p = Point(11, 22)
400
Ezio Melottie9615932010-01-24 19:26:24 +0000401 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000402 self.assertEqual(p, (11, 22)) # matches a real tuple
403 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
404 self.assertEqual(list(p), [11, 22]) # coercable to a list
405 self.assertEqual(max(p), 22) # iterable
406 self.assertEqual(max(*p), 22) # star-able
407 x, y = p
408 self.assertEqual(p, (x, y)) # unpacks like a tuple
409 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200410 with self.assertRaises(IndexError):
411 p[3]
412 self.assertEqual(p[-1], 22)
413 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000414
415 self.assertEqual(p.x, x)
416 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200417 with self.assertRaises(AttributeError):
418 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000419
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000420 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000421 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000422 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000423 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000424 self.assertEqual(repr(Zero()), 'Zero()')
425 self.assertEqual(Zero()._asdict(), {})
426 self.assertEqual(Zero()._fields, ())
427
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000428 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000429 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000430 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000431 self.assertEqual(Dot(1).d, 1)
432 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
433 self.assertEqual(Dot(1)._asdict(), {'d':1})
434 self.assertEqual(Dot(1)._replace(d=999), (999,))
435 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000436
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200437 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200438 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000439 for j in range(10)]) for i in range(n)))
440 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000441 Big = namedtuple('Big', names)
442 b = Big(*range(n))
443 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000444 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000445 for pos, name in enumerate(names):
446 self.assertEqual(getattr(b, name), pos)
447 repr(b) # make sure repr() doesn't blow-up
448 d = b._asdict()
449 d_expected = dict(zip(names, range(n)))
450 self.assertEqual(d, d_expected)
451 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
452 b2_expected = list(range(n))
453 b2_expected[1] = 999
454 b2_expected[-5] = 42
455 self.assertEqual(b2, tuple(b2_expected))
456 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000457
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000458 def test_pickle(self):
459 p = TestNT(x=10, y=20, z=30)
460 for module in (pickle,):
461 loads = getattr(module, 'loads')
462 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500463 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000464 q = loads(dumps(p, protocol))
465 self.assertEqual(p, q)
466 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700467 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000468
469 def test_copy(self):
470 p = TestNT(x=10, y=20, z=30)
471 for copier in copy.copy, copy.deepcopy:
472 q = copier(p)
473 self.assertEqual(p, q)
474 self.assertEqual(p._fields, q._fields)
475
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000476 def test_name_conflicts(self):
477 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
478 # failed when used as field names. Test to make sure these now work.
479 T = namedtuple('T', 'itemgetter property self cls tuple')
480 t = T(1, 2, 3, 4, 5)
481 self.assertEqual(t, (1,2,3,4,5))
482 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
483 self.assertEqual(newt, (10,20,30,40,50))
484
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700485 # Broader test of all interesting names taken from the code, old
486 # template, and an example
487 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
488 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
489 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
490 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
491 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
492 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
493 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
494 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
495 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
496 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
497 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
498 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
499 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
500 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
501 'instantiate', 'interning', 'introspection', 'isidentifier',
502 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
503 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
504 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
505 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
506 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
507 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
508 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
509 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
510 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
511 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
512 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
513 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
514 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
515 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000516 T = namedtuple('T', words)
517 # test __new__
518 values = tuple(range(len(words)))
519 t = T(*values)
520 self.assertEqual(t, values)
521 t = T(**dict(zip(T._fields, values)))
522 self.assertEqual(t, values)
523 # test _make
524 t = T._make(values)
525 self.assertEqual(t, values)
526 # exercise __repr__
527 repr(t)
528 # test _asdict
529 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
530 # test _replace
531 t = T._make(values)
532 newvalues = tuple(v*10 for v in values)
533 newt = t._replace(**dict(zip(T._fields, newvalues)))
534 self.assertEqual(newt, newvalues)
535 # test _fields
536 self.assertEqual(T._fields, tuple(words))
537 # test __getnewargs__
538 self.assertEqual(t.__getnewargs__(), values)
539
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000540 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700541 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000542 self.assertEqual(repr(A(1)), 'A(x=1)')
543 # repr should show the name of the subclass
544 class B(A):
545 pass
546 self.assertEqual(repr(B(1)), 'B(x=1)')
547
Raymond Hettinger6538b432016-08-16 10:55:43 -0700548 def test_keyword_only_arguments(self):
549 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700550 with self.assertRaises(TypeError):
551 NT = namedtuple('NT', ['x', 'y'], True)
552
553 NT = namedtuple('NT', ['abc', 'def'], rename=True)
554 self.assertEqual(NT._fields, ('abc', '_1'))
555 with self.assertRaises(TypeError):
556 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000557
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700558 def test_namedtuple_subclass_issue_24931(self):
559 class Point(namedtuple('_Point', ['x', 'y'])):
560 pass
561
562 a = Point(3, 4)
563 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
564
565 a.w = 5
566 self.assertEqual(a.__dict__, {'w': 5})
567
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200568 def test_field_descriptor(self):
569 Point = namedtuple('Point', 'x y')
570 p = Point(11, 22)
571 self.assertTrue(inspect.isdatadescriptor(Point.x))
572 self.assertEqual(Point.x.__get__(p), 11)
573 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
574 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000575
Joe Jevnikf36f8922019-02-21 16:00:40 -0500576 class NewPoint(tuple):
577 x = pickle.loads(pickle.dumps(Point.x))
578 y = pickle.loads(pickle.dumps(Point.y))
579
580 np = NewPoint([1, 2])
581
582 self.assertEqual(np.x, 1)
583 self.assertEqual(np.y, 2)
584
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700585
Raymond Hettinger499e1932011-02-23 07:56:53 +0000586################################################################################
587### Abstract Base Classes
588################################################################################
589
Raymond Hettingerae650182009-01-28 23:33:59 +0000590class ABCTestCase(unittest.TestCase):
591
592 def validate_abstract_methods(self, abc, *names):
593 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
594
595 # everything should work will all required methods are present
596 C = type('C', (abc,), methodstubs)
597 C()
598
599 # instantiation should fail if a required method is missing
600 for name in names:
601 stubs = methodstubs.copy()
602 del stubs[name]
603 C = type('C', (abc,), stubs)
604 self.assertRaises(TypeError, C, name)
605
Florent Xiclunace153f62010-03-08 15:34:35 +0000606 def validate_isinstance(self, abc, name):
607 stub = lambda s, *args: 0
608
609 C = type('C', (object,), {'__hash__': None})
610 setattr(C, name, stub)
611 self.assertIsInstance(C(), abc)
612 self.assertTrue(issubclass(C, abc))
613
614 C = type('C', (object,), {'__hash__': None})
615 self.assertNotIsInstance(C(), abc)
616 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000617
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000618 def validate_comparison(self, instance):
619 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
620 operators = {}
621 for op in ops:
622 name = '__' + op + '__'
623 operators[name] = getattr(operator, name)
624
625 class Other:
626 def __init__(self):
627 self.right_side = False
628 def __eq__(self, other):
629 self.right_side = True
630 return True
631 __lt__ = __eq__
632 __gt__ = __eq__
633 __le__ = __eq__
634 __ge__ = __eq__
635 __ne__ = __eq__
636 __ror__ = __eq__
637 __rand__ = __eq__
638 __rxor__ = __eq__
639 __rsub__ = __eq__
640
641 for name, op in operators.items():
642 if not hasattr(instance, name):
643 continue
644 other = Other()
645 op(instance, other)
646 self.assertTrue(other.right_side,'Right side not called for %s.%s'
647 % (type(instance), name))
648
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700649def _test_gen():
650 yield
651
Raymond Hettingerae650182009-01-28 23:33:59 +0000652class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000653
Yury Selivanov75445082015-05-11 22:57:16 -0400654 def test_Awaitable(self):
655 def gen():
656 yield
657
658 @types.coroutine
659 def coro():
660 yield
661
662 async def new_coro():
663 pass
664
665 class Bar:
666 def __await__(self):
667 yield
668
669 class MinimalCoro(Coroutine):
670 def send(self, value):
671 return value
672 def throw(self, typ, val=None, tb=None):
673 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400674 def __await__(self):
675 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400676
677 non_samples = [None, int(), gen(), object()]
678 for x in non_samples:
679 self.assertNotIsInstance(x, Awaitable)
680 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
681
682 samples = [Bar(), MinimalCoro()]
683 for x in samples:
684 self.assertIsInstance(x, Awaitable)
685 self.assertTrue(issubclass(type(x), Awaitable))
686
687 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400688 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
689 # flag don't have '__await__' method, hence can't be instances
690 # of Awaitable. Use inspect.isawaitable to detect them.
691 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400692
693 c = new_coro()
694 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300695 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400696
Yury Selivanov56fc6142015-05-29 09:01:29 -0400697 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400698 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400699 self.assertTrue(isinstance(CoroLike(), Awaitable))
700 self.assertTrue(issubclass(CoroLike, Awaitable))
701 CoroLike = None
702 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400703
Yury Selivanov75445082015-05-11 22:57:16 -0400704 def test_Coroutine(self):
705 def gen():
706 yield
707
708 @types.coroutine
709 def coro():
710 yield
711
712 async def new_coro():
713 pass
714
715 class Bar:
716 def __await__(self):
717 yield
718
719 class MinimalCoro(Coroutine):
720 def send(self, value):
721 return value
722 def throw(self, typ, val=None, tb=None):
723 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400724 def __await__(self):
725 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400726
727 non_samples = [None, int(), gen(), object(), Bar()]
728 for x in non_samples:
729 self.assertNotIsInstance(x, Coroutine)
730 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
731
732 samples = [MinimalCoro()]
733 for x in samples:
734 self.assertIsInstance(x, Awaitable)
735 self.assertTrue(issubclass(type(x), Awaitable))
736
737 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400738 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
739 # flag don't have '__await__' method, hence can't be instances
740 # of Coroutine. Use inspect.isawaitable to detect them.
741 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400742
743 c = new_coro()
744 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300745 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400746
Yury Selivanov56fc6142015-05-29 09:01:29 -0400747 class CoroLike:
748 def send(self, value):
749 pass
750 def throw(self, typ, val=None, tb=None):
751 pass
752 def close(self):
753 pass
754 def __await__(self):
755 pass
756 self.assertTrue(isinstance(CoroLike(), Coroutine))
757 self.assertTrue(issubclass(CoroLike, Coroutine))
758
759 class CoroLike:
760 def send(self, value):
761 pass
762 def close(self):
763 pass
764 def __await__(self):
765 pass
766 self.assertFalse(isinstance(CoroLike(), Coroutine))
767 self.assertFalse(issubclass(CoroLike, Coroutine))
768
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000769 def test_Hashable(self):
770 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000771 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000772 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000773 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000774 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000775 # Check some hashables
776 samples = [None,
777 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000778 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000779 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000780 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000781 ]
782 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000783 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000784 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000785 self.assertRaises(TypeError, Hashable)
786 # Check direct subclassing
787 class H(Hashable):
788 def __hash__(self):
789 return super().__hash__()
790 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000791 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000792 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000793 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000794
Yury Selivanove0104ae2015-05-14 12:19:16 -0400795 def test_AsyncIterable(self):
796 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400797 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400798 return self
799 self.assertTrue(isinstance(AI(), AsyncIterable))
800 self.assertTrue(issubclass(AI, AsyncIterable))
801 # Check some non-iterables
802 non_samples = [None, object, []]
803 for x in non_samples:
804 self.assertNotIsInstance(x, AsyncIterable)
805 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
806 self.validate_abstract_methods(AsyncIterable, '__aiter__')
807 self.validate_isinstance(AsyncIterable, '__aiter__')
808
809 def test_AsyncIterator(self):
810 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400811 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400812 return self
813 async def __anext__(self):
814 raise StopAsyncIteration
815 self.assertTrue(isinstance(AI(), AsyncIterator))
816 self.assertTrue(issubclass(AI, AsyncIterator))
817 non_samples = [None, object, []]
818 # Check some non-iterables
819 for x in non_samples:
820 self.assertNotIsInstance(x, AsyncIterator)
821 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
822 # Similarly to regular iterators (see issue 10565)
823 class AnextOnly:
824 async def __anext__(self):
825 raise StopAsyncIteration
826 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
827 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
828
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000829 def test_Iterable(self):
830 # Check some non-iterables
831 non_samples = [None, 42, 3.14, 1j]
832 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000833 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000834 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000835 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000836 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000837 tuple(), list(), set(), frozenset(), dict(),
838 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700839 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000840 (x for x in []),
841 ]
842 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000843 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000844 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000845 # Check direct subclassing
846 class I(Iterable):
847 def __iter__(self):
848 return super().__iter__()
849 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000850 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000851 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000852 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700853 # Check None blocking
854 class It:
855 def __iter__(self): return iter([])
856 class ItBlocked(It):
857 __iter__ = None
858 self.assertTrue(issubclass(It, Iterable))
859 self.assertTrue(isinstance(It(), Iterable))
860 self.assertFalse(issubclass(ItBlocked, Iterable))
861 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000862
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700863 def test_Reversible(self):
864 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100865 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700866 for x in non_samples:
867 self.assertNotIsInstance(x, Reversible)
868 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700869 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100870 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700871 for x in non_reversibles:
872 self.assertNotIsInstance(x, Reversible)
873 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
874 # Check some reversible iterables
875 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
876 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100877 OrderedDict().values(), Counter(), Counter().keys(),
878 Counter().items(), Counter().values(), dict(),
879 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700880 for x in samples:
881 self.assertIsInstance(x, Reversible)
882 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
883 # Check also Mapping, MutableMapping, and Sequence
884 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
885 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
886 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
887 # Check direct subclassing
888 class R(Reversible):
889 def __iter__(self):
890 return iter(list())
891 def __reversed__(self):
892 return iter(list())
893 self.assertEqual(list(reversed(R())), [])
894 self.assertFalse(issubclass(float, R))
895 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700896 # Check reversible non-iterable (which is not Reversible)
897 class RevNoIter:
898 def __reversed__(self): return reversed([])
899 class RevPlusIter(RevNoIter):
900 def __iter__(self): return iter([])
901 self.assertFalse(issubclass(RevNoIter, Reversible))
902 self.assertFalse(isinstance(RevNoIter(), Reversible))
903 self.assertTrue(issubclass(RevPlusIter, Reversible))
904 self.assertTrue(isinstance(RevPlusIter(), Reversible))
905 # Check None blocking
906 class Rev:
907 def __iter__(self): return iter([])
908 def __reversed__(self): return reversed([])
909 class RevItBlocked(Rev):
910 __iter__ = None
911 class RevRevBlocked(Rev):
912 __reversed__ = None
913 self.assertTrue(issubclass(Rev, Reversible))
914 self.assertTrue(isinstance(Rev(), Reversible))
915 self.assertFalse(issubclass(RevItBlocked, Reversible))
916 self.assertFalse(isinstance(RevItBlocked(), Reversible))
917 self.assertFalse(issubclass(RevRevBlocked, Reversible))
918 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700919
Guido van Rossumf0666942016-08-23 10:47:07 -0700920 def test_Collection(self):
921 # Check some non-collections
922 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
923 for x in non_collections:
924 self.assertNotIsInstance(x, Collection)
925 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
926 # Check some non-collection iterables
927 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -0800928 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -0700929 for x in non_col_iterables:
930 self.assertNotIsInstance(x, Collection)
931 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
932 # Check some collections
933 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -0800934 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -0700935 for x in samples:
936 self.assertIsInstance(x, Collection)
937 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
938 # Check also Mapping, MutableMapping, etc.
939 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
940 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
941 self.assertTrue(issubclass(MutableMapping, Collection),
942 repr(MutableMapping))
943 self.assertTrue(issubclass(Set, Collection), repr(Set))
944 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
945 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
946 # Check direct subclassing
947 class Col(Collection):
948 def __iter__(self):
949 return iter(list())
950 def __len__(self):
951 return 0
952 def __contains__(self, item):
953 return False
954 class DerCol(Col): pass
955 self.assertEqual(list(iter(Col())), [])
956 self.assertFalse(issubclass(list, Col))
957 self.assertFalse(issubclass(set, Col))
958 self.assertFalse(issubclass(float, Col))
959 self.assertEqual(list(iter(DerCol())), [])
960 self.assertFalse(issubclass(list, DerCol))
961 self.assertFalse(issubclass(set, DerCol))
962 self.assertFalse(issubclass(float, DerCol))
963 self.validate_abstract_methods(Collection, '__len__', '__iter__',
964 '__contains__')
965 # Check sized container non-iterable (which is not Collection) etc.
966 class ColNoIter:
967 def __len__(self): return 0
968 def __contains__(self, item): return False
969 class ColNoSize:
970 def __iter__(self): return iter([])
971 def __contains__(self, item): return False
972 class ColNoCont:
973 def __iter__(self): return iter([])
974 def __len__(self): return 0
975 self.assertFalse(issubclass(ColNoIter, Collection))
976 self.assertFalse(isinstance(ColNoIter(), Collection))
977 self.assertFalse(issubclass(ColNoSize, Collection))
978 self.assertFalse(isinstance(ColNoSize(), Collection))
979 self.assertFalse(issubclass(ColNoCont, Collection))
980 self.assertFalse(isinstance(ColNoCont(), Collection))
981 # Check None blocking
982 class SizeBlock:
983 def __iter__(self): return iter([])
984 def __contains__(self): return False
985 __len__ = None
986 class IterBlock:
987 def __len__(self): return 0
988 def __contains__(self): return True
989 __iter__ = None
990 self.assertFalse(issubclass(SizeBlock, Collection))
991 self.assertFalse(isinstance(SizeBlock(), Collection))
992 self.assertFalse(issubclass(IterBlock, Collection))
993 self.assertFalse(isinstance(IterBlock(), Collection))
994 # Check None blocking in subclass
995 class ColImpl:
996 def __iter__(self):
997 return iter(list())
998 def __len__(self):
999 return 0
1000 def __contains__(self, item):
1001 return False
1002 class NonCol(ColImpl):
1003 __contains__ = None
1004 self.assertFalse(issubclass(NonCol, Collection))
1005 self.assertFalse(isinstance(NonCol(), Collection))
1006
1007
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001008 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001009 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001010 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001011 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001012 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001013 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001014 iter(tuple()), iter(list()), iter(dict()),
1015 iter(set()), iter(frozenset()),
1016 iter(dict().keys()), iter(dict().items()),
1017 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001018 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001019 (x for x in []),
1020 ]
1021 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001022 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001023 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001024 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1025
1026 # Issue 10565
1027 class NextOnly:
1028 def __next__(self):
1029 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001030 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001031 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001032
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001033 def test_Generator(self):
1034 class NonGen1:
1035 def __iter__(self): return self
1036 def __next__(self): return None
1037 def close(self): pass
1038 def throw(self, typ, val=None, tb=None): pass
1039
1040 class NonGen2:
1041 def __iter__(self): return self
1042 def __next__(self): return None
1043 def close(self): pass
1044 def send(self, value): return value
1045
1046 class NonGen3:
1047 def close(self): pass
1048 def send(self, value): return value
1049 def throw(self, typ, val=None, tb=None): pass
1050
1051 non_samples = [
1052 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1053 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1054 for x in non_samples:
1055 self.assertNotIsInstance(x, Generator)
1056 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1057
1058 class Gen:
1059 def __iter__(self): return self
1060 def __next__(self): return None
1061 def close(self): pass
1062 def send(self, value): return value
1063 def throw(self, typ, val=None, tb=None): pass
1064
1065 class MinimalGen(Generator):
1066 def send(self, value):
1067 return value
1068 def throw(self, typ, val=None, tb=None):
1069 super().throw(typ, val, tb)
1070
1071 def gen():
1072 yield 1
1073
1074 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1075 for x in samples:
1076 self.assertIsInstance(x, Iterator)
1077 self.assertIsInstance(x, Generator)
1078 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1079 self.validate_abstract_methods(Generator, 'send', 'throw')
1080
1081 # mixin tests
1082 mgen = MinimalGen()
1083 self.assertIs(mgen, iter(mgen))
1084 self.assertIs(mgen.send(None), next(mgen))
1085 self.assertEqual(2, mgen.send(2))
1086 self.assertIsNone(mgen.close())
1087 self.assertRaises(ValueError, mgen.throw, ValueError)
1088 self.assertRaisesRegex(ValueError, "^huhu$",
1089 mgen.throw, ValueError, ValueError("huhu"))
1090 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1091
1092 class FailOnClose(Generator):
1093 def send(self, value): return value
1094 def throw(self, *args): raise ValueError
1095
1096 self.assertRaises(ValueError, FailOnClose().close)
1097
1098 class IgnoreGeneratorExit(Generator):
1099 def send(self, value): return value
1100 def throw(self, *args): pass
1101
1102 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1103
Yury Selivanov22214ab2016-11-16 18:25:04 -05001104 def test_AsyncGenerator(self):
1105 class NonAGen1:
1106 def __aiter__(self): return self
1107 def __anext__(self): return None
1108 def aclose(self): pass
1109 def athrow(self, typ, val=None, tb=None): pass
1110
1111 class NonAGen2:
1112 def __aiter__(self): return self
1113 def __anext__(self): return None
1114 def aclose(self): pass
1115 def asend(self, value): return value
1116
1117 class NonAGen3:
1118 def aclose(self): pass
1119 def asend(self, value): return value
1120 def athrow(self, typ, val=None, tb=None): pass
1121
1122 non_samples = [
1123 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1124 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1125 for x in non_samples:
1126 self.assertNotIsInstance(x, AsyncGenerator)
1127 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1128
1129 class Gen:
1130 def __aiter__(self): return self
1131 async def __anext__(self): return None
1132 async def aclose(self): pass
1133 async def asend(self, value): return value
1134 async def athrow(self, typ, val=None, tb=None): pass
1135
1136 class MinimalAGen(AsyncGenerator):
1137 async def asend(self, value):
1138 return value
1139 async def athrow(self, typ, val=None, tb=None):
1140 await super().athrow(typ, val, tb)
1141
1142 async def gen():
1143 yield 1
1144
1145 samples = [gen(), Gen(), MinimalAGen()]
1146 for x in samples:
1147 self.assertIsInstance(x, AsyncIterator)
1148 self.assertIsInstance(x, AsyncGenerator)
1149 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1150 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1151
1152 def run_async(coro):
1153 result = None
1154 while True:
1155 try:
1156 coro.send(None)
1157 except StopIteration as ex:
1158 result = ex.args[0] if ex.args else None
1159 break
1160 return result
1161
1162 # mixin tests
1163 mgen = MinimalAGen()
1164 self.assertIs(mgen, mgen.__aiter__())
1165 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1166 self.assertEqual(2, run_async(mgen.asend(2)))
1167 self.assertIsNone(run_async(mgen.aclose()))
1168 with self.assertRaises(ValueError):
1169 run_async(mgen.athrow(ValueError))
1170
1171 class FailOnClose(AsyncGenerator):
1172 async def asend(self, value): return value
1173 async def athrow(self, *args): raise ValueError
1174
1175 with self.assertRaises(ValueError):
1176 run_async(FailOnClose().aclose())
1177
1178 class IgnoreGeneratorExit(AsyncGenerator):
1179 async def asend(self, value): return value
1180 async def athrow(self, *args): pass
1181
1182 with self.assertRaises(RuntimeError):
1183 run_async(IgnoreGeneratorExit().aclose())
1184
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001185 def test_Sized(self):
1186 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001187 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001188 (x for x in []),
1189 ]
1190 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001191 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001192 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001193 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001194 tuple(), list(), set(), frozenset(), dict(),
1195 dict().keys(), dict().items(), dict().values(),
1196 ]
1197 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001198 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001199 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001200 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001201 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001202
1203 def test_Container(self):
1204 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001205 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001206 (x for x in []),
1207 ]
1208 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001209 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001210 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001211 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001212 tuple(), list(), set(), frozenset(), dict(),
1213 dict().keys(), dict().items(),
1214 ]
1215 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001216 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001217 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001218 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001219 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001220
1221 def test_Callable(self):
1222 non_samples = [None, 42, 3.14, 1j,
1223 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001224 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001225 (x for x in []),
1226 ]
1227 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001228 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001229 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001230 samples = [lambda: None,
1231 type, int, object,
1232 len,
1233 list.append, [].append,
1234 ]
1235 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001236 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001237 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001238 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001239 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001240
1241 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001242 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001243 class C(B):
1244 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001245 self.assertTrue(issubclass(C, B))
1246 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001247
1248 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001249 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001250 class C:
1251 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001252 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001253 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001254 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001255
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001256class WithSet(MutableSet):
1257
1258 def __init__(self, it=()):
1259 self.data = set(it)
1260
1261 def __len__(self):
1262 return len(self.data)
1263
1264 def __iter__(self):
1265 return iter(self.data)
1266
1267 def __contains__(self, item):
1268 return item in self.data
1269
1270 def add(self, item):
1271 self.data.add(item)
1272
1273 def discard(self, item):
1274 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001275
Raymond Hettingerae650182009-01-28 23:33:59 +00001276class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001277
1278 # XXX For now, we only test some virtual inheritance properties.
1279 # We should also test the proper behavior of the collection ABCs
1280 # as real base classes or mix-in classes.
1281
1282 def test_Set(self):
1283 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001284 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001285 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001286 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001287 class MySet(Set):
1288 def __contains__(self, x):
1289 return False
1290 def __len__(self):
1291 return 0
1292 def __iter__(self):
1293 return iter([])
1294 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001295
Benjamin Peterson41181742008-07-02 20:22:54 +00001296 def test_hash_Set(self):
1297 class OneTwoThreeSet(Set):
1298 def __init__(self):
1299 self.contents = [1, 2, 3]
1300 def __contains__(self, x):
1301 return x in self.contents
1302 def __len__(self):
1303 return len(self.contents)
1304 def __iter__(self):
1305 return iter(self.contents)
1306 def __hash__(self):
1307 return self._hash()
1308 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001309 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001310
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001311 def test_isdisjoint_Set(self):
1312 class MySet(Set):
1313 def __init__(self, itr):
1314 self.contents = itr
1315 def __contains__(self, x):
1316 return x in self.contents
1317 def __iter__(self):
1318 return iter(self.contents)
1319 def __len__(self):
1320 return len([x for x in self.contents])
1321 s1 = MySet((1, 2, 3))
1322 s2 = MySet((4, 5, 6))
1323 s3 = MySet((1, 5, 6))
1324 self.assertTrue(s1.isdisjoint(s2))
1325 self.assertFalse(s1.isdisjoint(s3))
1326
1327 def test_equality_Set(self):
1328 class MySet(Set):
1329 def __init__(self, itr):
1330 self.contents = itr
1331 def __contains__(self, x):
1332 return x in self.contents
1333 def __iter__(self):
1334 return iter(self.contents)
1335 def __len__(self):
1336 return len([x for x in self.contents])
1337 s1 = MySet((1,))
1338 s2 = MySet((1, 2))
1339 s3 = MySet((3, 4))
1340 s4 = MySet((3, 4))
1341 self.assertTrue(s2 > s1)
1342 self.assertTrue(s1 < s2)
1343 self.assertFalse(s2 <= s1)
1344 self.assertFalse(s2 <= s3)
1345 self.assertFalse(s1 >= s2)
1346 self.assertEqual(s3, s4)
1347 self.assertNotEqual(s2, s3)
1348
1349 def test_arithmetic_Set(self):
1350 class MySet(Set):
1351 def __init__(self, itr):
1352 self.contents = itr
1353 def __contains__(self, x):
1354 return x in self.contents
1355 def __iter__(self):
1356 return iter(self.contents)
1357 def __len__(self):
1358 return len([x for x in self.contents])
1359 s1 = MySet((1, 2, 3))
1360 s2 = MySet((3, 4, 5))
1361 s3 = s1 & s2
1362 self.assertEqual(s3, MySet((3,)))
1363
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001364 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001365 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001366 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001367 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001368 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001369 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1370 'add', 'discard')
1371
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001372 def test_issue_5647(self):
1373 # MutableSet.__iand__ mutated the set during iteration
1374 s = WithSet('abcd')
1375 s &= WithSet('cdef') # This used to fail
1376 self.assertEqual(set(s), set('cd'))
1377
Raymond Hettingerae650182009-01-28 23:33:59 +00001378 def test_issue_4920(self):
1379 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001380 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001381 __slots__=['__s']
1382 def __init__(self,items=None):
1383 if items is None:
1384 items=[]
1385 self.__s=set(items)
1386 def __contains__(self,v):
1387 return v in self.__s
1388 def __iter__(self):
1389 return iter(self.__s)
1390 def __len__(self):
1391 return len(self.__s)
1392 def add(self,v):
1393 result=v not in self.__s
1394 self.__s.add(v)
1395 return result
1396 def discard(self,v):
1397 result=v in self.__s
1398 self.__s.discard(v)
1399 return result
1400 def __repr__(self):
1401 return "MySet(%s)" % repr(list(self))
1402 s = MySet([5,43,2,1])
1403 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001404
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001405 def test_issue8750(self):
1406 empty = WithSet()
1407 full = WithSet(range(10))
1408 s = WithSet(full)
1409 s -= s
1410 self.assertEqual(s, empty)
1411 s = WithSet(full)
1412 s ^= s
1413 self.assertEqual(s, empty)
1414 s = WithSet(full)
1415 s &= s
1416 self.assertEqual(s, full)
1417 s |= s
1418 self.assertEqual(s, full)
1419
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001420 def test_issue16373(self):
1421 # Recursion error comparing comparable and noncomparable
1422 # Set instances
1423 class MyComparableSet(Set):
1424 def __contains__(self, x):
1425 return False
1426 def __len__(self):
1427 return 0
1428 def __iter__(self):
1429 return iter([])
1430 class MyNonComparableSet(Set):
1431 def __contains__(self, x):
1432 return False
1433 def __len__(self):
1434 return 0
1435 def __iter__(self):
1436 return iter([])
1437 def __le__(self, x):
1438 return NotImplemented
1439 def __lt__(self, x):
1440 return NotImplemented
1441
1442 cs = MyComparableSet()
1443 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001444 self.assertFalse(ncs < cs)
1445 self.assertTrue(ncs <= cs)
1446 self.assertFalse(ncs > cs)
1447 self.assertTrue(ncs >= cs)
1448
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001449 def test_issue26915(self):
1450 # Container membership test should check identity first
1451 class CustomEqualObject:
1452 def __eq__(self, other):
1453 return False
Xiang Zhangd5d32492017-03-08 11:04:24 +08001454 class CustomSequence(Sequence):
1455 def __init__(self, seq):
1456 self._seq = seq
1457 def __getitem__(self, index):
1458 return self._seq[index]
1459 def __len__(self):
1460 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001461
1462 nan = float('nan')
1463 obj = CustomEqualObject()
Xiang Zhangd5d32492017-03-08 11:04:24 +08001464 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001465 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001466 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001467 ItemsView({1: nan, 2: obj}),
1468 ValuesView({1: nan, 2: obj})
1469 ]
1470 for container in containers:
1471 for elem in container:
1472 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001473 self.assertEqual(seq.index(nan), 0)
1474 self.assertEqual(seq.index(obj), 1)
1475 self.assertEqual(seq.count(nan), 2)
1476 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001477
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001478 def assertSameSet(self, s1, s2):
1479 # coerce both to a real set then check equality
1480 self.assertSetEqual(set(s1), set(s2))
1481
1482 def test_Set_interoperability_with_real_sets(self):
1483 # Issue: 8743
1484 class ListSet(Set):
1485 def __init__(self, elements=()):
1486 self.data = []
1487 for elem in elements:
1488 if elem not in self.data:
1489 self.data.append(elem)
1490 def __contains__(self, elem):
1491 return elem in self.data
1492 def __iter__(self):
1493 return iter(self.data)
1494 def __len__(self):
1495 return len(self.data)
1496 def __repr__(self):
1497 return 'Set({!r})'.format(self.data)
1498
1499 r1 = set('abc')
1500 r2 = set('bcd')
1501 r3 = set('abcde')
1502 f1 = ListSet('abc')
1503 f2 = ListSet('bcd')
1504 f3 = ListSet('abcde')
1505 l1 = list('abccba')
1506 l2 = list('bcddcb')
1507 l3 = list('abcdeedcba')
1508
1509 target = r1 & r2
1510 self.assertSameSet(f1 & f2, target)
1511 self.assertSameSet(f1 & r2, target)
1512 self.assertSameSet(r2 & f1, target)
1513 self.assertSameSet(f1 & l2, target)
1514
1515 target = r1 | r2
1516 self.assertSameSet(f1 | f2, target)
1517 self.assertSameSet(f1 | r2, target)
1518 self.assertSameSet(r2 | f1, target)
1519 self.assertSameSet(f1 | l2, target)
1520
1521 fwd_target = r1 - r2
1522 rev_target = r2 - r1
1523 self.assertSameSet(f1 - f2, fwd_target)
1524 self.assertSameSet(f2 - f1, rev_target)
1525 self.assertSameSet(f1 - r2, fwd_target)
1526 self.assertSameSet(f2 - r1, rev_target)
1527 self.assertSameSet(r1 - f2, fwd_target)
1528 self.assertSameSet(r2 - f1, rev_target)
1529 self.assertSameSet(f1 - l2, fwd_target)
1530 self.assertSameSet(f2 - l1, rev_target)
1531
1532 target = r1 ^ r2
1533 self.assertSameSet(f1 ^ f2, target)
1534 self.assertSameSet(f1 ^ r2, target)
1535 self.assertSameSet(r2 ^ f1, target)
1536 self.assertSameSet(f1 ^ l2, target)
1537
1538 # Don't change the following to use assertLess or other
1539 # "more specific" unittest assertions. The current
1540 # assertTrue/assertFalse style makes the pattern of test
1541 # case combinations clear and allows us to know for sure
1542 # the exact operator being invoked.
1543
1544 # proper subset
1545 self.assertTrue(f1 < f3)
1546 self.assertFalse(f1 < f1)
1547 self.assertFalse(f1 < f2)
1548 self.assertTrue(r1 < f3)
1549 self.assertFalse(r1 < f1)
1550 self.assertFalse(r1 < f2)
1551 self.assertTrue(r1 < r3)
1552 self.assertFalse(r1 < r1)
1553 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001554 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001555 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001556 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001557 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001558 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001559 f1 < l2
1560
1561 # any subset
1562 self.assertTrue(f1 <= f3)
1563 self.assertTrue(f1 <= f1)
1564 self.assertFalse(f1 <= f2)
1565 self.assertTrue(r1 <= f3)
1566 self.assertTrue(r1 <= f1)
1567 self.assertFalse(r1 <= f2)
1568 self.assertTrue(r1 <= r3)
1569 self.assertTrue(r1 <= r1)
1570 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001571 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001572 f1 <= l3
1573 with self.assertRaises(TypeError):
1574 f1 <= l1
1575 with self.assertRaises(TypeError):
1576 f1 <= l2
1577
1578 # proper superset
1579 self.assertTrue(f3 > f1)
1580 self.assertFalse(f1 > f1)
1581 self.assertFalse(f2 > f1)
1582 self.assertTrue(r3 > r1)
1583 self.assertFalse(f1 > r1)
1584 self.assertFalse(f2 > r1)
1585 self.assertTrue(r3 > r1)
1586 self.assertFalse(r1 > r1)
1587 self.assertFalse(r2 > r1)
1588 with self.assertRaises(TypeError):
1589 f1 > l3
1590 with self.assertRaises(TypeError):
1591 f1 > l1
1592 with self.assertRaises(TypeError):
1593 f1 > l2
1594
1595 # any superset
1596 self.assertTrue(f3 >= f1)
1597 self.assertTrue(f1 >= f1)
1598 self.assertFalse(f2 >= f1)
1599 self.assertTrue(r3 >= r1)
1600 self.assertTrue(f1 >= r1)
1601 self.assertFalse(f2 >= r1)
1602 self.assertTrue(r3 >= r1)
1603 self.assertTrue(r1 >= r1)
1604 self.assertFalse(r2 >= r1)
1605 with self.assertRaises(TypeError):
1606 f1 >= l3
1607 with self.assertRaises(TypeError):
1608 f1 >=l1
1609 with self.assertRaises(TypeError):
1610 f1 >= l2
1611
1612 # equality
1613 self.assertTrue(f1 == f1)
1614 self.assertTrue(r1 == f1)
1615 self.assertTrue(f1 == r1)
1616 self.assertFalse(f1 == f3)
1617 self.assertFalse(r1 == f3)
1618 self.assertFalse(f1 == r3)
1619 self.assertFalse(f1 == l3)
1620 self.assertFalse(f1 == l1)
1621 self.assertFalse(f1 == l2)
1622
1623 # inequality
1624 self.assertFalse(f1 != f1)
1625 self.assertFalse(r1 != f1)
1626 self.assertFalse(f1 != r1)
1627 self.assertTrue(f1 != f3)
1628 self.assertTrue(r1 != f3)
1629 self.assertTrue(f1 != r3)
1630 self.assertTrue(f1 != l3)
1631 self.assertTrue(f1 != l1)
1632 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001633
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001634 def test_Mapping(self):
1635 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001636 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001637 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001638 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1639 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001640 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001641 def __len__(self):
1642 return 0
1643 def __getitem__(self, i):
1644 raise IndexError
1645 def __iter__(self):
1646 return iter(())
1647 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001648 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001649
1650 def test_MutableMapping(self):
1651 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001652 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001653 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001654 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1655 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001656
Raymond Hettinger9117c752010-08-22 07:44:24 +00001657 def test_MutableMapping_subclass(self):
1658 # Test issue 9214
1659 mymap = UserDict()
1660 mymap['red'] = 5
1661 self.assertIsInstance(mymap.keys(), Set)
1662 self.assertIsInstance(mymap.keys(), KeysView)
1663 self.assertIsInstance(mymap.items(), Set)
1664 self.assertIsInstance(mymap.items(), ItemsView)
1665
1666 mymap = UserDict()
1667 mymap['red'] = 5
1668 z = mymap.keys() | {'orange'}
1669 self.assertIsInstance(z, set)
1670 list(z)
1671 mymap['blue'] = 7 # Shouldn't affect 'z'
1672 self.assertEqual(sorted(z), ['orange', 'red'])
1673
1674 mymap = UserDict()
1675 mymap['red'] = 5
1676 z = mymap.items() | {('orange', 3)}
1677 self.assertIsInstance(z, set)
1678 list(z)
1679 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001680 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001681
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001682 def test_Sequence(self):
1683 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001684 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001685 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001686 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001687 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001688 self.assertIsInstance(memoryview(b""), Sequence)
1689 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001690 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001691 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1692 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001693
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001694 def test_Sequence_mixins(self):
1695 class SequenceSubclass(Sequence):
1696 def __init__(self, seq=()):
1697 self.seq = seq
1698
1699 def __getitem__(self, index):
1700 return self.seq[index]
1701
1702 def __len__(self):
1703 return len(self.seq)
1704
1705 # Compare Sequence.index() behavior to (list|str).index() behavior
1706 def assert_index_same(seq1, seq2, index_args):
1707 try:
1708 expected = seq1.index(*index_args)
1709 except ValueError:
1710 with self.assertRaises(ValueError):
1711 seq2.index(*index_args)
1712 else:
1713 actual = seq2.index(*index_args)
1714 self.assertEqual(
1715 actual, expected, '%r.index%s' % (seq1, index_args))
1716
1717 for ty in list, str:
1718 nativeseq = ty('abracadabra')
1719 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1720 seqseq = SequenceSubclass(nativeseq)
1721 for letter in set(nativeseq) | {'z'}:
1722 assert_index_same(nativeseq, seqseq, (letter,))
1723 for start in range(-3, len(nativeseq) + 3):
1724 assert_index_same(nativeseq, seqseq, (letter, start))
1725 for stop in range(-3, len(nativeseq) + 3):
1726 assert_index_same(
1727 nativeseq, seqseq, (letter, start, stop))
1728
Guido van Rossumd05eb002007-11-21 22:26:24 +00001729 def test_ByteString(self):
1730 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001731 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001732 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001733 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001734 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001735 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001736 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001737 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001738
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001739 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001740 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001741 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001742 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001743 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001744 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001745 self.assertTrue(issubclass(sample, MutableSequence))
1746 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001747 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1748 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001749
Eli Bendersky0716a572011-03-04 10:38:14 +00001750 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001751 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001752 # class inherited from it.
1753 class MutableSequenceSubclass(MutableSequence):
1754 def __init__(self):
1755 self.lst = []
1756
1757 def __setitem__(self, index, value):
1758 self.lst[index] = value
1759
1760 def __getitem__(self, index):
1761 return self.lst[index]
1762
1763 def __len__(self):
1764 return len(self.lst)
1765
1766 def __delitem__(self, index):
1767 del self.lst[index]
1768
1769 def insert(self, index, value):
1770 self.lst.insert(index, value)
1771
1772 mss = MutableSequenceSubclass()
1773 mss.append(0)
1774 mss.extend((1, 2, 3, 4))
1775 self.assertEqual(len(mss), 5)
1776 self.assertEqual(mss[3], 3)
1777 mss.reverse()
1778 self.assertEqual(mss[3], 1)
1779 mss.pop()
1780 self.assertEqual(len(mss), 4)
1781 mss.remove(3)
1782 self.assertEqual(len(mss), 3)
1783 mss += (10, 20, 30)
1784 self.assertEqual(len(mss), 6)
1785 self.assertEqual(mss[-1], 30)
1786 mss.clear()
1787 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001788
Naris R1b5f9c92018-08-31 02:56:14 +10001789 # issue 34427
1790 # extending self should not cause infinite loop
1791 items = 'ABCD'
1792 mss2 = MutableSequenceSubclass()
1793 mss2.extend(items + items)
1794 mss.clear()
1795 mss.extend(items)
1796 mss.extend(mss)
1797 self.assertEqual(len(mss), len(mss2))
1798 self.assertEqual(list(mss), list(mss2))
1799
1800
Raymond Hettinger499e1932011-02-23 07:56:53 +00001801################################################################################
1802### Counter
1803################################################################################
1804
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001805class CounterSubclassWithSetItem(Counter):
1806 # Test a counter subclass that overrides __setitem__
1807 def __init__(self, *args, **kwds):
1808 self.called = False
1809 Counter.__init__(self, *args, **kwds)
1810 def __setitem__(self, key, value):
1811 self.called = True
1812 Counter.__setitem__(self, key, value)
1813
1814class CounterSubclassWithGet(Counter):
1815 # Test a counter subclass that overrides get()
1816 def __init__(self, *args, **kwds):
1817 self.called = False
1818 Counter.__init__(self, *args, **kwds)
1819 def get(self, key, default):
1820 self.called = True
1821 return Counter.get(self, key, default)
1822
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001823class TestCounter(unittest.TestCase):
1824
1825 def test_basics(self):
1826 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001827 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1828 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001829 self.assertIsInstance(c, dict)
1830 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001831 self.assertTrue(issubclass(Counter, dict))
1832 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001833 self.assertEqual(len(c), 3)
1834 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001835 self.assertEqual(list(c.values()), [3, 2, 1])
1836 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1837 self.assertEqual(list(c), ['a', 'b', 'c'])
1838 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001839 [('a', 3), ('b', 2), ('c', 1)])
1840 self.assertEqual(c['b'], 2)
1841 self.assertEqual(c['z'], 0)
1842 self.assertEqual(c.__contains__('c'), True)
1843 self.assertEqual(c.__contains__('z'), False)
1844 self.assertEqual(c.get('b', 10), 2)
1845 self.assertEqual(c.get('z', 10), 10)
1846 self.assertEqual(c, dict(a=3, b=2, c=1))
1847 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1848 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1849 for i in range(5):
1850 self.assertEqual(c.most_common(i),
1851 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001852 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001853 c['a'] += 1 # increment an existing value
1854 c['b'] -= 2 # sub existing value to zero
1855 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001856 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001857 c['d'] -= 2 # sub from a missing value
1858 c['e'] = -5 # directly assign a missing value
1859 c['f'] += 4 # add to a missing value
1860 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001861 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001862 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001863 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001864 for i in range(3):
1865 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001866 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001867 c.clear()
1868 self.assertEqual(c, {})
1869 self.assertEqual(repr(c), 'Counter()')
1870 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1871 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001872 c.update(dict(a=5, b=3))
1873 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001874 c.update(Counter('a' * 50 + 'b' * 30))
1875 c.update() # test case with no args
1876 c.__init__('a' * 500 + 'b' * 300)
1877 c.__init__('cdc')
1878 c.__init__()
1879 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1880 self.assertEqual(c.setdefault('d', 5), 1)
1881 self.assertEqual(c['d'], 1)
1882 self.assertEqual(c.setdefault('e', 5), 5)
1883 self.assertEqual(c['e'], 5)
1884
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001885 def test_init(self):
1886 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1887 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1888 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1889 self.assertRaises(TypeError, Counter, 42)
1890 self.assertRaises(TypeError, Counter, (), ())
1891 self.assertRaises(TypeError, Counter.__init__)
1892
Raymond Hettinger407c7342019-02-21 09:19:00 -08001893 def test_order_preservation(self):
1894 # Input order dictates items() order
1895 self.assertEqual(list(Counter('abracadabra').items()),
1896 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
1897 # letters with same count: ^----------^ ^---------^
1898
1899 # Verify retention of order even when all counts are equal
1900 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
1901 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
1902
1903 # Input order dictates elements() order
1904 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
1905 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
1906 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
1907
1908 # Math operations order first by the order encountered in the left
1909 # operand and then by the order encounted in the right operand.
1910 ps = 'aaabbcdddeefggghhijjjkkl'
1911 qs = 'abbcccdeefffhkkllllmmnno'
1912 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
1913 def correctly_ordered(seq):
1914 'Return true if the letters occur in the expected order'
1915 positions = [order[letter] for letter in seq]
1916 return positions == sorted(positions)
1917
1918 p, q = Counter(ps), Counter(qs)
1919 self.assertTrue(correctly_ordered(+p))
1920 self.assertTrue(correctly_ordered(-p))
1921 self.assertTrue(correctly_ordered(p + q))
1922 self.assertTrue(correctly_ordered(p - q))
1923 self.assertTrue(correctly_ordered(p | q))
1924 self.assertTrue(correctly_ordered(p & q))
1925
1926 p, q = Counter(ps), Counter(qs)
1927 p += q
1928 self.assertTrue(correctly_ordered(p))
1929
1930 p, q = Counter(ps), Counter(qs)
1931 p -= q
1932 self.assertTrue(correctly_ordered(p))
1933
1934 p, q = Counter(ps), Counter(qs)
1935 p |= q
1936 self.assertTrue(correctly_ordered(p))
1937
1938 p, q = Counter(ps), Counter(qs)
1939 p &= q
1940 self.assertTrue(correctly_ordered(p))
1941
1942 p, q = Counter(ps), Counter(qs)
1943 p.update(q)
1944 self.assertTrue(correctly_ordered(p))
1945
1946 p, q = Counter(ps), Counter(qs)
1947 p.subtract(q)
1948 self.assertTrue(correctly_ordered(p))
1949
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001950 def test_update(self):
1951 c = Counter()
1952 c.update(self=42)
1953 self.assertEqual(list(c.items()), [('self', 42)])
1954 c = Counter()
1955 c.update(iterable=42)
1956 self.assertEqual(list(c.items()), [('iterable', 42)])
1957 c = Counter()
1958 c.update(iterable=None)
1959 self.assertEqual(list(c.items()), [('iterable', None)])
1960 self.assertRaises(TypeError, Counter().update, 42)
1961 self.assertRaises(TypeError, Counter().update, {}, {})
1962 self.assertRaises(TypeError, Counter.update)
1963
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001964 def test_copying(self):
1965 # Check that counters are copyable, deepcopyable, picklable, and
1966 #have a repr/eval round-trip
1967 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02001968 def check(dup):
1969 msg = "\ncopy: %s\nwords: %s" % (dup, words)
1970 self.assertIsNot(dup, words, msg)
1971 self.assertEqual(dup, words)
1972 check(words.copy())
1973 check(copy.copy(words))
1974 check(copy.deepcopy(words))
1975 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1976 with self.subTest(proto=proto):
1977 check(pickle.loads(pickle.dumps(words, proto)))
1978 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001979 update_test = Counter()
1980 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02001981 check(update_test)
1982 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001983
Raymond Hettinger1c746c22011-04-15 13:16:46 -07001984 def test_copy_subclass(self):
1985 class MyCounter(Counter):
1986 pass
1987 c = MyCounter('slartibartfast')
1988 d = c.copy()
1989 self.assertEqual(d, c)
1990 self.assertEqual(len(d), len(c))
1991 self.assertEqual(type(d), type(c))
1992
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001993 def test_conversions(self):
1994 # Convert to: set, list, dict
1995 s = 'she sells sea shells by the sea shore'
1996 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
1997 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
1998 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
1999 self.assertEqual(set(Counter(s)), set(s))
2000
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002001 def test_invariant_for_the_in_operator(self):
2002 c = Counter(a=10, b=-2, c=0)
2003 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002004 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002005 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002006
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002007 def test_multiset_operations(self):
2008 # Verify that adding a zero counter will strip zeros and negatives
2009 c = Counter(a=10, b=-2, c=0) + Counter()
2010 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002011
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002012 elements = 'abcd'
2013 for i in range(1000):
2014 # test random pairs of multisets
2015 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002016 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002017 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002018 q.update(h=1, i=-1, j=0)
2019 for counterop, numberop in [
2020 (Counter.__add__, lambda x, y: max(0, x+y)),
2021 (Counter.__sub__, lambda x, y: max(0, x-y)),
2022 (Counter.__or__, lambda x, y: max(0,x,y)),
2023 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002024 ]:
2025 result = counterop(p, q)
2026 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002027 self.assertEqual(numberop(p[x], q[x]), result[x],
2028 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002029 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002030 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002031
2032 elements = 'abcdef'
2033 for i in range(100):
2034 # verify that random multisets with no repeats are exactly like sets
2035 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2036 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2037 for counterop, setop in [
2038 (Counter.__sub__, set.__sub__),
2039 (Counter.__or__, set.__or__),
2040 (Counter.__and__, set.__and__),
2041 ]:
2042 counter_result = counterop(p, q)
2043 set_result = setop(set(p.elements()), set(q.elements()))
2044 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002045
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002046 def test_inplace_operations(self):
2047 elements = 'abcd'
2048 for i in range(1000):
2049 # test random pairs of multisets
2050 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2051 p.update(e=1, f=-1, g=0)
2052 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2053 q.update(h=1, i=-1, j=0)
2054 for inplace_op, regular_op in [
2055 (Counter.__iadd__, Counter.__add__),
2056 (Counter.__isub__, Counter.__sub__),
2057 (Counter.__ior__, Counter.__or__),
2058 (Counter.__iand__, Counter.__and__),
2059 ]:
2060 c = p.copy()
2061 c_id = id(c)
2062 regular_result = regular_op(c, q)
2063 inplace_result = inplace_op(c, q)
2064 self.assertEqual(inplace_result, regular_result)
2065 self.assertEqual(id(inplace_result), c_id)
2066
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002067 def test_subtract(self):
2068 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2069 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2070 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2071 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2072 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2073 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2074 c = Counter('aaabbcd')
2075 c.subtract('aaaabbcce')
2076 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002077
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002078 c = Counter()
2079 c.subtract(self=42)
2080 self.assertEqual(list(c.items()), [('self', -42)])
2081 c = Counter()
2082 c.subtract(iterable=42)
2083 self.assertEqual(list(c.items()), [('iterable', -42)])
2084 self.assertRaises(TypeError, Counter().subtract, 42)
2085 self.assertRaises(TypeError, Counter().subtract, {}, {})
2086 self.assertRaises(TypeError, Counter.subtract)
2087
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002088 def test_unary(self):
2089 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2090 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2091 self.assertEqual(dict(-c), dict(a=5))
2092
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002093 def test_repr_nonsortable(self):
2094 c = Counter(a=2, b=None)
2095 r = repr(c)
2096 self.assertIn("'a': 2", r)
2097 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002098
Raymond Hettinger426e0522011-01-03 02:12:02 +00002099 def test_helper_function(self):
2100 # two paths, one for real dicts and one for other mappings
2101 elems = list('abracadabra')
2102
2103 d = dict()
2104 _count_elements(d, elems)
2105 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2106
2107 m = OrderedDict()
2108 _count_elements(m, elems)
2109 self.assertEqual(m,
2110 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2111
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002112 # test fidelity to the pure python version
2113 c = CounterSubclassWithSetItem('abracadabra')
2114 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002115 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002116 c = CounterSubclassWithGet('abracadabra')
2117 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002118 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002119
Raymond Hettinger499e1932011-02-23 07:56:53 +00002120
2121################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002122### Run tests
2123################################################################################
2124
Guido van Rossumd8faa362007-04-27 19:54:29 +00002125def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002126 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002127 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002128 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002129 TestUserObjects,
2130 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002131 support.run_unittest(*test_classes)
2132 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002133
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002134
Guido van Rossumd8faa362007-04-27 19:54:29 +00002135if __name__ == "__main__":
2136 test_main(verbose=True)