blob: d1c305a4a39c9b60e628b8909f53e8b66f9c7e79 [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
Raymond Hettinger60398512020-05-28 08:35:46 -070010from itertools import product, chain, combinations
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020011import string
R. David Murray378c0cf2010-02-24 01:46:21 +000012import sys
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020013from test import support
Yury Selivanov75445082015-05-11 22:57:16 -040014import types
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020015import unittest
16
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020017from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger573b44c2015-05-22 16:56:32 -070018from collections import UserDict, UserString, UserList
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000019from collections import ChainMap
Raymond Hettinger32ea1652015-03-21 01:37:37 -070020from collections import deque
Yury Selivanov22214ab2016-11-16 18:25:04 -050021from collections.abc import Awaitable, Coroutine
22from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator
Guido van Rossum16ca06b2016-04-04 10:59:29 -070023from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
Guido van Rossumf0666942016-08-23 10:47:07 -070024from collections.abc import Sized, Container, Callable, Collection
Raymond Hettinger57d1a882011-02-23 00:46:28 +000025from collections.abc import Set, MutableSet
Raymond Hettinger584e8ae2016-05-05 11:14:06 +030026from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
Raymond Hettinger57d1a882011-02-23 00:46:28 +000027from collections.abc import Sequence, MutableSequence
28from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000029
Raymond Hettinger499e1932011-02-23 07:56:53 +000030
Raymond Hettinger573b44c2015-05-22 16:56:32 -070031class TestUserObjects(unittest.TestCase):
32 def _superset_test(self, a, b):
33 self.assertGreaterEqual(
34 set(dir(a)),
35 set(dir(b)),
36 '{a} should have all the methods of {b}'.format(
37 a=a.__name__,
38 b=b.__name__,
39 ),
40 )
Bar Harelf4e1bab2019-05-19 16:57:13 +030041
42 def _copy_test(self, obj):
43 # Test internal copy
44 obj_copy = obj.copy()
45 self.assertIsNot(obj.data, obj_copy.data)
46 self.assertEqual(obj.data, obj_copy.data)
47
48 # Test copy.copy
49 obj.test = [1234] # Make sure instance vars are also copied.
50 obj_copy = copy.copy(obj)
51 self.assertIsNot(obj.data, obj_copy.data)
52 self.assertEqual(obj.data, obj_copy.data)
53 self.assertIs(obj.test, obj_copy.test)
54
Raymond Hettinger573b44c2015-05-22 16:56:32 -070055 def test_str_protocol(self):
56 self._superset_test(UserString, str)
57
58 def test_list_protocol(self):
59 self._superset_test(UserList, list)
60
61 def test_dict_protocol(self):
62 self._superset_test(UserDict, dict)
63
Bar Harelf4e1bab2019-05-19 16:57:13 +030064 def test_list_copy(self):
65 obj = UserList()
66 obj.append(123)
67 self._copy_test(obj)
68
69 def test_dict_copy(self):
70 obj = UserDict()
71 obj[123] = "abc"
72 self._copy_test(obj)
73
Raymond Hettinger573b44c2015-05-22 16:56:32 -070074
Raymond Hettinger499e1932011-02-23 07:56:53 +000075################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000076### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000077################################################################################
78
79class TestChainMap(unittest.TestCase):
80
81 def test_basics(self):
82 c = ChainMap()
83 c['a'] = 1
84 c['b'] = 2
85 d = c.new_child()
86 d['b'] = 20
87 d['c'] = 30
88 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
89 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
90 self.assertEqual(len(d), 3) # check len
91 for key in 'abc': # check contains
92 self.assertIn(key, d)
93 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
94 self.assertEqual(d.get(k, 100), v)
95
96 del d['b'] # unmask a value
97 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
98 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
99 self.assertEqual(len(d), 3) # check len
100 for key in 'abc': # check contains
101 self.assertIn(key, d)
102 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
103 self.assertEqual(d.get(k, 100), v)
104 self.assertIn(repr(d), [ # check repr
105 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
106 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
107 ])
108
109 for e in d.copy(), copy.copy(d): # check shallow copies
110 self.assertEqual(d, e)
111 self.assertEqual(d.maps, e.maps)
112 self.assertIsNot(d, e)
113 self.assertIsNot(d.maps[0], e.maps[0])
114 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
115 self.assertIs(m1, m2)
116
Serhiy Storchakabad12572014-12-15 14:03:42 +0200117 # check deep copies
118 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
119 e = pickle.loads(pickle.dumps(d, proto))
120 self.assertEqual(d, e)
121 self.assertEqual(d.maps, e.maps)
122 self.assertIsNot(d, e)
123 for m1, m2 in zip(d.maps, e.maps):
124 self.assertIsNot(m1, m2, e)
125 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +0000126 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +0200127 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +0000128 self.assertEqual(d, e)
129 self.assertEqual(d.maps, e.maps)
130 self.assertIsNot(d, e)
131 for m1, m2 in zip(d.maps, e.maps):
132 self.assertIsNot(m1, m2, e)
133
Raymond Hettingerd0321312011-02-26 06:53:58 +0000134 f = d.new_child()
135 f['b'] = 5
136 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
137 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
138 self.assertEqual(f['b'], 5) # find first in chain
139 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +0000140
Raymond Hettinger86f093f2019-02-21 09:12:15 -0800141 def test_ordering(self):
142 # Combined order matches a series of dict updates from last to first.
143 # This test relies on the ordering of the underlying dicts.
144
145 baseline = {'music': 'bach', 'art': 'rembrandt'}
146 adjustments = {'art': 'van gogh', 'opera': 'carmen'}
147
148 cm = ChainMap(adjustments, baseline)
149
150 combined = baseline.copy()
151 combined.update(adjustments)
152
153 self.assertEqual(list(combined.items()), list(cm.items()))
154
Martin Pantereb995702016-07-28 01:11:04 +0000155 def test_constructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +0000156 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +0000157 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
158
Raymond Hettingerd0321312011-02-26 06:53:58 +0000159 def test_bool(self):
160 self.assertFalse(ChainMap())
161 self.assertFalse(ChainMap({}, {}))
162 self.assertTrue(ChainMap({1:2}, {}))
163 self.assertTrue(ChainMap({}, {1:2}))
164
Raymond Hettinger499e1932011-02-23 07:56:53 +0000165 def test_missing(self):
166 class DefaultChainMap(ChainMap):
167 def __missing__(self, key):
168 return 999
169 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
170 for k, v in dict(a=1, b=2, c=30, d=999).items():
171 self.assertEqual(d[k], v) # check __getitem__ w/missing
172 for k, v in dict(a=1, b=2, c=30, d=77).items():
173 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
174 for k, v in dict(a=True, b=True, c=True, d=False).items():
175 self.assertEqual(k in d, v) # check __contains__ w/missing
176 self.assertEqual(d.pop('a', 1001), 1, d)
177 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
178 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
179 with self.assertRaises(KeyError):
180 d.popitem()
181
Raymond Hettinger3793f952018-02-11 00:30:31 -0800182 def test_order_preservation(self):
183 d = ChainMap(
184 OrderedDict(j=0, h=88888),
185 OrderedDict(),
186 OrderedDict(i=9999, d=4444, c=3333),
187 OrderedDict(f=666, b=222, g=777, c=333, h=888),
188 OrderedDict(),
189 OrderedDict(e=55, b=22),
190 OrderedDict(a=1, b=2, c=3, d=4, e=5),
191 OrderedDict(),
192 )
193 self.assertEqual(''.join(d), 'abcdefghij')
194 self.assertEqual(list(d.items()),
195 [('a', 1), ('b', 222), ('c', 3333), ('d', 4444),
196 ('e', 55), ('f', 666), ('g', 777), ('h', 88888),
197 ('i', 9999), ('j', 0)])
198
Andreas Poehlmann0be9ce32020-11-30 17:34:15 +0100199 def test_iter_not_calling_getitem_on_maps(self):
200 class DictWithGetItem(UserDict):
201 def __init__(self, *args, **kwds):
202 self.called = False
203 UserDict.__init__(self, *args, **kwds)
204 def __getitem__(self, item):
205 self.called = True
206 UserDict.__getitem__(self, item)
207
208 d = DictWithGetItem(a=1)
209 c = ChainMap(d)
210 d.called = False
211
212 set(c) # iterate over chain map
213 self.assertFalse(d.called, '__getitem__ was called')
214
Raymond Hettinger499e1932011-02-23 07:56:53 +0000215 def test_dict_coercion(self):
216 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
217 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
218 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
219
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000220 def test_new_child(self):
221 'Tests for changes for issue #16613.'
222 c = ChainMap()
223 c['a'] = 1
224 c['b'] = 2
225 m = {'b':20, 'c': 30}
226 d = c.new_child(m)
227 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
228 self.assertIs(m, d.maps[0])
229
230 # Use a different map than a dict
231 class lowerdict(dict):
232 def __getitem__(self, key):
233 if isinstance(key, str):
234 key = key.lower()
235 return dict.__getitem__(self, key)
236 def __contains__(self, key):
237 if isinstance(key, str):
238 key = key.lower()
239 return dict.__contains__(self, key)
240
241 c = ChainMap()
242 c['a'] = 1
243 c['b'] = 2
244 m = lowerdict(b=20, c=30)
245 d = c.new_child(m)
246 self.assertIs(m, d.maps[0])
247 for key in 'abc': # check contains
248 self.assertIn(key, d)
249 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
250 self.assertEqual(d.get(k, 100), v)
251
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700252 def test_union_operators(self):
253 cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
254 cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
255 cm3 = cm1.copy()
256 d = dict(a=10, c=30)
257 pairs = [('c', 3), ('p',0)]
258
259 tmp = cm1 | cm2 # testing between chainmaps
260 self.assertEqual(tmp.maps, [cm1.maps[0] | dict(cm2), *cm1.maps[1:]])
261 cm1 |= cm2
262 self.assertEqual(tmp, cm1)
263
264 tmp = cm2 | d # testing between chainmap and mapping
265 self.assertEqual(tmp.maps, [cm2.maps[0] | d, *cm2.maps[1:]])
266 self.assertEqual((d | cm2).maps, [d | dict(cm2)])
267 cm2 |= d
268 self.assertEqual(tmp, cm2)
269
270 # testing behavior between chainmap and iterable key-value pairs
271 with self.assertRaises(TypeError):
272 cm3 | pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700273 tmp = cm3.copy()
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700274 cm3 |= pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700275 self.assertEqual(cm3.maps, [tmp.maps[0] | dict(pairs), *tmp.maps[1:]])
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700276
277 # testing proper return types for ChainMap and it's subclasses
278 class Subclass(ChainMap):
279 pass
280
281 class SubclassRor(ChainMap):
282 def __ror__(self, other):
283 return super().__ror__(other)
284
285 tmp = ChainMap() | ChainMap()
286 self.assertIs(type(tmp), ChainMap)
287 self.assertIs(type(tmp.maps[0]), dict)
288 tmp = ChainMap() | Subclass()
289 self.assertIs(type(tmp), ChainMap)
290 self.assertIs(type(tmp.maps[0]), dict)
291 tmp = Subclass() | ChainMap()
292 self.assertIs(type(tmp), Subclass)
293 self.assertIs(type(tmp.maps[0]), dict)
294 tmp = ChainMap() | SubclassRor()
295 self.assertIs(type(tmp), SubclassRor)
296 self.assertIs(type(tmp.maps[0]), dict)
297
Raymond Hettinger499e1932011-02-23 07:56:53 +0000298
299################################################################################
300### Named Tuples
301################################################################################
302
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000303TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000304
305class TestNamedTuple(unittest.TestCase):
306
307 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000308 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000309 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000310 self.assertEqual(Point.__slots__, ())
311 self.assertEqual(Point.__module__, __name__)
312 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000313 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000314
315 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
316 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
317 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
318
319 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
320 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
321 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000322 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000323 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
324
325 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000326 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000327
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000328 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000329 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000330 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000331 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000332
Christian Heimesfaf2f632008-01-06 16:59:19 +0000333 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
334 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
335
Raymond Hettinger39482072018-01-10 21:45:19 -0800336 def test_defaults(self):
337 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700338 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800339 self.assertEqual(Point(1, 2), (1, 2))
340 self.assertEqual(Point(1), (1, 20))
341 self.assertEqual(Point(), (10, 20))
342
343 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700344 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800345 self.assertEqual(Point(1, 2), (1, 2))
346 self.assertEqual(Point(1), (1, 20))
347
348 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700349 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800350 self.assertEqual(Point(1, 2), (1, 2))
351 with self.assertRaises(TypeError):
352 Point(1)
353
354 with self.assertRaises(TypeError): # catch too few args
355 Point()
356 with self.assertRaises(TypeError): # catch too many args
357 Point(1, 2, 3)
358 with self.assertRaises(TypeError): # too many defaults
359 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
360 with self.assertRaises(TypeError): # non-iterable defaults
361 Point = namedtuple('Point', 'x y', defaults=10)
362 with self.assertRaises(TypeError): # another non-iterable default
363 Point = namedtuple('Point', 'x y', defaults=False)
364
365 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700366 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800367 self.assertIsNone(Point.__new__.__defaults__, None)
368 self.assertEqual(Point(10, 20), (10, 20))
369 with self.assertRaises(TypeError): # catch too few args
370 Point(10)
371
372 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700373 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800374 self.assertEqual(Point.__new__.__defaults__, (10, 20))
375 self.assertEqual(Point(1, 2), (1, 2))
376 self.assertEqual(Point(1), (1, 20))
377 self.assertEqual(Point(), (10, 20))
378
379 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700380 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800381 self.assertEqual(Point.__new__.__defaults__, (10, 20))
382 self.assertEqual(Point(1, 2), (1, 2))
383 self.assertEqual(Point(1), (1, 20))
384 self.assertEqual(Point(), (10, 20))
385
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200386 def test_readonly(self):
387 Point = namedtuple('Point', 'x y')
388 p = Point(11, 22)
389 with self.assertRaises(AttributeError):
390 p.x = 33
391 with self.assertRaises(AttributeError):
392 del p.x
393 with self.assertRaises(TypeError):
394 p[0] = 33
395 with self.assertRaises(TypeError):
396 del p[0]
397 self.assertEqual(p.x, 11)
398 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800399
R. David Murray378c0cf2010-02-24 01:46:21 +0000400 @unittest.skipIf(sys.flags.optimize >= 2,
401 "Docstrings are omitted with -O2 and above")
402 def test_factory_doc_attr(self):
403 Point = namedtuple('Point', 'x y')
404 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200405 Point.__doc__ = '2D point'
406 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000407
Raymond Hettingereac503a2015-05-13 01:09:59 -0700408 @unittest.skipIf(sys.flags.optimize >= 2,
409 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200410 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700411 Point = namedtuple('Point', 'x y')
412 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200413 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700414 Point.x.__doc__ = 'docstring for Point.x'
415 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200416 # namedtuple can mutate doc of descriptors independently
417 Vector = namedtuple('Vector', 'x y')
418 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
419 Vector.x.__doc__ = 'docstring for Vector.x'
420 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
421
422 @support.cpython_only
423 @unittest.skipIf(sys.flags.optimize >= 2,
424 "Docstrings are omitted with -O2 and above")
425 def test_field_doc_reuse(self):
426 P = namedtuple('P', ['m', 'n'])
427 Q = namedtuple('Q', ['o', 'p'])
428 self.assertIs(P.m.__doc__, Q.o.__doc__)
429 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700430
Ammar Askara86b5222020-04-14 23:36:08 -0700431 @support.cpython_only
432 def test_field_repr(self):
433 Point = namedtuple('Point', 'x y')
434 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'Alias for field number 0')")
435 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'Alias for field number 1')")
436
437 Point.x.__doc__ = 'The x-coordinate'
438 Point.y.__doc__ = 'The y-coordinate'
439
440 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'The x-coordinate')")
441 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'The y-coordinate')")
442
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000443 def test_name_fixer(self):
444 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000445 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
446 [('abc', 'class'), ('abc', '_1')], # field has keyword
447 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
448 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
449 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
450 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000451 ]:
452 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
453
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700454 def test_module_parameter(self):
455 NT = namedtuple('NT', ['x', 'y'], module=collections)
456 self.assertEqual(NT.__module__, collections)
457
Guido van Rossumd8faa362007-04-27 19:54:29 +0000458 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000459 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000460 p = Point(11, 22)
461 self.assertEqual(p, Point(x=11, y=22))
462 self.assertEqual(p, Point(11, y=22))
463 self.assertEqual(p, Point(y=22, x=11))
464 self.assertEqual(p, Point(*(11, 22)))
465 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200466 self.assertRaises(TypeError, Point, 1) # too few args
467 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
468 with self.assertRaises(TypeError): # wrong keyword argument
469 Point(XXX=1, y=2)
470 with self.assertRaises(TypeError): # missing keyword argument
471 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000472 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000473 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200474 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
475 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
476 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
477 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000478
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000479 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000480 p._replace(x=1, error=2)
481 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000482 pass
483 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000484 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000485
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000487 Point = namedtuple('Point', 'x, y')
488 p = Point(x=11, y=22)
489 self.assertEqual(repr(p), 'Point(x=11, y=22)')
490
491 # verify that fieldspec can be a non-string sequence
492 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493 p = Point(x=11, y=22)
494 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000495
496 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000497 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000498 p = Point(11, 22)
499
Ezio Melottie9615932010-01-24 19:26:24 +0000500 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000501 self.assertEqual(p, (11, 22)) # matches a real tuple
Min ho Kimc4cacc82019-07-31 08:16:13 +1000502 self.assertEqual(tuple(p), (11, 22)) # coercible to a real tuple
503 self.assertEqual(list(p), [11, 22]) # coercible to a list
Guido van Rossumd8faa362007-04-27 19:54:29 +0000504 self.assertEqual(max(p), 22) # iterable
505 self.assertEqual(max(*p), 22) # star-able
506 x, y = p
507 self.assertEqual(p, (x, y)) # unpacks like a tuple
508 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200509 with self.assertRaises(IndexError):
510 p[3]
511 self.assertEqual(p[-1], 22)
512 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000513
514 self.assertEqual(p.x, x)
515 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200516 with self.assertRaises(AttributeError):
517 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000518
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000519 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000520 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000521 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000522 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000523 self.assertEqual(repr(Zero()), 'Zero()')
524 self.assertEqual(Zero()._asdict(), {})
525 self.assertEqual(Zero()._fields, ())
526
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000527 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000529 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000530 self.assertEqual(Dot(1).d, 1)
531 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
532 self.assertEqual(Dot(1)._asdict(), {'d':1})
533 self.assertEqual(Dot(1)._replace(d=999), (999,))
534 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000535
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200536 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200537 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000538 for j in range(10)]) for i in range(n)))
539 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000540 Big = namedtuple('Big', names)
541 b = Big(*range(n))
542 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000543 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000544 for pos, name in enumerate(names):
545 self.assertEqual(getattr(b, name), pos)
546 repr(b) # make sure repr() doesn't blow-up
547 d = b._asdict()
548 d_expected = dict(zip(names, range(n)))
549 self.assertEqual(d, d_expected)
550 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
551 b2_expected = list(range(n))
552 b2_expected[1] = 999
553 b2_expected[-5] = 42
554 self.assertEqual(b2, tuple(b2_expected))
555 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000556
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000557 def test_pickle(self):
558 p = TestNT(x=10, y=20, z=30)
559 for module in (pickle,):
560 loads = getattr(module, 'loads')
561 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500562 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000563 q = loads(dumps(p, protocol))
564 self.assertEqual(p, q)
565 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700566 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000567
568 def test_copy(self):
569 p = TestNT(x=10, y=20, z=30)
570 for copier in copy.copy, copy.deepcopy:
571 q = copier(p)
572 self.assertEqual(p, q)
573 self.assertEqual(p._fields, q._fields)
574
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000575 def test_name_conflicts(self):
576 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
577 # failed when used as field names. Test to make sure these now work.
578 T = namedtuple('T', 'itemgetter property self cls tuple')
579 t = T(1, 2, 3, 4, 5)
580 self.assertEqual(t, (1,2,3,4,5))
581 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
582 self.assertEqual(newt, (10,20,30,40,50))
583
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700584 # Broader test of all interesting names taken from the code, old
585 # template, and an example
586 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
587 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
588 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
589 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
590 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
591 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
592 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
593 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
594 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
595 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
596 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
597 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
598 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
599 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
600 'instantiate', 'interning', 'introspection', 'isidentifier',
601 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
602 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
603 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
604 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
605 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
606 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
607 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
608 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
609 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
610 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
611 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
612 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
613 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
614 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000615 T = namedtuple('T', words)
616 # test __new__
617 values = tuple(range(len(words)))
618 t = T(*values)
619 self.assertEqual(t, values)
620 t = T(**dict(zip(T._fields, values)))
621 self.assertEqual(t, values)
622 # test _make
623 t = T._make(values)
624 self.assertEqual(t, values)
625 # exercise __repr__
626 repr(t)
627 # test _asdict
628 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
629 # test _replace
630 t = T._make(values)
631 newvalues = tuple(v*10 for v in values)
632 newt = t._replace(**dict(zip(T._fields, newvalues)))
633 self.assertEqual(newt, newvalues)
634 # test _fields
635 self.assertEqual(T._fields, tuple(words))
636 # test __getnewargs__
637 self.assertEqual(t.__getnewargs__(), values)
638
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000639 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700640 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000641 self.assertEqual(repr(A(1)), 'A(x=1)')
642 # repr should show the name of the subclass
643 class B(A):
644 pass
645 self.assertEqual(repr(B(1)), 'B(x=1)')
646
Raymond Hettinger6538b432016-08-16 10:55:43 -0700647 def test_keyword_only_arguments(self):
648 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700649 with self.assertRaises(TypeError):
650 NT = namedtuple('NT', ['x', 'y'], True)
651
652 NT = namedtuple('NT', ['abc', 'def'], rename=True)
653 self.assertEqual(NT._fields, ('abc', '_1'))
654 with self.assertRaises(TypeError):
655 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000656
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700657 def test_namedtuple_subclass_issue_24931(self):
658 class Point(namedtuple('_Point', ['x', 'y'])):
659 pass
660
661 a = Point(3, 4)
662 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
663
664 a.w = 5
665 self.assertEqual(a.__dict__, {'w': 5})
666
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200667 def test_field_descriptor(self):
668 Point = namedtuple('Point', 'x y')
669 p = Point(11, 22)
670 self.assertTrue(inspect.isdatadescriptor(Point.x))
671 self.assertEqual(Point.x.__get__(p), 11)
672 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
673 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000674
Joe Jevnikf36f8922019-02-21 16:00:40 -0500675 class NewPoint(tuple):
676 x = pickle.loads(pickle.dumps(Point.x))
677 y = pickle.loads(pickle.dumps(Point.y))
678
679 np = NewPoint([1, 2])
680
681 self.assertEqual(np.x, 1)
682 self.assertEqual(np.y, 2)
683
Raymond Hettingerb6d68aa2021-02-04 15:52:16 -0800684 def test_new_builtins_issue_43102(self):
Victor Stinnera3c3ffa2021-02-18 12:35:37 +0100685 obj = namedtuple('C', ())
686 new_func = obj.__new__
687 self.assertEqual(new_func.__globals__['__builtins__'], {})
688 self.assertEqual(new_func.__builtins__, {})
Raymond Hettingerb6d68aa2021-02-04 15:52:16 -0800689
Brandt Bucher145bf262021-02-26 14:51:55 -0800690 def test_match_args(self):
691 Point = namedtuple('Point', 'x y')
692 self.assertEqual(Point.__match_args__, ('x', 'y'))
693
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700694
Raymond Hettinger499e1932011-02-23 07:56:53 +0000695################################################################################
696### Abstract Base Classes
697################################################################################
698
Raymond Hettingerae650182009-01-28 23:33:59 +0000699class ABCTestCase(unittest.TestCase):
700
701 def validate_abstract_methods(self, abc, *names):
702 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
703
704 # everything should work will all required methods are present
705 C = type('C', (abc,), methodstubs)
706 C()
707
708 # instantiation should fail if a required method is missing
709 for name in names:
710 stubs = methodstubs.copy()
711 del stubs[name]
712 C = type('C', (abc,), stubs)
713 self.assertRaises(TypeError, C, name)
714
Florent Xiclunace153f62010-03-08 15:34:35 +0000715 def validate_isinstance(self, abc, name):
716 stub = lambda s, *args: 0
717
718 C = type('C', (object,), {'__hash__': None})
719 setattr(C, name, stub)
720 self.assertIsInstance(C(), abc)
721 self.assertTrue(issubclass(C, abc))
722
723 C = type('C', (object,), {'__hash__': None})
724 self.assertNotIsInstance(C(), abc)
725 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000726
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000727 def validate_comparison(self, instance):
728 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
729 operators = {}
730 for op in ops:
731 name = '__' + op + '__'
732 operators[name] = getattr(operator, name)
733
734 class Other:
735 def __init__(self):
736 self.right_side = False
737 def __eq__(self, other):
738 self.right_side = True
739 return True
740 __lt__ = __eq__
741 __gt__ = __eq__
742 __le__ = __eq__
743 __ge__ = __eq__
744 __ne__ = __eq__
745 __ror__ = __eq__
746 __rand__ = __eq__
747 __rxor__ = __eq__
748 __rsub__ = __eq__
749
750 for name, op in operators.items():
751 if not hasattr(instance, name):
752 continue
753 other = Other()
754 op(instance, other)
755 self.assertTrue(other.right_side,'Right side not called for %s.%s'
756 % (type(instance), name))
757
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700758def _test_gen():
759 yield
760
Raymond Hettingerae650182009-01-28 23:33:59 +0000761class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000762
Yury Selivanov75445082015-05-11 22:57:16 -0400763 def test_Awaitable(self):
764 def gen():
765 yield
766
767 @types.coroutine
768 def coro():
769 yield
770
771 async def new_coro():
772 pass
773
774 class Bar:
775 def __await__(self):
776 yield
777
778 class MinimalCoro(Coroutine):
779 def send(self, value):
780 return value
781 def throw(self, typ, val=None, tb=None):
782 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400783 def __await__(self):
784 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400785
786 non_samples = [None, int(), gen(), object()]
787 for x in non_samples:
788 self.assertNotIsInstance(x, Awaitable)
789 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
790
791 samples = [Bar(), MinimalCoro()]
792 for x in samples:
793 self.assertIsInstance(x, Awaitable)
794 self.assertTrue(issubclass(type(x), Awaitable))
795
796 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400797 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
798 # flag don't have '__await__' method, hence can't be instances
799 # of Awaitable. Use inspect.isawaitable to detect them.
800 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400801
802 c = new_coro()
803 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300804 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400805
Yury Selivanov56fc6142015-05-29 09:01:29 -0400806 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400807 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400808 self.assertTrue(isinstance(CoroLike(), Awaitable))
809 self.assertTrue(issubclass(CoroLike, Awaitable))
810 CoroLike = None
811 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400812
Yury Selivanov75445082015-05-11 22:57:16 -0400813 def test_Coroutine(self):
814 def gen():
815 yield
816
817 @types.coroutine
818 def coro():
819 yield
820
821 async def new_coro():
822 pass
823
824 class Bar:
825 def __await__(self):
826 yield
827
828 class MinimalCoro(Coroutine):
829 def send(self, value):
830 return value
831 def throw(self, typ, val=None, tb=None):
832 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400833 def __await__(self):
834 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400835
836 non_samples = [None, int(), gen(), object(), Bar()]
837 for x in non_samples:
838 self.assertNotIsInstance(x, Coroutine)
839 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
840
841 samples = [MinimalCoro()]
842 for x in samples:
843 self.assertIsInstance(x, Awaitable)
844 self.assertTrue(issubclass(type(x), Awaitable))
845
846 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400847 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
848 # flag don't have '__await__' method, hence can't be instances
849 # of Coroutine. Use inspect.isawaitable to detect them.
850 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400851
852 c = new_coro()
853 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300854 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400855
Yury Selivanov56fc6142015-05-29 09:01:29 -0400856 class CoroLike:
857 def send(self, value):
858 pass
859 def throw(self, typ, val=None, tb=None):
860 pass
861 def close(self):
862 pass
863 def __await__(self):
864 pass
865 self.assertTrue(isinstance(CoroLike(), Coroutine))
866 self.assertTrue(issubclass(CoroLike, Coroutine))
867
868 class CoroLike:
869 def send(self, value):
870 pass
871 def close(self):
872 pass
873 def __await__(self):
874 pass
875 self.assertFalse(isinstance(CoroLike(), Coroutine))
876 self.assertFalse(issubclass(CoroLike, Coroutine))
877
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000878 def test_Hashable(self):
879 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000880 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000881 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000882 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000883 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000884 # Check some hashables
885 samples = [None,
886 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000887 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000888 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000889 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000890 ]
891 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000892 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000893 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000894 self.assertRaises(TypeError, Hashable)
895 # Check direct subclassing
896 class H(Hashable):
897 def __hash__(self):
898 return super().__hash__()
899 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000900 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000901 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000902 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000903
Yury Selivanove0104ae2015-05-14 12:19:16 -0400904 def test_AsyncIterable(self):
905 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400906 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400907 return self
908 self.assertTrue(isinstance(AI(), AsyncIterable))
909 self.assertTrue(issubclass(AI, AsyncIterable))
910 # Check some non-iterables
911 non_samples = [None, object, []]
912 for x in non_samples:
913 self.assertNotIsInstance(x, AsyncIterable)
914 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
915 self.validate_abstract_methods(AsyncIterable, '__aiter__')
916 self.validate_isinstance(AsyncIterable, '__aiter__')
917
918 def test_AsyncIterator(self):
919 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400920 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400921 return self
922 async def __anext__(self):
923 raise StopAsyncIteration
924 self.assertTrue(isinstance(AI(), AsyncIterator))
925 self.assertTrue(issubclass(AI, AsyncIterator))
926 non_samples = [None, object, []]
927 # Check some non-iterables
928 for x in non_samples:
929 self.assertNotIsInstance(x, AsyncIterator)
930 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
931 # Similarly to regular iterators (see issue 10565)
932 class AnextOnly:
933 async def __anext__(self):
934 raise StopAsyncIteration
935 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
936 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
937
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000938 def test_Iterable(self):
939 # Check some non-iterables
940 non_samples = [None, 42, 3.14, 1j]
941 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000942 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000943 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000944 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000945 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000946 tuple(), list(), set(), frozenset(), dict(),
947 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700948 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000949 (x for x in []),
950 ]
951 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000952 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000953 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000954 # Check direct subclassing
955 class I(Iterable):
956 def __iter__(self):
957 return super().__iter__()
958 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000959 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000960 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000961 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700962 # Check None blocking
963 class It:
964 def __iter__(self): return iter([])
965 class ItBlocked(It):
966 __iter__ = None
967 self.assertTrue(issubclass(It, Iterable))
968 self.assertTrue(isinstance(It(), Iterable))
969 self.assertFalse(issubclass(ItBlocked, Iterable))
970 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000971
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700972 def test_Reversible(self):
973 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100974 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700975 for x in non_samples:
976 self.assertNotIsInstance(x, Reversible)
977 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700978 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100979 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700980 for x in non_reversibles:
981 self.assertNotIsInstance(x, Reversible)
982 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
983 # Check some reversible iterables
984 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
985 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100986 OrderedDict().values(), Counter(), Counter().keys(),
987 Counter().items(), Counter().values(), dict(),
988 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700989 for x in samples:
990 self.assertIsInstance(x, Reversible)
991 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
992 # Check also Mapping, MutableMapping, and Sequence
993 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
994 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
995 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
996 # Check direct subclassing
997 class R(Reversible):
998 def __iter__(self):
999 return iter(list())
1000 def __reversed__(self):
1001 return iter(list())
1002 self.assertEqual(list(reversed(R())), [])
1003 self.assertFalse(issubclass(float, R))
1004 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001005 # Check reversible non-iterable (which is not Reversible)
1006 class RevNoIter:
1007 def __reversed__(self): return reversed([])
1008 class RevPlusIter(RevNoIter):
1009 def __iter__(self): return iter([])
1010 self.assertFalse(issubclass(RevNoIter, Reversible))
1011 self.assertFalse(isinstance(RevNoIter(), Reversible))
1012 self.assertTrue(issubclass(RevPlusIter, Reversible))
1013 self.assertTrue(isinstance(RevPlusIter(), Reversible))
1014 # Check None blocking
1015 class Rev:
1016 def __iter__(self): return iter([])
1017 def __reversed__(self): return reversed([])
1018 class RevItBlocked(Rev):
1019 __iter__ = None
1020 class RevRevBlocked(Rev):
1021 __reversed__ = None
1022 self.assertTrue(issubclass(Rev, Reversible))
1023 self.assertTrue(isinstance(Rev(), Reversible))
1024 self.assertFalse(issubclass(RevItBlocked, Reversible))
1025 self.assertFalse(isinstance(RevItBlocked(), Reversible))
1026 self.assertFalse(issubclass(RevRevBlocked, Reversible))
1027 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001028
Guido van Rossumf0666942016-08-23 10:47:07 -07001029 def test_Collection(self):
1030 # Check some non-collections
1031 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
1032 for x in non_collections:
1033 self.assertNotIsInstance(x, Collection)
1034 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1035 # Check some non-collection iterables
1036 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001037 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -07001038 for x in non_col_iterables:
1039 self.assertNotIsInstance(x, Collection)
1040 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1041 # Check some collections
1042 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001043 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001044 for x in samples:
1045 self.assertIsInstance(x, Collection)
1046 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1047 # Check also Mapping, MutableMapping, etc.
1048 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1049 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1050 self.assertTrue(issubclass(MutableMapping, Collection),
1051 repr(MutableMapping))
1052 self.assertTrue(issubclass(Set, Collection), repr(Set))
1053 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1054 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1055 # Check direct subclassing
1056 class Col(Collection):
1057 def __iter__(self):
1058 return iter(list())
1059 def __len__(self):
1060 return 0
1061 def __contains__(self, item):
1062 return False
1063 class DerCol(Col): pass
1064 self.assertEqual(list(iter(Col())), [])
1065 self.assertFalse(issubclass(list, Col))
1066 self.assertFalse(issubclass(set, Col))
1067 self.assertFalse(issubclass(float, Col))
1068 self.assertEqual(list(iter(DerCol())), [])
1069 self.assertFalse(issubclass(list, DerCol))
1070 self.assertFalse(issubclass(set, DerCol))
1071 self.assertFalse(issubclass(float, DerCol))
1072 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1073 '__contains__')
1074 # Check sized container non-iterable (which is not Collection) etc.
1075 class ColNoIter:
1076 def __len__(self): return 0
1077 def __contains__(self, item): return False
1078 class ColNoSize:
1079 def __iter__(self): return iter([])
1080 def __contains__(self, item): return False
1081 class ColNoCont:
1082 def __iter__(self): return iter([])
1083 def __len__(self): return 0
1084 self.assertFalse(issubclass(ColNoIter, Collection))
1085 self.assertFalse(isinstance(ColNoIter(), Collection))
1086 self.assertFalse(issubclass(ColNoSize, Collection))
1087 self.assertFalse(isinstance(ColNoSize(), Collection))
1088 self.assertFalse(issubclass(ColNoCont, Collection))
1089 self.assertFalse(isinstance(ColNoCont(), Collection))
1090 # Check None blocking
1091 class SizeBlock:
1092 def __iter__(self): return iter([])
1093 def __contains__(self): return False
1094 __len__ = None
1095 class IterBlock:
1096 def __len__(self): return 0
1097 def __contains__(self): return True
1098 __iter__ = None
1099 self.assertFalse(issubclass(SizeBlock, Collection))
1100 self.assertFalse(isinstance(SizeBlock(), Collection))
1101 self.assertFalse(issubclass(IterBlock, Collection))
1102 self.assertFalse(isinstance(IterBlock(), Collection))
1103 # Check None blocking in subclass
1104 class ColImpl:
1105 def __iter__(self):
1106 return iter(list())
1107 def __len__(self):
1108 return 0
1109 def __contains__(self, item):
1110 return False
1111 class NonCol(ColImpl):
1112 __contains__ = None
1113 self.assertFalse(issubclass(NonCol, Collection))
1114 self.assertFalse(isinstance(NonCol(), Collection))
1115
1116
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001117 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001118 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001119 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001120 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001121 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001122 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001123 iter(tuple()), iter(list()), iter(dict()),
1124 iter(set()), iter(frozenset()),
1125 iter(dict().keys()), iter(dict().items()),
1126 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001127 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001128 (x for x in []),
1129 ]
1130 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001131 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001132 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001133 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1134
1135 # Issue 10565
1136 class NextOnly:
1137 def __next__(self):
1138 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001139 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001140 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001141
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001142 def test_Generator(self):
1143 class NonGen1:
1144 def __iter__(self): return self
1145 def __next__(self): return None
1146 def close(self): pass
1147 def throw(self, typ, val=None, tb=None): pass
1148
1149 class NonGen2:
1150 def __iter__(self): return self
1151 def __next__(self): return None
1152 def close(self): pass
1153 def send(self, value): return value
1154
1155 class NonGen3:
1156 def close(self): pass
1157 def send(self, value): return value
1158 def throw(self, typ, val=None, tb=None): pass
1159
1160 non_samples = [
1161 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1162 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1163 for x in non_samples:
1164 self.assertNotIsInstance(x, Generator)
1165 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1166
1167 class Gen:
1168 def __iter__(self): return self
1169 def __next__(self): return None
1170 def close(self): pass
1171 def send(self, value): return value
1172 def throw(self, typ, val=None, tb=None): pass
1173
1174 class MinimalGen(Generator):
1175 def send(self, value):
1176 return value
1177 def throw(self, typ, val=None, tb=None):
1178 super().throw(typ, val, tb)
1179
1180 def gen():
1181 yield 1
1182
1183 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1184 for x in samples:
1185 self.assertIsInstance(x, Iterator)
1186 self.assertIsInstance(x, Generator)
1187 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1188 self.validate_abstract_methods(Generator, 'send', 'throw')
1189
1190 # mixin tests
1191 mgen = MinimalGen()
1192 self.assertIs(mgen, iter(mgen))
1193 self.assertIs(mgen.send(None), next(mgen))
1194 self.assertEqual(2, mgen.send(2))
1195 self.assertIsNone(mgen.close())
1196 self.assertRaises(ValueError, mgen.throw, ValueError)
1197 self.assertRaisesRegex(ValueError, "^huhu$",
1198 mgen.throw, ValueError, ValueError("huhu"))
1199 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1200
1201 class FailOnClose(Generator):
1202 def send(self, value): return value
1203 def throw(self, *args): raise ValueError
1204
1205 self.assertRaises(ValueError, FailOnClose().close)
1206
1207 class IgnoreGeneratorExit(Generator):
1208 def send(self, value): return value
1209 def throw(self, *args): pass
1210
1211 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1212
Yury Selivanov22214ab2016-11-16 18:25:04 -05001213 def test_AsyncGenerator(self):
1214 class NonAGen1:
1215 def __aiter__(self): return self
1216 def __anext__(self): return None
1217 def aclose(self): pass
1218 def athrow(self, typ, val=None, tb=None): pass
1219
1220 class NonAGen2:
1221 def __aiter__(self): return self
1222 def __anext__(self): return None
1223 def aclose(self): pass
1224 def asend(self, value): return value
1225
1226 class NonAGen3:
1227 def aclose(self): pass
1228 def asend(self, value): return value
1229 def athrow(self, typ, val=None, tb=None): pass
1230
1231 non_samples = [
1232 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1233 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1234 for x in non_samples:
1235 self.assertNotIsInstance(x, AsyncGenerator)
1236 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1237
1238 class Gen:
1239 def __aiter__(self): return self
1240 async def __anext__(self): return None
1241 async def aclose(self): pass
1242 async def asend(self, value): return value
1243 async def athrow(self, typ, val=None, tb=None): pass
1244
1245 class MinimalAGen(AsyncGenerator):
1246 async def asend(self, value):
1247 return value
1248 async def athrow(self, typ, val=None, tb=None):
1249 await super().athrow(typ, val, tb)
1250
1251 async def gen():
1252 yield 1
1253
1254 samples = [gen(), Gen(), MinimalAGen()]
1255 for x in samples:
1256 self.assertIsInstance(x, AsyncIterator)
1257 self.assertIsInstance(x, AsyncGenerator)
1258 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1259 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1260
1261 def run_async(coro):
1262 result = None
1263 while True:
1264 try:
1265 coro.send(None)
1266 except StopIteration as ex:
1267 result = ex.args[0] if ex.args else None
1268 break
1269 return result
1270
1271 # mixin tests
1272 mgen = MinimalAGen()
1273 self.assertIs(mgen, mgen.__aiter__())
1274 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1275 self.assertEqual(2, run_async(mgen.asend(2)))
1276 self.assertIsNone(run_async(mgen.aclose()))
1277 with self.assertRaises(ValueError):
1278 run_async(mgen.athrow(ValueError))
1279
1280 class FailOnClose(AsyncGenerator):
1281 async def asend(self, value): return value
1282 async def athrow(self, *args): raise ValueError
1283
1284 with self.assertRaises(ValueError):
1285 run_async(FailOnClose().aclose())
1286
1287 class IgnoreGeneratorExit(AsyncGenerator):
1288 async def asend(self, value): return value
1289 async def athrow(self, *args): pass
1290
1291 with self.assertRaises(RuntimeError):
1292 run_async(IgnoreGeneratorExit().aclose())
1293
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001294 def test_Sized(self):
1295 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001296 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001297 (x for x in []),
1298 ]
1299 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001300 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001301 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001302 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001303 tuple(), list(), set(), frozenset(), dict(),
1304 dict().keys(), dict().items(), dict().values(),
1305 ]
1306 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001307 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001308 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001309 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001310 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001311
1312 def test_Container(self):
1313 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001314 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001315 (x for x in []),
1316 ]
1317 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001318 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001319 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001320 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001321 tuple(), list(), set(), frozenset(), dict(),
1322 dict().keys(), dict().items(),
1323 ]
1324 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001325 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001326 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001327 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001328 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001329
1330 def test_Callable(self):
1331 non_samples = [None, 42, 3.14, 1j,
1332 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001333 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001334 (x for x in []),
1335 ]
1336 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001337 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001338 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001339 samples = [lambda: None,
1340 type, int, object,
1341 len,
1342 list.append, [].append,
1343 ]
1344 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001345 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001346 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001347 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001348 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001349
1350 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001351 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001352 class C(B):
1353 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001354 self.assertTrue(issubclass(C, B))
1355 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001356
1357 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001358 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001359 class C:
1360 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001361 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001362 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001363 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001364
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001365class WithSet(MutableSet):
1366
1367 def __init__(self, it=()):
1368 self.data = set(it)
1369
1370 def __len__(self):
1371 return len(self.data)
1372
1373 def __iter__(self):
1374 return iter(self.data)
1375
1376 def __contains__(self, item):
1377 return item in self.data
1378
1379 def add(self, item):
1380 self.data.add(item)
1381
1382 def discard(self, item):
1383 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001384
Raymond Hettingerae650182009-01-28 23:33:59 +00001385class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001386
1387 # XXX For now, we only test some virtual inheritance properties.
1388 # We should also test the proper behavior of the collection ABCs
1389 # as real base classes or mix-in classes.
1390
1391 def test_Set(self):
1392 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001393 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001394 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001395 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001396 class MySet(Set):
1397 def __contains__(self, x):
1398 return False
1399 def __len__(self):
1400 return 0
1401 def __iter__(self):
1402 return iter([])
1403 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001404
Benjamin Peterson41181742008-07-02 20:22:54 +00001405 def test_hash_Set(self):
1406 class OneTwoThreeSet(Set):
1407 def __init__(self):
1408 self.contents = [1, 2, 3]
1409 def __contains__(self, x):
1410 return x in self.contents
1411 def __len__(self):
1412 return len(self.contents)
1413 def __iter__(self):
1414 return iter(self.contents)
1415 def __hash__(self):
1416 return self._hash()
1417 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001418 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001419
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001420 def test_isdisjoint_Set(self):
1421 class MySet(Set):
1422 def __init__(self, itr):
1423 self.contents = itr
1424 def __contains__(self, x):
1425 return x in self.contents
1426 def __iter__(self):
1427 return iter(self.contents)
1428 def __len__(self):
1429 return len([x for x in self.contents])
1430 s1 = MySet((1, 2, 3))
1431 s2 = MySet((4, 5, 6))
1432 s3 = MySet((1, 5, 6))
1433 self.assertTrue(s1.isdisjoint(s2))
1434 self.assertFalse(s1.isdisjoint(s3))
1435
1436 def test_equality_Set(self):
1437 class MySet(Set):
1438 def __init__(self, itr):
1439 self.contents = itr
1440 def __contains__(self, x):
1441 return x in self.contents
1442 def __iter__(self):
1443 return iter(self.contents)
1444 def __len__(self):
1445 return len([x for x in self.contents])
1446 s1 = MySet((1,))
1447 s2 = MySet((1, 2))
1448 s3 = MySet((3, 4))
1449 s4 = MySet((3, 4))
1450 self.assertTrue(s2 > s1)
1451 self.assertTrue(s1 < s2)
1452 self.assertFalse(s2 <= s1)
1453 self.assertFalse(s2 <= s3)
1454 self.assertFalse(s1 >= s2)
1455 self.assertEqual(s3, s4)
1456 self.assertNotEqual(s2, s3)
1457
1458 def test_arithmetic_Set(self):
1459 class MySet(Set):
1460 def __init__(self, itr):
1461 self.contents = itr
1462 def __contains__(self, x):
1463 return x in self.contents
1464 def __iter__(self):
1465 return iter(self.contents)
1466 def __len__(self):
1467 return len([x for x in self.contents])
1468 s1 = MySet((1, 2, 3))
1469 s2 = MySet((3, 4, 5))
1470 s3 = s1 & s2
1471 self.assertEqual(s3, MySet((3,)))
1472
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001473 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001474 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001475 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001476 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001477 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001478 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1479 'add', 'discard')
1480
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001481 def test_issue_5647(self):
1482 # MutableSet.__iand__ mutated the set during iteration
1483 s = WithSet('abcd')
1484 s &= WithSet('cdef') # This used to fail
1485 self.assertEqual(set(s), set('cd'))
1486
Raymond Hettingerae650182009-01-28 23:33:59 +00001487 def test_issue_4920(self):
1488 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001489 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001490 __slots__=['__s']
1491 def __init__(self,items=None):
1492 if items is None:
1493 items=[]
1494 self.__s=set(items)
1495 def __contains__(self,v):
1496 return v in self.__s
1497 def __iter__(self):
1498 return iter(self.__s)
1499 def __len__(self):
1500 return len(self.__s)
1501 def add(self,v):
1502 result=v not in self.__s
1503 self.__s.add(v)
1504 return result
1505 def discard(self,v):
1506 result=v in self.__s
1507 self.__s.discard(v)
1508 return result
1509 def __repr__(self):
1510 return "MySet(%s)" % repr(list(self))
1511 s = MySet([5,43,2,1])
1512 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001513
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001514 def test_issue8750(self):
1515 empty = WithSet()
1516 full = WithSet(range(10))
1517 s = WithSet(full)
1518 s -= s
1519 self.assertEqual(s, empty)
1520 s = WithSet(full)
1521 s ^= s
1522 self.assertEqual(s, empty)
1523 s = WithSet(full)
1524 s &= s
1525 self.assertEqual(s, full)
1526 s |= s
1527 self.assertEqual(s, full)
1528
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001529 def test_issue16373(self):
1530 # Recursion error comparing comparable and noncomparable
1531 # Set instances
1532 class MyComparableSet(Set):
1533 def __contains__(self, x):
1534 return False
1535 def __len__(self):
1536 return 0
1537 def __iter__(self):
1538 return iter([])
1539 class MyNonComparableSet(Set):
1540 def __contains__(self, x):
1541 return False
1542 def __len__(self):
1543 return 0
1544 def __iter__(self):
1545 return iter([])
1546 def __le__(self, x):
1547 return NotImplemented
1548 def __lt__(self, x):
1549 return NotImplemented
1550
1551 cs = MyComparableSet()
1552 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001553 self.assertFalse(ncs < cs)
1554 self.assertTrue(ncs <= cs)
1555 self.assertFalse(ncs > cs)
1556 self.assertTrue(ncs >= cs)
1557
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001558 def test_issue26915(self):
1559 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001560 class CustomSequence(Sequence):
1561 def __init__(self, seq):
1562 self._seq = seq
1563 def __getitem__(self, index):
1564 return self._seq[index]
1565 def __len__(self):
1566 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001567
1568 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001569 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001570 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001571 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001572 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001573 ItemsView({1: nan, 2: obj}),
1574 ValuesView({1: nan, 2: obj})
1575 ]
1576 for container in containers:
1577 for elem in container:
1578 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001579 self.assertEqual(seq.index(nan), 0)
1580 self.assertEqual(seq.index(obj), 1)
1581 self.assertEqual(seq.count(nan), 2)
1582 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001583
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001584 def assertSameSet(self, s1, s2):
1585 # coerce both to a real set then check equality
1586 self.assertSetEqual(set(s1), set(s2))
1587
Richard Levasseur68f68fa2020-11-21 11:56:24 -08001588 def test_Set_from_iterable(self):
1589 """Verify _from_iterable overriden to an instance method works."""
1590 class SetUsingInstanceFromIterable(MutableSet):
1591 def __init__(self, values, created_by):
1592 if not created_by:
1593 raise ValueError(f'created_by must be specified')
1594 self.created_by = created_by
1595 self._values = set(values)
1596
1597 def _from_iterable(self, values):
1598 return type(self)(values, 'from_iterable')
1599
1600 def __contains__(self, value):
1601 return value in self._values
1602
1603 def __iter__(self):
1604 yield from self._values
1605
1606 def __len__(self):
1607 return len(self._values)
1608
1609 def add(self, value):
1610 self._values.add(value)
1611
1612 def discard(self, value):
1613 self._values.discard(value)
1614
1615 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
1616
1617 actual = impl - {1}
1618 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1619 self.assertEqual('from_iterable', actual.created_by)
1620 self.assertEqual({2, 3}, actual)
1621
1622 actual = impl | {4}
1623 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1624 self.assertEqual('from_iterable', actual.created_by)
1625 self.assertEqual({1, 2, 3, 4}, actual)
1626
1627 actual = impl & {2}
1628 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1629 self.assertEqual('from_iterable', actual.created_by)
1630 self.assertEqual({2}, actual)
1631
1632 actual = impl ^ {3, 4}
1633 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1634 self.assertEqual('from_iterable', actual.created_by)
1635 self.assertEqual({1, 2, 4}, actual)
1636
1637 # NOTE: ixor'ing with a list is important here: internally, __ixor__
1638 # only calls _from_iterable if the other value isn't already a Set.
1639 impl ^= [3, 4]
1640 self.assertIsInstance(impl, SetUsingInstanceFromIterable)
1641 self.assertEqual('test', impl.created_by)
1642 self.assertEqual({1, 2, 4}, impl)
1643
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001644 def test_Set_interoperability_with_real_sets(self):
1645 # Issue: 8743
1646 class ListSet(Set):
1647 def __init__(self, elements=()):
1648 self.data = []
1649 for elem in elements:
1650 if elem not in self.data:
1651 self.data.append(elem)
1652 def __contains__(self, elem):
1653 return elem in self.data
1654 def __iter__(self):
1655 return iter(self.data)
1656 def __len__(self):
1657 return len(self.data)
1658 def __repr__(self):
1659 return 'Set({!r})'.format(self.data)
1660
1661 r1 = set('abc')
1662 r2 = set('bcd')
1663 r3 = set('abcde')
1664 f1 = ListSet('abc')
1665 f2 = ListSet('bcd')
1666 f3 = ListSet('abcde')
1667 l1 = list('abccba')
1668 l2 = list('bcddcb')
1669 l3 = list('abcdeedcba')
1670
1671 target = r1 & r2
1672 self.assertSameSet(f1 & f2, target)
1673 self.assertSameSet(f1 & r2, target)
1674 self.assertSameSet(r2 & f1, target)
1675 self.assertSameSet(f1 & l2, target)
1676
1677 target = r1 | r2
1678 self.assertSameSet(f1 | f2, target)
1679 self.assertSameSet(f1 | r2, target)
1680 self.assertSameSet(r2 | f1, target)
1681 self.assertSameSet(f1 | l2, target)
1682
1683 fwd_target = r1 - r2
1684 rev_target = r2 - r1
1685 self.assertSameSet(f1 - f2, fwd_target)
1686 self.assertSameSet(f2 - f1, rev_target)
1687 self.assertSameSet(f1 - r2, fwd_target)
1688 self.assertSameSet(f2 - r1, rev_target)
1689 self.assertSameSet(r1 - f2, fwd_target)
1690 self.assertSameSet(r2 - f1, rev_target)
1691 self.assertSameSet(f1 - l2, fwd_target)
1692 self.assertSameSet(f2 - l1, rev_target)
1693
1694 target = r1 ^ r2
1695 self.assertSameSet(f1 ^ f2, target)
1696 self.assertSameSet(f1 ^ r2, target)
1697 self.assertSameSet(r2 ^ f1, target)
1698 self.assertSameSet(f1 ^ l2, target)
1699
1700 # Don't change the following to use assertLess or other
1701 # "more specific" unittest assertions. The current
1702 # assertTrue/assertFalse style makes the pattern of test
1703 # case combinations clear and allows us to know for sure
1704 # the exact operator being invoked.
1705
1706 # proper subset
1707 self.assertTrue(f1 < f3)
1708 self.assertFalse(f1 < f1)
1709 self.assertFalse(f1 < f2)
1710 self.assertTrue(r1 < f3)
1711 self.assertFalse(r1 < f1)
1712 self.assertFalse(r1 < f2)
1713 self.assertTrue(r1 < r3)
1714 self.assertFalse(r1 < r1)
1715 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001716 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001717 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001718 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001719 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001720 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001721 f1 < l2
1722
1723 # any subset
1724 self.assertTrue(f1 <= f3)
1725 self.assertTrue(f1 <= f1)
1726 self.assertFalse(f1 <= f2)
1727 self.assertTrue(r1 <= f3)
1728 self.assertTrue(r1 <= f1)
1729 self.assertFalse(r1 <= f2)
1730 self.assertTrue(r1 <= r3)
1731 self.assertTrue(r1 <= r1)
1732 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001733 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001734 f1 <= l3
1735 with self.assertRaises(TypeError):
1736 f1 <= l1
1737 with self.assertRaises(TypeError):
1738 f1 <= l2
1739
1740 # proper superset
1741 self.assertTrue(f3 > f1)
1742 self.assertFalse(f1 > f1)
1743 self.assertFalse(f2 > f1)
1744 self.assertTrue(r3 > r1)
1745 self.assertFalse(f1 > r1)
1746 self.assertFalse(f2 > r1)
1747 self.assertTrue(r3 > r1)
1748 self.assertFalse(r1 > r1)
1749 self.assertFalse(r2 > r1)
1750 with self.assertRaises(TypeError):
1751 f1 > l3
1752 with self.assertRaises(TypeError):
1753 f1 > l1
1754 with self.assertRaises(TypeError):
1755 f1 > l2
1756
1757 # any superset
1758 self.assertTrue(f3 >= f1)
1759 self.assertTrue(f1 >= f1)
1760 self.assertFalse(f2 >= f1)
1761 self.assertTrue(r3 >= r1)
1762 self.assertTrue(f1 >= r1)
1763 self.assertFalse(f2 >= r1)
1764 self.assertTrue(r3 >= r1)
1765 self.assertTrue(r1 >= r1)
1766 self.assertFalse(r2 >= r1)
1767 with self.assertRaises(TypeError):
1768 f1 >= l3
1769 with self.assertRaises(TypeError):
1770 f1 >=l1
1771 with self.assertRaises(TypeError):
1772 f1 >= l2
1773
1774 # equality
1775 self.assertTrue(f1 == f1)
1776 self.assertTrue(r1 == f1)
1777 self.assertTrue(f1 == r1)
1778 self.assertFalse(f1 == f3)
1779 self.assertFalse(r1 == f3)
1780 self.assertFalse(f1 == r3)
1781 self.assertFalse(f1 == l3)
1782 self.assertFalse(f1 == l1)
1783 self.assertFalse(f1 == l2)
1784
1785 # inequality
1786 self.assertFalse(f1 != f1)
1787 self.assertFalse(r1 != f1)
1788 self.assertFalse(f1 != r1)
1789 self.assertTrue(f1 != f3)
1790 self.assertTrue(r1 != f3)
1791 self.assertTrue(f1 != r3)
1792 self.assertTrue(f1 != l3)
1793 self.assertTrue(f1 != l1)
1794 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001795
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001796 def test_Mapping(self):
1797 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001798 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001799 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001800 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1801 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001802 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001803 def __len__(self):
1804 return 0
1805 def __getitem__(self, i):
1806 raise IndexError
1807 def __iter__(self):
1808 return iter(())
1809 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001810 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001811
1812 def test_MutableMapping(self):
1813 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001814 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001815 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001816 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1817 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001818
Raymond Hettinger9117c752010-08-22 07:44:24 +00001819 def test_MutableMapping_subclass(self):
1820 # Test issue 9214
1821 mymap = UserDict()
1822 mymap['red'] = 5
1823 self.assertIsInstance(mymap.keys(), Set)
1824 self.assertIsInstance(mymap.keys(), KeysView)
1825 self.assertIsInstance(mymap.items(), Set)
1826 self.assertIsInstance(mymap.items(), ItemsView)
1827
1828 mymap = UserDict()
1829 mymap['red'] = 5
1830 z = mymap.keys() | {'orange'}
1831 self.assertIsInstance(z, set)
1832 list(z)
1833 mymap['blue'] = 7 # Shouldn't affect 'z'
1834 self.assertEqual(sorted(z), ['orange', 'red'])
1835
1836 mymap = UserDict()
1837 mymap['red'] = 5
1838 z = mymap.items() | {('orange', 3)}
1839 self.assertIsInstance(z, set)
1840 list(z)
1841 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001842 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001843
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001844 def test_Sequence(self):
1845 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001846 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001847 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001848 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001849 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001850 self.assertIsInstance(memoryview(b""), Sequence)
1851 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001852 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001853 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1854 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001855
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001856 def test_Sequence_mixins(self):
1857 class SequenceSubclass(Sequence):
1858 def __init__(self, seq=()):
1859 self.seq = seq
1860
1861 def __getitem__(self, index):
1862 return self.seq[index]
1863
1864 def __len__(self):
1865 return len(self.seq)
1866
1867 # Compare Sequence.index() behavior to (list|str).index() behavior
1868 def assert_index_same(seq1, seq2, index_args):
1869 try:
1870 expected = seq1.index(*index_args)
1871 except ValueError:
1872 with self.assertRaises(ValueError):
1873 seq2.index(*index_args)
1874 else:
1875 actual = seq2.index(*index_args)
1876 self.assertEqual(
1877 actual, expected, '%r.index%s' % (seq1, index_args))
1878
1879 for ty in list, str:
1880 nativeseq = ty('abracadabra')
1881 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1882 seqseq = SequenceSubclass(nativeseq)
1883 for letter in set(nativeseq) | {'z'}:
1884 assert_index_same(nativeseq, seqseq, (letter,))
1885 for start in range(-3, len(nativeseq) + 3):
1886 assert_index_same(nativeseq, seqseq, (letter, start))
1887 for stop in range(-3, len(nativeseq) + 3):
1888 assert_index_same(
1889 nativeseq, seqseq, (letter, start, stop))
1890
Guido van Rossumd05eb002007-11-21 22:26:24 +00001891 def test_ByteString(self):
1892 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001893 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001894 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001895 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001896 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001897 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001898 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001899 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001900
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001901 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001902 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001903 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001904 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001905 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001906 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001907 self.assertTrue(issubclass(sample, MutableSequence))
1908 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001909 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1910 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001911
Eli Bendersky0716a572011-03-04 10:38:14 +00001912 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001913 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001914 # class inherited from it.
1915 class MutableSequenceSubclass(MutableSequence):
1916 def __init__(self):
1917 self.lst = []
1918
1919 def __setitem__(self, index, value):
1920 self.lst[index] = value
1921
1922 def __getitem__(self, index):
1923 return self.lst[index]
1924
1925 def __len__(self):
1926 return len(self.lst)
1927
1928 def __delitem__(self, index):
1929 del self.lst[index]
1930
1931 def insert(self, index, value):
1932 self.lst.insert(index, value)
1933
1934 mss = MutableSequenceSubclass()
1935 mss.append(0)
1936 mss.extend((1, 2, 3, 4))
1937 self.assertEqual(len(mss), 5)
1938 self.assertEqual(mss[3], 3)
1939 mss.reverse()
1940 self.assertEqual(mss[3], 1)
1941 mss.pop()
1942 self.assertEqual(len(mss), 4)
1943 mss.remove(3)
1944 self.assertEqual(len(mss), 3)
1945 mss += (10, 20, 30)
1946 self.assertEqual(len(mss), 6)
1947 self.assertEqual(mss[-1], 30)
1948 mss.clear()
1949 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001950
Naris R1b5f9c92018-08-31 02:56:14 +10001951 # issue 34427
1952 # extending self should not cause infinite loop
1953 items = 'ABCD'
1954 mss2 = MutableSequenceSubclass()
1955 mss2.extend(items + items)
1956 mss.clear()
1957 mss.extend(items)
1958 mss.extend(mss)
1959 self.assertEqual(len(mss), len(mss2))
1960 self.assertEqual(list(mss), list(mss2))
1961
1962
Raymond Hettinger499e1932011-02-23 07:56:53 +00001963################################################################################
1964### Counter
1965################################################################################
1966
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001967class CounterSubclassWithSetItem(Counter):
1968 # Test a counter subclass that overrides __setitem__
1969 def __init__(self, *args, **kwds):
1970 self.called = False
1971 Counter.__init__(self, *args, **kwds)
1972 def __setitem__(self, key, value):
1973 self.called = True
1974 Counter.__setitem__(self, key, value)
1975
1976class CounterSubclassWithGet(Counter):
1977 # Test a counter subclass that overrides get()
1978 def __init__(self, *args, **kwds):
1979 self.called = False
1980 Counter.__init__(self, *args, **kwds)
1981 def get(self, key, default):
1982 self.called = True
1983 return Counter.get(self, key, default)
1984
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001985class TestCounter(unittest.TestCase):
1986
1987 def test_basics(self):
1988 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001989 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1990 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001991 self.assertIsInstance(c, dict)
1992 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001993 self.assertTrue(issubclass(Counter, dict))
1994 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001995 self.assertEqual(len(c), 3)
1996 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001997 self.assertEqual(list(c.values()), [3, 2, 1])
1998 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1999 self.assertEqual(list(c), ['a', 'b', 'c'])
2000 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002001 [('a', 3), ('b', 2), ('c', 1)])
2002 self.assertEqual(c['b'], 2)
2003 self.assertEqual(c['z'], 0)
2004 self.assertEqual(c.__contains__('c'), True)
2005 self.assertEqual(c.__contains__('z'), False)
2006 self.assertEqual(c.get('b', 10), 2)
2007 self.assertEqual(c.get('z', 10), 10)
2008 self.assertEqual(c, dict(a=3, b=2, c=1))
2009 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
2010 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
2011 for i in range(5):
2012 self.assertEqual(c.most_common(i),
2013 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002014 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002015 c['a'] += 1 # increment an existing value
2016 c['b'] -= 2 # sub existing value to zero
2017 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002018 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002019 c['d'] -= 2 # sub from a missing value
2020 c['e'] = -5 # directly assign a missing value
2021 c['f'] += 4 # add to a missing value
2022 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002023 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002024 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002025 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002026 for i in range(3):
2027 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002028 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002029 c.clear()
2030 self.assertEqual(c, {})
2031 self.assertEqual(repr(c), 'Counter()')
2032 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
2033 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002034 c.update(dict(a=5, b=3))
2035 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002036 c.update(Counter('a' * 50 + 'b' * 30))
2037 c.update() # test case with no args
2038 c.__init__('a' * 500 + 'b' * 300)
2039 c.__init__('cdc')
2040 c.__init__()
2041 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
2042 self.assertEqual(c.setdefault('d', 5), 1)
2043 self.assertEqual(c['d'], 1)
2044 self.assertEqual(c.setdefault('e', 5), 5)
2045 self.assertEqual(c['e'], 5)
2046
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002047 def test_init(self):
2048 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
2049 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
2050 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
2051 self.assertRaises(TypeError, Counter, 42)
2052 self.assertRaises(TypeError, Counter, (), ())
2053 self.assertRaises(TypeError, Counter.__init__)
2054
Raymond Hettinger407c7342019-02-21 09:19:00 -08002055 def test_order_preservation(self):
2056 # Input order dictates items() order
2057 self.assertEqual(list(Counter('abracadabra').items()),
2058 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
2059 # letters with same count: ^----------^ ^---------^
2060
2061 # Verify retention of order even when all counts are equal
2062 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
2063 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
2064
2065 # Input order dictates elements() order
2066 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
2067 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
2068 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
2069
2070 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10002071 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08002072 ps = 'aaabbcdddeefggghhijjjkkl'
2073 qs = 'abbcccdeefffhkkllllmmnno'
2074 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
2075 def correctly_ordered(seq):
2076 'Return true if the letters occur in the expected order'
2077 positions = [order[letter] for letter in seq]
2078 return positions == sorted(positions)
2079
2080 p, q = Counter(ps), Counter(qs)
2081 self.assertTrue(correctly_ordered(+p))
2082 self.assertTrue(correctly_ordered(-p))
2083 self.assertTrue(correctly_ordered(p + q))
2084 self.assertTrue(correctly_ordered(p - q))
2085 self.assertTrue(correctly_ordered(p | q))
2086 self.assertTrue(correctly_ordered(p & q))
2087
2088 p, q = Counter(ps), Counter(qs)
2089 p += q
2090 self.assertTrue(correctly_ordered(p))
2091
2092 p, q = Counter(ps), Counter(qs)
2093 p -= q
2094 self.assertTrue(correctly_ordered(p))
2095
2096 p, q = Counter(ps), Counter(qs)
2097 p |= q
2098 self.assertTrue(correctly_ordered(p))
2099
2100 p, q = Counter(ps), Counter(qs)
2101 p &= q
2102 self.assertTrue(correctly_ordered(p))
2103
2104 p, q = Counter(ps), Counter(qs)
2105 p.update(q)
2106 self.assertTrue(correctly_ordered(p))
2107
2108 p, q = Counter(ps), Counter(qs)
2109 p.subtract(q)
2110 self.assertTrue(correctly_ordered(p))
2111
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002112 def test_update(self):
2113 c = Counter()
2114 c.update(self=42)
2115 self.assertEqual(list(c.items()), [('self', 42)])
2116 c = Counter()
2117 c.update(iterable=42)
2118 self.assertEqual(list(c.items()), [('iterable', 42)])
2119 c = Counter()
2120 c.update(iterable=None)
2121 self.assertEqual(list(c.items()), [('iterable', None)])
2122 self.assertRaises(TypeError, Counter().update, 42)
2123 self.assertRaises(TypeError, Counter().update, {}, {})
2124 self.assertRaises(TypeError, Counter.update)
2125
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002126 def test_copying(self):
2127 # Check that counters are copyable, deepcopyable, picklable, and
2128 #have a repr/eval round-trip
2129 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002130 def check(dup):
2131 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2132 self.assertIsNot(dup, words, msg)
2133 self.assertEqual(dup, words)
2134 check(words.copy())
2135 check(copy.copy(words))
2136 check(copy.deepcopy(words))
2137 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2138 with self.subTest(proto=proto):
2139 check(pickle.loads(pickle.dumps(words, proto)))
2140 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002141 update_test = Counter()
2142 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002143 check(update_test)
2144 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002145
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002146 def test_copy_subclass(self):
2147 class MyCounter(Counter):
2148 pass
2149 c = MyCounter('slartibartfast')
2150 d = c.copy()
2151 self.assertEqual(d, c)
2152 self.assertEqual(len(d), len(c))
2153 self.assertEqual(type(d), type(c))
2154
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002155 def test_conversions(self):
2156 # Convert to: set, list, dict
2157 s = 'she sells sea shells by the sea shore'
2158 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2159 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2160 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2161 self.assertEqual(set(Counter(s)), set(s))
2162
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002163 def test_invariant_for_the_in_operator(self):
2164 c = Counter(a=10, b=-2, c=0)
2165 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002166 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002167 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002168
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002169 def test_multiset_operations(self):
2170 # Verify that adding a zero counter will strip zeros and negatives
2171 c = Counter(a=10, b=-2, c=0) + Counter()
2172 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002173
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002174 elements = 'abcd'
2175 for i in range(1000):
2176 # test random pairs of multisets
2177 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002178 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002179 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002180 q.update(h=1, i=-1, j=0)
2181 for counterop, numberop in [
2182 (Counter.__add__, lambda x, y: max(0, x+y)),
2183 (Counter.__sub__, lambda x, y: max(0, x-y)),
2184 (Counter.__or__, lambda x, y: max(0,x,y)),
2185 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002186 ]:
2187 result = counterop(p, q)
2188 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002189 self.assertEqual(numberop(p[x], q[x]), result[x],
2190 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002191 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002192 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002193
2194 elements = 'abcdef'
2195 for i in range(100):
2196 # verify that random multisets with no repeats are exactly like sets
2197 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2198 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2199 for counterop, setop in [
2200 (Counter.__sub__, set.__sub__),
2201 (Counter.__or__, set.__or__),
2202 (Counter.__and__, set.__and__),
2203 ]:
2204 counter_result = counterop(p, q)
2205 set_result = setop(set(p.elements()), set(q.elements()))
2206 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002207
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002208 def test_inplace_operations(self):
2209 elements = 'abcd'
2210 for i in range(1000):
2211 # test random pairs of multisets
2212 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2213 p.update(e=1, f=-1, g=0)
2214 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2215 q.update(h=1, i=-1, j=0)
2216 for inplace_op, regular_op in [
2217 (Counter.__iadd__, Counter.__add__),
2218 (Counter.__isub__, Counter.__sub__),
2219 (Counter.__ior__, Counter.__or__),
2220 (Counter.__iand__, Counter.__and__),
2221 ]:
2222 c = p.copy()
2223 c_id = id(c)
2224 regular_result = regular_op(c, q)
2225 inplace_result = inplace_op(c, q)
2226 self.assertEqual(inplace_result, regular_result)
2227 self.assertEqual(id(inplace_result), c_id)
2228
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002229 def test_subtract(self):
2230 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2231 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2232 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2233 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2234 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2235 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2236 c = Counter('aaabbcd')
2237 c.subtract('aaaabbcce')
2238 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002239
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002240 c = Counter()
2241 c.subtract(self=42)
2242 self.assertEqual(list(c.items()), [('self', -42)])
2243 c = Counter()
2244 c.subtract(iterable=42)
2245 self.assertEqual(list(c.items()), [('iterable', -42)])
2246 self.assertRaises(TypeError, Counter().subtract, 42)
2247 self.assertRaises(TypeError, Counter().subtract, {}, {})
2248 self.assertRaises(TypeError, Counter.subtract)
2249
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002250 def test_unary(self):
2251 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2252 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2253 self.assertEqual(dict(-c), dict(a=5))
2254
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002255 def test_repr_nonsortable(self):
2256 c = Counter(a=2, b=None)
2257 r = repr(c)
2258 self.assertIn("'a': 2", r)
2259 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002260
Raymond Hettinger426e0522011-01-03 02:12:02 +00002261 def test_helper_function(self):
2262 # two paths, one for real dicts and one for other mappings
2263 elems = list('abracadabra')
2264
2265 d = dict()
2266 _count_elements(d, elems)
2267 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2268
2269 m = OrderedDict()
2270 _count_elements(m, elems)
2271 self.assertEqual(m,
2272 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2273
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002274 # test fidelity to the pure python version
2275 c = CounterSubclassWithSetItem('abracadabra')
2276 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002277 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002278 c = CounterSubclassWithGet('abracadabra')
2279 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002280 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002281
Raymond Hettinger60398512020-05-28 08:35:46 -07002282 def test_multiset_operations_equivalent_to_set_operations(self):
2283 # When the multiplicities are all zero or one, multiset operations
2284 # are guaranteed to be equivalent to the corresponding operations
2285 # for regular sets.
2286 s = list(product(('a', 'b', 'c'), range(2)))
2287 powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
2288 counters = [Counter(dict(groups)) for groups in powerset]
2289 for cp, cq in product(counters, repeat=2):
2290 sp = set(cp.elements())
2291 sq = set(cq.elements())
2292 self.assertEqual(set(cp + cq), sp | sq)
2293 self.assertEqual(set(cp - cq), sp - sq)
2294 self.assertEqual(set(cp | cq), sp | sq)
2295 self.assertEqual(set(cp & cq), sp & sq)
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002296 self.assertEqual(cp == cq, sp == sq)
2297 self.assertEqual(cp != cq, sp != sq)
2298 self.assertEqual(cp <= cq, sp <= sq)
2299 self.assertEqual(cp >= cq, sp >= sq)
2300 self.assertEqual(cp < cq, sp < sq)
2301 self.assertEqual(cp > cq, sp > sq)
Raymond Hettinger60398512020-05-28 08:35:46 -07002302
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002303 def test_eq(self):
2304 self.assertEqual(Counter(a=3, b=2, c=0), Counter('ababa'))
2305 self.assertNotEqual(Counter(a=3, b=2), Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002306
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002307 def test_le(self):
2308 self.assertTrue(Counter(a=3, b=2, c=0) <= Counter('ababa'))
2309 self.assertFalse(Counter(a=3, b=2) <= Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002310
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002311 def test_lt(self):
2312 self.assertTrue(Counter(a=3, b=1, c=0) < Counter('ababa'))
2313 self.assertFalse(Counter(a=3, b=2, c=0) < Counter('ababa'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002314
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002315 def test_ge(self):
2316 self.assertTrue(Counter(a=2, b=1, c=0) >= Counter('aab'))
2317 self.assertFalse(Counter(a=3, b=2, c=0) >= Counter('aabd'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002318
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002319 def test_gt(self):
2320 self.assertTrue(Counter(a=3, b=2, c=0) > Counter('aab'))
2321 self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002322
Raymond Hettinger499e1932011-02-23 07:56:53 +00002323
2324################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002325### Run tests
2326################################################################################
2327
Guido van Rossumd8faa362007-04-27 19:54:29 +00002328def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002329 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002330 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002331 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002332 TestUserObjects,
2333 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002334 support.run_unittest(*test_classes)
2335 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002336
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002337
Guido van Rossumd8faa362007-04-27 19:54:29 +00002338if __name__ == "__main__":
2339 test_main(verbose=True)