blob: befb7ab436c40af836509a985845f82188cfd2e9 [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):
685 self.assertEqual(
686 namedtuple('C', ()).__new__.__globals__['__builtins__'],
687 {})
688
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700689
Raymond Hettinger499e1932011-02-23 07:56:53 +0000690################################################################################
691### Abstract Base Classes
692################################################################################
693
Raymond Hettingerae650182009-01-28 23:33:59 +0000694class ABCTestCase(unittest.TestCase):
695
696 def validate_abstract_methods(self, abc, *names):
697 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
698
699 # everything should work will all required methods are present
700 C = type('C', (abc,), methodstubs)
701 C()
702
703 # instantiation should fail if a required method is missing
704 for name in names:
705 stubs = methodstubs.copy()
706 del stubs[name]
707 C = type('C', (abc,), stubs)
708 self.assertRaises(TypeError, C, name)
709
Florent Xiclunace153f62010-03-08 15:34:35 +0000710 def validate_isinstance(self, abc, name):
711 stub = lambda s, *args: 0
712
713 C = type('C', (object,), {'__hash__': None})
714 setattr(C, name, stub)
715 self.assertIsInstance(C(), abc)
716 self.assertTrue(issubclass(C, abc))
717
718 C = type('C', (object,), {'__hash__': None})
719 self.assertNotIsInstance(C(), abc)
720 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000721
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000722 def validate_comparison(self, instance):
723 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
724 operators = {}
725 for op in ops:
726 name = '__' + op + '__'
727 operators[name] = getattr(operator, name)
728
729 class Other:
730 def __init__(self):
731 self.right_side = False
732 def __eq__(self, other):
733 self.right_side = True
734 return True
735 __lt__ = __eq__
736 __gt__ = __eq__
737 __le__ = __eq__
738 __ge__ = __eq__
739 __ne__ = __eq__
740 __ror__ = __eq__
741 __rand__ = __eq__
742 __rxor__ = __eq__
743 __rsub__ = __eq__
744
745 for name, op in operators.items():
746 if not hasattr(instance, name):
747 continue
748 other = Other()
749 op(instance, other)
750 self.assertTrue(other.right_side,'Right side not called for %s.%s'
751 % (type(instance), name))
752
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700753def _test_gen():
754 yield
755
Raymond Hettingerae650182009-01-28 23:33:59 +0000756class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000757
Yury Selivanov75445082015-05-11 22:57:16 -0400758 def test_Awaitable(self):
759 def gen():
760 yield
761
762 @types.coroutine
763 def coro():
764 yield
765
766 async def new_coro():
767 pass
768
769 class Bar:
770 def __await__(self):
771 yield
772
773 class MinimalCoro(Coroutine):
774 def send(self, value):
775 return value
776 def throw(self, typ, val=None, tb=None):
777 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400778 def __await__(self):
779 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400780
781 non_samples = [None, int(), gen(), object()]
782 for x in non_samples:
783 self.assertNotIsInstance(x, Awaitable)
784 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
785
786 samples = [Bar(), MinimalCoro()]
787 for x in samples:
788 self.assertIsInstance(x, Awaitable)
789 self.assertTrue(issubclass(type(x), Awaitable))
790
791 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400792 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
793 # flag don't have '__await__' method, hence can't be instances
794 # of Awaitable. Use inspect.isawaitable to detect them.
795 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400796
797 c = new_coro()
798 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300799 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400800
Yury Selivanov56fc6142015-05-29 09:01:29 -0400801 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400802 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400803 self.assertTrue(isinstance(CoroLike(), Awaitable))
804 self.assertTrue(issubclass(CoroLike, Awaitable))
805 CoroLike = None
806 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400807
Yury Selivanov75445082015-05-11 22:57:16 -0400808 def test_Coroutine(self):
809 def gen():
810 yield
811
812 @types.coroutine
813 def coro():
814 yield
815
816 async def new_coro():
817 pass
818
819 class Bar:
820 def __await__(self):
821 yield
822
823 class MinimalCoro(Coroutine):
824 def send(self, value):
825 return value
826 def throw(self, typ, val=None, tb=None):
827 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400828 def __await__(self):
829 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400830
831 non_samples = [None, int(), gen(), object(), Bar()]
832 for x in non_samples:
833 self.assertNotIsInstance(x, Coroutine)
834 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
835
836 samples = [MinimalCoro()]
837 for x in samples:
838 self.assertIsInstance(x, Awaitable)
839 self.assertTrue(issubclass(type(x), Awaitable))
840
841 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400842 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
843 # flag don't have '__await__' method, hence can't be instances
844 # of Coroutine. Use inspect.isawaitable to detect them.
845 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400846
847 c = new_coro()
848 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300849 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400850
Yury Selivanov56fc6142015-05-29 09:01:29 -0400851 class CoroLike:
852 def send(self, value):
853 pass
854 def throw(self, typ, val=None, tb=None):
855 pass
856 def close(self):
857 pass
858 def __await__(self):
859 pass
860 self.assertTrue(isinstance(CoroLike(), Coroutine))
861 self.assertTrue(issubclass(CoroLike, Coroutine))
862
863 class CoroLike:
864 def send(self, value):
865 pass
866 def close(self):
867 pass
868 def __await__(self):
869 pass
870 self.assertFalse(isinstance(CoroLike(), Coroutine))
871 self.assertFalse(issubclass(CoroLike, Coroutine))
872
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000873 def test_Hashable(self):
874 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000875 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000876 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000877 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000878 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000879 # Check some hashables
880 samples = [None,
881 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000882 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000883 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000884 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000885 ]
886 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000887 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000888 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000889 self.assertRaises(TypeError, Hashable)
890 # Check direct subclassing
891 class H(Hashable):
892 def __hash__(self):
893 return super().__hash__()
894 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000895 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000896 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000897 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000898
Yury Selivanove0104ae2015-05-14 12:19:16 -0400899 def test_AsyncIterable(self):
900 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400901 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400902 return self
903 self.assertTrue(isinstance(AI(), AsyncIterable))
904 self.assertTrue(issubclass(AI, AsyncIterable))
905 # Check some non-iterables
906 non_samples = [None, object, []]
907 for x in non_samples:
908 self.assertNotIsInstance(x, AsyncIterable)
909 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
910 self.validate_abstract_methods(AsyncIterable, '__aiter__')
911 self.validate_isinstance(AsyncIterable, '__aiter__')
912
913 def test_AsyncIterator(self):
914 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400915 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400916 return self
917 async def __anext__(self):
918 raise StopAsyncIteration
919 self.assertTrue(isinstance(AI(), AsyncIterator))
920 self.assertTrue(issubclass(AI, AsyncIterator))
921 non_samples = [None, object, []]
922 # Check some non-iterables
923 for x in non_samples:
924 self.assertNotIsInstance(x, AsyncIterator)
925 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
926 # Similarly to regular iterators (see issue 10565)
927 class AnextOnly:
928 async def __anext__(self):
929 raise StopAsyncIteration
930 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
931 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
932
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000933 def test_Iterable(self):
934 # Check some non-iterables
935 non_samples = [None, 42, 3.14, 1j]
936 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000937 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000938 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000939 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000940 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000941 tuple(), list(), set(), frozenset(), dict(),
942 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700943 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000944 (x for x in []),
945 ]
946 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000947 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000948 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000949 # Check direct subclassing
950 class I(Iterable):
951 def __iter__(self):
952 return super().__iter__()
953 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000954 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000955 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000956 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700957 # Check None blocking
958 class It:
959 def __iter__(self): return iter([])
960 class ItBlocked(It):
961 __iter__ = None
962 self.assertTrue(issubclass(It, Iterable))
963 self.assertTrue(isinstance(It(), Iterable))
964 self.assertFalse(issubclass(ItBlocked, Iterable))
965 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000966
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700967 def test_Reversible(self):
968 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100969 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700970 for x in non_samples:
971 self.assertNotIsInstance(x, Reversible)
972 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700973 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100974 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700975 for x in non_reversibles:
976 self.assertNotIsInstance(x, Reversible)
977 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
978 # Check some reversible iterables
979 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
980 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100981 OrderedDict().values(), Counter(), Counter().keys(),
982 Counter().items(), Counter().values(), dict(),
983 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700984 for x in samples:
985 self.assertIsInstance(x, Reversible)
986 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
987 # Check also Mapping, MutableMapping, and Sequence
988 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
989 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
990 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
991 # Check direct subclassing
992 class R(Reversible):
993 def __iter__(self):
994 return iter(list())
995 def __reversed__(self):
996 return iter(list())
997 self.assertEqual(list(reversed(R())), [])
998 self.assertFalse(issubclass(float, R))
999 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001000 # Check reversible non-iterable (which is not Reversible)
1001 class RevNoIter:
1002 def __reversed__(self): return reversed([])
1003 class RevPlusIter(RevNoIter):
1004 def __iter__(self): return iter([])
1005 self.assertFalse(issubclass(RevNoIter, Reversible))
1006 self.assertFalse(isinstance(RevNoIter(), Reversible))
1007 self.assertTrue(issubclass(RevPlusIter, Reversible))
1008 self.assertTrue(isinstance(RevPlusIter(), Reversible))
1009 # Check None blocking
1010 class Rev:
1011 def __iter__(self): return iter([])
1012 def __reversed__(self): return reversed([])
1013 class RevItBlocked(Rev):
1014 __iter__ = None
1015 class RevRevBlocked(Rev):
1016 __reversed__ = None
1017 self.assertTrue(issubclass(Rev, Reversible))
1018 self.assertTrue(isinstance(Rev(), Reversible))
1019 self.assertFalse(issubclass(RevItBlocked, Reversible))
1020 self.assertFalse(isinstance(RevItBlocked(), Reversible))
1021 self.assertFalse(issubclass(RevRevBlocked, Reversible))
1022 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001023
Guido van Rossumf0666942016-08-23 10:47:07 -07001024 def test_Collection(self):
1025 # Check some non-collections
1026 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
1027 for x in non_collections:
1028 self.assertNotIsInstance(x, Collection)
1029 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1030 # Check some non-collection iterables
1031 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001032 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -07001033 for x in non_col_iterables:
1034 self.assertNotIsInstance(x, Collection)
1035 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1036 # Check some collections
1037 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001038 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001039 for x in samples:
1040 self.assertIsInstance(x, Collection)
1041 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1042 # Check also Mapping, MutableMapping, etc.
1043 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1044 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1045 self.assertTrue(issubclass(MutableMapping, Collection),
1046 repr(MutableMapping))
1047 self.assertTrue(issubclass(Set, Collection), repr(Set))
1048 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1049 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1050 # Check direct subclassing
1051 class Col(Collection):
1052 def __iter__(self):
1053 return iter(list())
1054 def __len__(self):
1055 return 0
1056 def __contains__(self, item):
1057 return False
1058 class DerCol(Col): pass
1059 self.assertEqual(list(iter(Col())), [])
1060 self.assertFalse(issubclass(list, Col))
1061 self.assertFalse(issubclass(set, Col))
1062 self.assertFalse(issubclass(float, Col))
1063 self.assertEqual(list(iter(DerCol())), [])
1064 self.assertFalse(issubclass(list, DerCol))
1065 self.assertFalse(issubclass(set, DerCol))
1066 self.assertFalse(issubclass(float, DerCol))
1067 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1068 '__contains__')
1069 # Check sized container non-iterable (which is not Collection) etc.
1070 class ColNoIter:
1071 def __len__(self): return 0
1072 def __contains__(self, item): return False
1073 class ColNoSize:
1074 def __iter__(self): return iter([])
1075 def __contains__(self, item): return False
1076 class ColNoCont:
1077 def __iter__(self): return iter([])
1078 def __len__(self): return 0
1079 self.assertFalse(issubclass(ColNoIter, Collection))
1080 self.assertFalse(isinstance(ColNoIter(), Collection))
1081 self.assertFalse(issubclass(ColNoSize, Collection))
1082 self.assertFalse(isinstance(ColNoSize(), Collection))
1083 self.assertFalse(issubclass(ColNoCont, Collection))
1084 self.assertFalse(isinstance(ColNoCont(), Collection))
1085 # Check None blocking
1086 class SizeBlock:
1087 def __iter__(self): return iter([])
1088 def __contains__(self): return False
1089 __len__ = None
1090 class IterBlock:
1091 def __len__(self): return 0
1092 def __contains__(self): return True
1093 __iter__ = None
1094 self.assertFalse(issubclass(SizeBlock, Collection))
1095 self.assertFalse(isinstance(SizeBlock(), Collection))
1096 self.assertFalse(issubclass(IterBlock, Collection))
1097 self.assertFalse(isinstance(IterBlock(), Collection))
1098 # Check None blocking in subclass
1099 class ColImpl:
1100 def __iter__(self):
1101 return iter(list())
1102 def __len__(self):
1103 return 0
1104 def __contains__(self, item):
1105 return False
1106 class NonCol(ColImpl):
1107 __contains__ = None
1108 self.assertFalse(issubclass(NonCol, Collection))
1109 self.assertFalse(isinstance(NonCol(), Collection))
1110
1111
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001112 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001113 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001114 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001115 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001116 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001117 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001118 iter(tuple()), iter(list()), iter(dict()),
1119 iter(set()), iter(frozenset()),
1120 iter(dict().keys()), iter(dict().items()),
1121 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001122 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001123 (x for x in []),
1124 ]
1125 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001126 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001127 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001128 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1129
1130 # Issue 10565
1131 class NextOnly:
1132 def __next__(self):
1133 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001134 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001135 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001136
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001137 def test_Generator(self):
1138 class NonGen1:
1139 def __iter__(self): return self
1140 def __next__(self): return None
1141 def close(self): pass
1142 def throw(self, typ, val=None, tb=None): pass
1143
1144 class NonGen2:
1145 def __iter__(self): return self
1146 def __next__(self): return None
1147 def close(self): pass
1148 def send(self, value): return value
1149
1150 class NonGen3:
1151 def close(self): pass
1152 def send(self, value): return value
1153 def throw(self, typ, val=None, tb=None): pass
1154
1155 non_samples = [
1156 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1157 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1158 for x in non_samples:
1159 self.assertNotIsInstance(x, Generator)
1160 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1161
1162 class Gen:
1163 def __iter__(self): return self
1164 def __next__(self): return None
1165 def close(self): pass
1166 def send(self, value): return value
1167 def throw(self, typ, val=None, tb=None): pass
1168
1169 class MinimalGen(Generator):
1170 def send(self, value):
1171 return value
1172 def throw(self, typ, val=None, tb=None):
1173 super().throw(typ, val, tb)
1174
1175 def gen():
1176 yield 1
1177
1178 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1179 for x in samples:
1180 self.assertIsInstance(x, Iterator)
1181 self.assertIsInstance(x, Generator)
1182 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1183 self.validate_abstract_methods(Generator, 'send', 'throw')
1184
1185 # mixin tests
1186 mgen = MinimalGen()
1187 self.assertIs(mgen, iter(mgen))
1188 self.assertIs(mgen.send(None), next(mgen))
1189 self.assertEqual(2, mgen.send(2))
1190 self.assertIsNone(mgen.close())
1191 self.assertRaises(ValueError, mgen.throw, ValueError)
1192 self.assertRaisesRegex(ValueError, "^huhu$",
1193 mgen.throw, ValueError, ValueError("huhu"))
1194 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1195
1196 class FailOnClose(Generator):
1197 def send(self, value): return value
1198 def throw(self, *args): raise ValueError
1199
1200 self.assertRaises(ValueError, FailOnClose().close)
1201
1202 class IgnoreGeneratorExit(Generator):
1203 def send(self, value): return value
1204 def throw(self, *args): pass
1205
1206 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1207
Yury Selivanov22214ab2016-11-16 18:25:04 -05001208 def test_AsyncGenerator(self):
1209 class NonAGen1:
1210 def __aiter__(self): return self
1211 def __anext__(self): return None
1212 def aclose(self): pass
1213 def athrow(self, typ, val=None, tb=None): pass
1214
1215 class NonAGen2:
1216 def __aiter__(self): return self
1217 def __anext__(self): return None
1218 def aclose(self): pass
1219 def asend(self, value): return value
1220
1221 class NonAGen3:
1222 def aclose(self): pass
1223 def asend(self, value): return value
1224 def athrow(self, typ, val=None, tb=None): pass
1225
1226 non_samples = [
1227 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1228 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1229 for x in non_samples:
1230 self.assertNotIsInstance(x, AsyncGenerator)
1231 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1232
1233 class Gen:
1234 def __aiter__(self): return self
1235 async def __anext__(self): return None
1236 async def aclose(self): pass
1237 async def asend(self, value): return value
1238 async def athrow(self, typ, val=None, tb=None): pass
1239
1240 class MinimalAGen(AsyncGenerator):
1241 async def asend(self, value):
1242 return value
1243 async def athrow(self, typ, val=None, tb=None):
1244 await super().athrow(typ, val, tb)
1245
1246 async def gen():
1247 yield 1
1248
1249 samples = [gen(), Gen(), MinimalAGen()]
1250 for x in samples:
1251 self.assertIsInstance(x, AsyncIterator)
1252 self.assertIsInstance(x, AsyncGenerator)
1253 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1254 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1255
1256 def run_async(coro):
1257 result = None
1258 while True:
1259 try:
1260 coro.send(None)
1261 except StopIteration as ex:
1262 result = ex.args[0] if ex.args else None
1263 break
1264 return result
1265
1266 # mixin tests
1267 mgen = MinimalAGen()
1268 self.assertIs(mgen, mgen.__aiter__())
1269 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1270 self.assertEqual(2, run_async(mgen.asend(2)))
1271 self.assertIsNone(run_async(mgen.aclose()))
1272 with self.assertRaises(ValueError):
1273 run_async(mgen.athrow(ValueError))
1274
1275 class FailOnClose(AsyncGenerator):
1276 async def asend(self, value): return value
1277 async def athrow(self, *args): raise ValueError
1278
1279 with self.assertRaises(ValueError):
1280 run_async(FailOnClose().aclose())
1281
1282 class IgnoreGeneratorExit(AsyncGenerator):
1283 async def asend(self, value): return value
1284 async def athrow(self, *args): pass
1285
1286 with self.assertRaises(RuntimeError):
1287 run_async(IgnoreGeneratorExit().aclose())
1288
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001289 def test_Sized(self):
1290 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001291 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001292 (x for x in []),
1293 ]
1294 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001295 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001296 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001297 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001298 tuple(), list(), set(), frozenset(), dict(),
1299 dict().keys(), dict().items(), dict().values(),
1300 ]
1301 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001302 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001303 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001304 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001305 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001306
1307 def test_Container(self):
1308 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001309 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001310 (x for x in []),
1311 ]
1312 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001313 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001314 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001315 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001316 tuple(), list(), set(), frozenset(), dict(),
1317 dict().keys(), dict().items(),
1318 ]
1319 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001320 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001321 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001322 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001323 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001324
1325 def test_Callable(self):
1326 non_samples = [None, 42, 3.14, 1j,
1327 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001328 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001329 (x for x in []),
1330 ]
1331 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001332 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001333 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001334 samples = [lambda: None,
1335 type, int, object,
1336 len,
1337 list.append, [].append,
1338 ]
1339 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001340 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001341 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001342 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001343 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001344
1345 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001346 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001347 class C(B):
1348 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001349 self.assertTrue(issubclass(C, B))
1350 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001351
1352 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001353 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001354 class C:
1355 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001356 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001357 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001358 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001359
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001360class WithSet(MutableSet):
1361
1362 def __init__(self, it=()):
1363 self.data = set(it)
1364
1365 def __len__(self):
1366 return len(self.data)
1367
1368 def __iter__(self):
1369 return iter(self.data)
1370
1371 def __contains__(self, item):
1372 return item in self.data
1373
1374 def add(self, item):
1375 self.data.add(item)
1376
1377 def discard(self, item):
1378 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001379
Raymond Hettingerae650182009-01-28 23:33:59 +00001380class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001381
1382 # XXX For now, we only test some virtual inheritance properties.
1383 # We should also test the proper behavior of the collection ABCs
1384 # as real base classes or mix-in classes.
1385
1386 def test_Set(self):
1387 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001388 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001389 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001390 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001391 class MySet(Set):
1392 def __contains__(self, x):
1393 return False
1394 def __len__(self):
1395 return 0
1396 def __iter__(self):
1397 return iter([])
1398 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001399
Benjamin Peterson41181742008-07-02 20:22:54 +00001400 def test_hash_Set(self):
1401 class OneTwoThreeSet(Set):
1402 def __init__(self):
1403 self.contents = [1, 2, 3]
1404 def __contains__(self, x):
1405 return x in self.contents
1406 def __len__(self):
1407 return len(self.contents)
1408 def __iter__(self):
1409 return iter(self.contents)
1410 def __hash__(self):
1411 return self._hash()
1412 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001413 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001414
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001415 def test_isdisjoint_Set(self):
1416 class MySet(Set):
1417 def __init__(self, itr):
1418 self.contents = itr
1419 def __contains__(self, x):
1420 return x in self.contents
1421 def __iter__(self):
1422 return iter(self.contents)
1423 def __len__(self):
1424 return len([x for x in self.contents])
1425 s1 = MySet((1, 2, 3))
1426 s2 = MySet((4, 5, 6))
1427 s3 = MySet((1, 5, 6))
1428 self.assertTrue(s1.isdisjoint(s2))
1429 self.assertFalse(s1.isdisjoint(s3))
1430
1431 def test_equality_Set(self):
1432 class MySet(Set):
1433 def __init__(self, itr):
1434 self.contents = itr
1435 def __contains__(self, x):
1436 return x in self.contents
1437 def __iter__(self):
1438 return iter(self.contents)
1439 def __len__(self):
1440 return len([x for x in self.contents])
1441 s1 = MySet((1,))
1442 s2 = MySet((1, 2))
1443 s3 = MySet((3, 4))
1444 s4 = MySet((3, 4))
1445 self.assertTrue(s2 > s1)
1446 self.assertTrue(s1 < s2)
1447 self.assertFalse(s2 <= s1)
1448 self.assertFalse(s2 <= s3)
1449 self.assertFalse(s1 >= s2)
1450 self.assertEqual(s3, s4)
1451 self.assertNotEqual(s2, s3)
1452
1453 def test_arithmetic_Set(self):
1454 class MySet(Set):
1455 def __init__(self, itr):
1456 self.contents = itr
1457 def __contains__(self, x):
1458 return x in self.contents
1459 def __iter__(self):
1460 return iter(self.contents)
1461 def __len__(self):
1462 return len([x for x in self.contents])
1463 s1 = MySet((1, 2, 3))
1464 s2 = MySet((3, 4, 5))
1465 s3 = s1 & s2
1466 self.assertEqual(s3, MySet((3,)))
1467
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001468 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001469 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001470 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001471 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001472 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001473 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1474 'add', 'discard')
1475
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001476 def test_issue_5647(self):
1477 # MutableSet.__iand__ mutated the set during iteration
1478 s = WithSet('abcd')
1479 s &= WithSet('cdef') # This used to fail
1480 self.assertEqual(set(s), set('cd'))
1481
Raymond Hettingerae650182009-01-28 23:33:59 +00001482 def test_issue_4920(self):
1483 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001484 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001485 __slots__=['__s']
1486 def __init__(self,items=None):
1487 if items is None:
1488 items=[]
1489 self.__s=set(items)
1490 def __contains__(self,v):
1491 return v in self.__s
1492 def __iter__(self):
1493 return iter(self.__s)
1494 def __len__(self):
1495 return len(self.__s)
1496 def add(self,v):
1497 result=v not in self.__s
1498 self.__s.add(v)
1499 return result
1500 def discard(self,v):
1501 result=v in self.__s
1502 self.__s.discard(v)
1503 return result
1504 def __repr__(self):
1505 return "MySet(%s)" % repr(list(self))
1506 s = MySet([5,43,2,1])
1507 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001508
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001509 def test_issue8750(self):
1510 empty = WithSet()
1511 full = WithSet(range(10))
1512 s = WithSet(full)
1513 s -= s
1514 self.assertEqual(s, empty)
1515 s = WithSet(full)
1516 s ^= s
1517 self.assertEqual(s, empty)
1518 s = WithSet(full)
1519 s &= s
1520 self.assertEqual(s, full)
1521 s |= s
1522 self.assertEqual(s, full)
1523
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001524 def test_issue16373(self):
1525 # Recursion error comparing comparable and noncomparable
1526 # Set instances
1527 class MyComparableSet(Set):
1528 def __contains__(self, x):
1529 return False
1530 def __len__(self):
1531 return 0
1532 def __iter__(self):
1533 return iter([])
1534 class MyNonComparableSet(Set):
1535 def __contains__(self, x):
1536 return False
1537 def __len__(self):
1538 return 0
1539 def __iter__(self):
1540 return iter([])
1541 def __le__(self, x):
1542 return NotImplemented
1543 def __lt__(self, x):
1544 return NotImplemented
1545
1546 cs = MyComparableSet()
1547 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001548 self.assertFalse(ncs < cs)
1549 self.assertTrue(ncs <= cs)
1550 self.assertFalse(ncs > cs)
1551 self.assertTrue(ncs >= cs)
1552
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001553 def test_issue26915(self):
1554 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001555 class CustomSequence(Sequence):
1556 def __init__(self, seq):
1557 self._seq = seq
1558 def __getitem__(self, index):
1559 return self._seq[index]
1560 def __len__(self):
1561 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001562
1563 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001564 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001565 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001566 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001567 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001568 ItemsView({1: nan, 2: obj}),
1569 ValuesView({1: nan, 2: obj})
1570 ]
1571 for container in containers:
1572 for elem in container:
1573 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001574 self.assertEqual(seq.index(nan), 0)
1575 self.assertEqual(seq.index(obj), 1)
1576 self.assertEqual(seq.count(nan), 2)
1577 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001578
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001579 def assertSameSet(self, s1, s2):
1580 # coerce both to a real set then check equality
1581 self.assertSetEqual(set(s1), set(s2))
1582
Richard Levasseur68f68fa2020-11-21 11:56:24 -08001583 def test_Set_from_iterable(self):
1584 """Verify _from_iterable overriden to an instance method works."""
1585 class SetUsingInstanceFromIterable(MutableSet):
1586 def __init__(self, values, created_by):
1587 if not created_by:
1588 raise ValueError(f'created_by must be specified')
1589 self.created_by = created_by
1590 self._values = set(values)
1591
1592 def _from_iterable(self, values):
1593 return type(self)(values, 'from_iterable')
1594
1595 def __contains__(self, value):
1596 return value in self._values
1597
1598 def __iter__(self):
1599 yield from self._values
1600
1601 def __len__(self):
1602 return len(self._values)
1603
1604 def add(self, value):
1605 self._values.add(value)
1606
1607 def discard(self, value):
1608 self._values.discard(value)
1609
1610 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
1611
1612 actual = impl - {1}
1613 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1614 self.assertEqual('from_iterable', actual.created_by)
1615 self.assertEqual({2, 3}, actual)
1616
1617 actual = impl | {4}
1618 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1619 self.assertEqual('from_iterable', actual.created_by)
1620 self.assertEqual({1, 2, 3, 4}, actual)
1621
1622 actual = impl & {2}
1623 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1624 self.assertEqual('from_iterable', actual.created_by)
1625 self.assertEqual({2}, actual)
1626
1627 actual = impl ^ {3, 4}
1628 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1629 self.assertEqual('from_iterable', actual.created_by)
1630 self.assertEqual({1, 2, 4}, actual)
1631
1632 # NOTE: ixor'ing with a list is important here: internally, __ixor__
1633 # only calls _from_iterable if the other value isn't already a Set.
1634 impl ^= [3, 4]
1635 self.assertIsInstance(impl, SetUsingInstanceFromIterable)
1636 self.assertEqual('test', impl.created_by)
1637 self.assertEqual({1, 2, 4}, impl)
1638
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001639 def test_Set_interoperability_with_real_sets(self):
1640 # Issue: 8743
1641 class ListSet(Set):
1642 def __init__(self, elements=()):
1643 self.data = []
1644 for elem in elements:
1645 if elem not in self.data:
1646 self.data.append(elem)
1647 def __contains__(self, elem):
1648 return elem in self.data
1649 def __iter__(self):
1650 return iter(self.data)
1651 def __len__(self):
1652 return len(self.data)
1653 def __repr__(self):
1654 return 'Set({!r})'.format(self.data)
1655
1656 r1 = set('abc')
1657 r2 = set('bcd')
1658 r3 = set('abcde')
1659 f1 = ListSet('abc')
1660 f2 = ListSet('bcd')
1661 f3 = ListSet('abcde')
1662 l1 = list('abccba')
1663 l2 = list('bcddcb')
1664 l3 = list('abcdeedcba')
1665
1666 target = r1 & r2
1667 self.assertSameSet(f1 & f2, target)
1668 self.assertSameSet(f1 & r2, target)
1669 self.assertSameSet(r2 & f1, target)
1670 self.assertSameSet(f1 & l2, target)
1671
1672 target = r1 | r2
1673 self.assertSameSet(f1 | f2, target)
1674 self.assertSameSet(f1 | r2, target)
1675 self.assertSameSet(r2 | f1, target)
1676 self.assertSameSet(f1 | l2, target)
1677
1678 fwd_target = r1 - r2
1679 rev_target = r2 - r1
1680 self.assertSameSet(f1 - f2, fwd_target)
1681 self.assertSameSet(f2 - f1, rev_target)
1682 self.assertSameSet(f1 - r2, fwd_target)
1683 self.assertSameSet(f2 - r1, rev_target)
1684 self.assertSameSet(r1 - f2, fwd_target)
1685 self.assertSameSet(r2 - f1, rev_target)
1686 self.assertSameSet(f1 - l2, fwd_target)
1687 self.assertSameSet(f2 - l1, rev_target)
1688
1689 target = r1 ^ r2
1690 self.assertSameSet(f1 ^ f2, target)
1691 self.assertSameSet(f1 ^ r2, target)
1692 self.assertSameSet(r2 ^ f1, target)
1693 self.assertSameSet(f1 ^ l2, target)
1694
1695 # Don't change the following to use assertLess or other
1696 # "more specific" unittest assertions. The current
1697 # assertTrue/assertFalse style makes the pattern of test
1698 # case combinations clear and allows us to know for sure
1699 # the exact operator being invoked.
1700
1701 # proper subset
1702 self.assertTrue(f1 < f3)
1703 self.assertFalse(f1 < f1)
1704 self.assertFalse(f1 < f2)
1705 self.assertTrue(r1 < f3)
1706 self.assertFalse(r1 < f1)
1707 self.assertFalse(r1 < f2)
1708 self.assertTrue(r1 < r3)
1709 self.assertFalse(r1 < r1)
1710 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001711 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001712 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001713 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001714 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001715 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001716 f1 < l2
1717
1718 # any subset
1719 self.assertTrue(f1 <= f3)
1720 self.assertTrue(f1 <= f1)
1721 self.assertFalse(f1 <= f2)
1722 self.assertTrue(r1 <= f3)
1723 self.assertTrue(r1 <= f1)
1724 self.assertFalse(r1 <= f2)
1725 self.assertTrue(r1 <= r3)
1726 self.assertTrue(r1 <= r1)
1727 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001728 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001729 f1 <= l3
1730 with self.assertRaises(TypeError):
1731 f1 <= l1
1732 with self.assertRaises(TypeError):
1733 f1 <= l2
1734
1735 # proper superset
1736 self.assertTrue(f3 > f1)
1737 self.assertFalse(f1 > f1)
1738 self.assertFalse(f2 > f1)
1739 self.assertTrue(r3 > r1)
1740 self.assertFalse(f1 > r1)
1741 self.assertFalse(f2 > r1)
1742 self.assertTrue(r3 > r1)
1743 self.assertFalse(r1 > r1)
1744 self.assertFalse(r2 > r1)
1745 with self.assertRaises(TypeError):
1746 f1 > l3
1747 with self.assertRaises(TypeError):
1748 f1 > l1
1749 with self.assertRaises(TypeError):
1750 f1 > l2
1751
1752 # any superset
1753 self.assertTrue(f3 >= f1)
1754 self.assertTrue(f1 >= f1)
1755 self.assertFalse(f2 >= f1)
1756 self.assertTrue(r3 >= r1)
1757 self.assertTrue(f1 >= r1)
1758 self.assertFalse(f2 >= r1)
1759 self.assertTrue(r3 >= r1)
1760 self.assertTrue(r1 >= r1)
1761 self.assertFalse(r2 >= r1)
1762 with self.assertRaises(TypeError):
1763 f1 >= l3
1764 with self.assertRaises(TypeError):
1765 f1 >=l1
1766 with self.assertRaises(TypeError):
1767 f1 >= l2
1768
1769 # equality
1770 self.assertTrue(f1 == f1)
1771 self.assertTrue(r1 == f1)
1772 self.assertTrue(f1 == r1)
1773 self.assertFalse(f1 == f3)
1774 self.assertFalse(r1 == f3)
1775 self.assertFalse(f1 == r3)
1776 self.assertFalse(f1 == l3)
1777 self.assertFalse(f1 == l1)
1778 self.assertFalse(f1 == l2)
1779
1780 # inequality
1781 self.assertFalse(f1 != f1)
1782 self.assertFalse(r1 != f1)
1783 self.assertFalse(f1 != r1)
1784 self.assertTrue(f1 != f3)
1785 self.assertTrue(r1 != f3)
1786 self.assertTrue(f1 != r3)
1787 self.assertTrue(f1 != l3)
1788 self.assertTrue(f1 != l1)
1789 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001790
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001791 def test_Mapping(self):
1792 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001793 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001794 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001795 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1796 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001797 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001798 def __len__(self):
1799 return 0
1800 def __getitem__(self, i):
1801 raise IndexError
1802 def __iter__(self):
1803 return iter(())
1804 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001805 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001806
1807 def test_MutableMapping(self):
1808 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001809 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001810 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001811 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1812 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001813
Raymond Hettinger9117c752010-08-22 07:44:24 +00001814 def test_MutableMapping_subclass(self):
1815 # Test issue 9214
1816 mymap = UserDict()
1817 mymap['red'] = 5
1818 self.assertIsInstance(mymap.keys(), Set)
1819 self.assertIsInstance(mymap.keys(), KeysView)
1820 self.assertIsInstance(mymap.items(), Set)
1821 self.assertIsInstance(mymap.items(), ItemsView)
1822
1823 mymap = UserDict()
1824 mymap['red'] = 5
1825 z = mymap.keys() | {'orange'}
1826 self.assertIsInstance(z, set)
1827 list(z)
1828 mymap['blue'] = 7 # Shouldn't affect 'z'
1829 self.assertEqual(sorted(z), ['orange', 'red'])
1830
1831 mymap = UserDict()
1832 mymap['red'] = 5
1833 z = mymap.items() | {('orange', 3)}
1834 self.assertIsInstance(z, set)
1835 list(z)
1836 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001837 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001838
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001839 def test_Sequence(self):
1840 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001841 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001842 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001843 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001844 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001845 self.assertIsInstance(memoryview(b""), Sequence)
1846 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001847 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001848 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1849 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001850
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001851 def test_Sequence_mixins(self):
1852 class SequenceSubclass(Sequence):
1853 def __init__(self, seq=()):
1854 self.seq = seq
1855
1856 def __getitem__(self, index):
1857 return self.seq[index]
1858
1859 def __len__(self):
1860 return len(self.seq)
1861
1862 # Compare Sequence.index() behavior to (list|str).index() behavior
1863 def assert_index_same(seq1, seq2, index_args):
1864 try:
1865 expected = seq1.index(*index_args)
1866 except ValueError:
1867 with self.assertRaises(ValueError):
1868 seq2.index(*index_args)
1869 else:
1870 actual = seq2.index(*index_args)
1871 self.assertEqual(
1872 actual, expected, '%r.index%s' % (seq1, index_args))
1873
1874 for ty in list, str:
1875 nativeseq = ty('abracadabra')
1876 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1877 seqseq = SequenceSubclass(nativeseq)
1878 for letter in set(nativeseq) | {'z'}:
1879 assert_index_same(nativeseq, seqseq, (letter,))
1880 for start in range(-3, len(nativeseq) + 3):
1881 assert_index_same(nativeseq, seqseq, (letter, start))
1882 for stop in range(-3, len(nativeseq) + 3):
1883 assert_index_same(
1884 nativeseq, seqseq, (letter, start, stop))
1885
Guido van Rossumd05eb002007-11-21 22:26:24 +00001886 def test_ByteString(self):
1887 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001888 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001889 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001890 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001891 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001892 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001893 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001894 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001895
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001896 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001897 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001898 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001899 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001900 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001901 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001902 self.assertTrue(issubclass(sample, MutableSequence))
1903 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001904 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1905 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001906
Eli Bendersky0716a572011-03-04 10:38:14 +00001907 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001908 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001909 # class inherited from it.
1910 class MutableSequenceSubclass(MutableSequence):
1911 def __init__(self):
1912 self.lst = []
1913
1914 def __setitem__(self, index, value):
1915 self.lst[index] = value
1916
1917 def __getitem__(self, index):
1918 return self.lst[index]
1919
1920 def __len__(self):
1921 return len(self.lst)
1922
1923 def __delitem__(self, index):
1924 del self.lst[index]
1925
1926 def insert(self, index, value):
1927 self.lst.insert(index, value)
1928
1929 mss = MutableSequenceSubclass()
1930 mss.append(0)
1931 mss.extend((1, 2, 3, 4))
1932 self.assertEqual(len(mss), 5)
1933 self.assertEqual(mss[3], 3)
1934 mss.reverse()
1935 self.assertEqual(mss[3], 1)
1936 mss.pop()
1937 self.assertEqual(len(mss), 4)
1938 mss.remove(3)
1939 self.assertEqual(len(mss), 3)
1940 mss += (10, 20, 30)
1941 self.assertEqual(len(mss), 6)
1942 self.assertEqual(mss[-1], 30)
1943 mss.clear()
1944 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001945
Naris R1b5f9c92018-08-31 02:56:14 +10001946 # issue 34427
1947 # extending self should not cause infinite loop
1948 items = 'ABCD'
1949 mss2 = MutableSequenceSubclass()
1950 mss2.extend(items + items)
1951 mss.clear()
1952 mss.extend(items)
1953 mss.extend(mss)
1954 self.assertEqual(len(mss), len(mss2))
1955 self.assertEqual(list(mss), list(mss2))
1956
1957
Raymond Hettinger499e1932011-02-23 07:56:53 +00001958################################################################################
1959### Counter
1960################################################################################
1961
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001962class CounterSubclassWithSetItem(Counter):
1963 # Test a counter subclass that overrides __setitem__
1964 def __init__(self, *args, **kwds):
1965 self.called = False
1966 Counter.__init__(self, *args, **kwds)
1967 def __setitem__(self, key, value):
1968 self.called = True
1969 Counter.__setitem__(self, key, value)
1970
1971class CounterSubclassWithGet(Counter):
1972 # Test a counter subclass that overrides get()
1973 def __init__(self, *args, **kwds):
1974 self.called = False
1975 Counter.__init__(self, *args, **kwds)
1976 def get(self, key, default):
1977 self.called = True
1978 return Counter.get(self, key, default)
1979
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001980class TestCounter(unittest.TestCase):
1981
1982 def test_basics(self):
1983 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001984 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1985 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001986 self.assertIsInstance(c, dict)
1987 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001988 self.assertTrue(issubclass(Counter, dict))
1989 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001990 self.assertEqual(len(c), 3)
1991 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001992 self.assertEqual(list(c.values()), [3, 2, 1])
1993 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1994 self.assertEqual(list(c), ['a', 'b', 'c'])
1995 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001996 [('a', 3), ('b', 2), ('c', 1)])
1997 self.assertEqual(c['b'], 2)
1998 self.assertEqual(c['z'], 0)
1999 self.assertEqual(c.__contains__('c'), True)
2000 self.assertEqual(c.__contains__('z'), False)
2001 self.assertEqual(c.get('b', 10), 2)
2002 self.assertEqual(c.get('z', 10), 10)
2003 self.assertEqual(c, dict(a=3, b=2, c=1))
2004 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
2005 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
2006 for i in range(5):
2007 self.assertEqual(c.most_common(i),
2008 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002009 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002010 c['a'] += 1 # increment an existing value
2011 c['b'] -= 2 # sub existing value to zero
2012 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002013 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002014 c['d'] -= 2 # sub from a missing value
2015 c['e'] = -5 # directly assign a missing value
2016 c['f'] += 4 # add to a missing value
2017 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002018 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002019 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002020 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002021 for i in range(3):
2022 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002023 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002024 c.clear()
2025 self.assertEqual(c, {})
2026 self.assertEqual(repr(c), 'Counter()')
2027 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
2028 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002029 c.update(dict(a=5, b=3))
2030 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002031 c.update(Counter('a' * 50 + 'b' * 30))
2032 c.update() # test case with no args
2033 c.__init__('a' * 500 + 'b' * 300)
2034 c.__init__('cdc')
2035 c.__init__()
2036 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
2037 self.assertEqual(c.setdefault('d', 5), 1)
2038 self.assertEqual(c['d'], 1)
2039 self.assertEqual(c.setdefault('e', 5), 5)
2040 self.assertEqual(c['e'], 5)
2041
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002042 def test_init(self):
2043 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
2044 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
2045 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
2046 self.assertRaises(TypeError, Counter, 42)
2047 self.assertRaises(TypeError, Counter, (), ())
2048 self.assertRaises(TypeError, Counter.__init__)
2049
Raymond Hettinger407c7342019-02-21 09:19:00 -08002050 def test_order_preservation(self):
2051 # Input order dictates items() order
2052 self.assertEqual(list(Counter('abracadabra').items()),
2053 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
2054 # letters with same count: ^----------^ ^---------^
2055
2056 # Verify retention of order even when all counts are equal
2057 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
2058 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
2059
2060 # Input order dictates elements() order
2061 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
2062 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
2063 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
2064
2065 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10002066 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08002067 ps = 'aaabbcdddeefggghhijjjkkl'
2068 qs = 'abbcccdeefffhkkllllmmnno'
2069 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
2070 def correctly_ordered(seq):
2071 'Return true if the letters occur in the expected order'
2072 positions = [order[letter] for letter in seq]
2073 return positions == sorted(positions)
2074
2075 p, q = Counter(ps), Counter(qs)
2076 self.assertTrue(correctly_ordered(+p))
2077 self.assertTrue(correctly_ordered(-p))
2078 self.assertTrue(correctly_ordered(p + q))
2079 self.assertTrue(correctly_ordered(p - q))
2080 self.assertTrue(correctly_ordered(p | q))
2081 self.assertTrue(correctly_ordered(p & q))
2082
2083 p, q = Counter(ps), Counter(qs)
2084 p += q
2085 self.assertTrue(correctly_ordered(p))
2086
2087 p, q = Counter(ps), Counter(qs)
2088 p -= q
2089 self.assertTrue(correctly_ordered(p))
2090
2091 p, q = Counter(ps), Counter(qs)
2092 p |= q
2093 self.assertTrue(correctly_ordered(p))
2094
2095 p, q = Counter(ps), Counter(qs)
2096 p &= q
2097 self.assertTrue(correctly_ordered(p))
2098
2099 p, q = Counter(ps), Counter(qs)
2100 p.update(q)
2101 self.assertTrue(correctly_ordered(p))
2102
2103 p, q = Counter(ps), Counter(qs)
2104 p.subtract(q)
2105 self.assertTrue(correctly_ordered(p))
2106
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002107 def test_update(self):
2108 c = Counter()
2109 c.update(self=42)
2110 self.assertEqual(list(c.items()), [('self', 42)])
2111 c = Counter()
2112 c.update(iterable=42)
2113 self.assertEqual(list(c.items()), [('iterable', 42)])
2114 c = Counter()
2115 c.update(iterable=None)
2116 self.assertEqual(list(c.items()), [('iterable', None)])
2117 self.assertRaises(TypeError, Counter().update, 42)
2118 self.assertRaises(TypeError, Counter().update, {}, {})
2119 self.assertRaises(TypeError, Counter.update)
2120
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002121 def test_copying(self):
2122 # Check that counters are copyable, deepcopyable, picklable, and
2123 #have a repr/eval round-trip
2124 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002125 def check(dup):
2126 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2127 self.assertIsNot(dup, words, msg)
2128 self.assertEqual(dup, words)
2129 check(words.copy())
2130 check(copy.copy(words))
2131 check(copy.deepcopy(words))
2132 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2133 with self.subTest(proto=proto):
2134 check(pickle.loads(pickle.dumps(words, proto)))
2135 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002136 update_test = Counter()
2137 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002138 check(update_test)
2139 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002140
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002141 def test_copy_subclass(self):
2142 class MyCounter(Counter):
2143 pass
2144 c = MyCounter('slartibartfast')
2145 d = c.copy()
2146 self.assertEqual(d, c)
2147 self.assertEqual(len(d), len(c))
2148 self.assertEqual(type(d), type(c))
2149
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002150 def test_conversions(self):
2151 # Convert to: set, list, dict
2152 s = 'she sells sea shells by the sea shore'
2153 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2154 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2155 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2156 self.assertEqual(set(Counter(s)), set(s))
2157
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002158 def test_invariant_for_the_in_operator(self):
2159 c = Counter(a=10, b=-2, c=0)
2160 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002161 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002162 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002163
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002164 def test_multiset_operations(self):
2165 # Verify that adding a zero counter will strip zeros and negatives
2166 c = Counter(a=10, b=-2, c=0) + Counter()
2167 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002168
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002169 elements = 'abcd'
2170 for i in range(1000):
2171 # test random pairs of multisets
2172 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002173 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002174 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002175 q.update(h=1, i=-1, j=0)
2176 for counterop, numberop in [
2177 (Counter.__add__, lambda x, y: max(0, x+y)),
2178 (Counter.__sub__, lambda x, y: max(0, x-y)),
2179 (Counter.__or__, lambda x, y: max(0,x,y)),
2180 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002181 ]:
2182 result = counterop(p, q)
2183 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002184 self.assertEqual(numberop(p[x], q[x]), result[x],
2185 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002186 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002187 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002188
2189 elements = 'abcdef'
2190 for i in range(100):
2191 # verify that random multisets with no repeats are exactly like sets
2192 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2193 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2194 for counterop, setop in [
2195 (Counter.__sub__, set.__sub__),
2196 (Counter.__or__, set.__or__),
2197 (Counter.__and__, set.__and__),
2198 ]:
2199 counter_result = counterop(p, q)
2200 set_result = setop(set(p.elements()), set(q.elements()))
2201 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002202
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002203 def test_inplace_operations(self):
2204 elements = 'abcd'
2205 for i in range(1000):
2206 # test random pairs of multisets
2207 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2208 p.update(e=1, f=-1, g=0)
2209 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2210 q.update(h=1, i=-1, j=0)
2211 for inplace_op, regular_op in [
2212 (Counter.__iadd__, Counter.__add__),
2213 (Counter.__isub__, Counter.__sub__),
2214 (Counter.__ior__, Counter.__or__),
2215 (Counter.__iand__, Counter.__and__),
2216 ]:
2217 c = p.copy()
2218 c_id = id(c)
2219 regular_result = regular_op(c, q)
2220 inplace_result = inplace_op(c, q)
2221 self.assertEqual(inplace_result, regular_result)
2222 self.assertEqual(id(inplace_result), c_id)
2223
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002224 def test_subtract(self):
2225 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2226 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2227 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2228 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2229 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2230 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2231 c = Counter('aaabbcd')
2232 c.subtract('aaaabbcce')
2233 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002234
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002235 c = Counter()
2236 c.subtract(self=42)
2237 self.assertEqual(list(c.items()), [('self', -42)])
2238 c = Counter()
2239 c.subtract(iterable=42)
2240 self.assertEqual(list(c.items()), [('iterable', -42)])
2241 self.assertRaises(TypeError, Counter().subtract, 42)
2242 self.assertRaises(TypeError, Counter().subtract, {}, {})
2243 self.assertRaises(TypeError, Counter.subtract)
2244
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002245 def test_unary(self):
2246 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2247 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2248 self.assertEqual(dict(-c), dict(a=5))
2249
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002250 def test_repr_nonsortable(self):
2251 c = Counter(a=2, b=None)
2252 r = repr(c)
2253 self.assertIn("'a': 2", r)
2254 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002255
Raymond Hettinger426e0522011-01-03 02:12:02 +00002256 def test_helper_function(self):
2257 # two paths, one for real dicts and one for other mappings
2258 elems = list('abracadabra')
2259
2260 d = dict()
2261 _count_elements(d, elems)
2262 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2263
2264 m = OrderedDict()
2265 _count_elements(m, elems)
2266 self.assertEqual(m,
2267 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2268
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002269 # test fidelity to the pure python version
2270 c = CounterSubclassWithSetItem('abracadabra')
2271 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002272 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002273 c = CounterSubclassWithGet('abracadabra')
2274 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002275 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002276
Raymond Hettinger60398512020-05-28 08:35:46 -07002277 def test_multiset_operations_equivalent_to_set_operations(self):
2278 # When the multiplicities are all zero or one, multiset operations
2279 # are guaranteed to be equivalent to the corresponding operations
2280 # for regular sets.
2281 s = list(product(('a', 'b', 'c'), range(2)))
2282 powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
2283 counters = [Counter(dict(groups)) for groups in powerset]
2284 for cp, cq in product(counters, repeat=2):
2285 sp = set(cp.elements())
2286 sq = set(cq.elements())
2287 self.assertEqual(set(cp + cq), sp | sq)
2288 self.assertEqual(set(cp - cq), sp - sq)
2289 self.assertEqual(set(cp | cq), sp | sq)
2290 self.assertEqual(set(cp & cq), sp & sq)
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002291 self.assertEqual(cp == cq, sp == sq)
2292 self.assertEqual(cp != cq, sp != sq)
2293 self.assertEqual(cp <= cq, sp <= sq)
2294 self.assertEqual(cp >= cq, sp >= sq)
2295 self.assertEqual(cp < cq, sp < sq)
2296 self.assertEqual(cp > cq, sp > sq)
Raymond Hettinger60398512020-05-28 08:35:46 -07002297
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002298 def test_eq(self):
2299 self.assertEqual(Counter(a=3, b=2, c=0), Counter('ababa'))
2300 self.assertNotEqual(Counter(a=3, b=2), Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002301
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002302 def test_le(self):
2303 self.assertTrue(Counter(a=3, b=2, c=0) <= Counter('ababa'))
2304 self.assertFalse(Counter(a=3, b=2) <= Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002305
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002306 def test_lt(self):
2307 self.assertTrue(Counter(a=3, b=1, c=0) < Counter('ababa'))
2308 self.assertFalse(Counter(a=3, b=2, c=0) < Counter('ababa'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002309
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002310 def test_ge(self):
2311 self.assertTrue(Counter(a=2, b=1, c=0) >= Counter('aab'))
2312 self.assertFalse(Counter(a=3, b=2, c=0) >= Counter('aabd'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002313
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002314 def test_gt(self):
2315 self.assertTrue(Counter(a=3, b=2, c=0) > Counter('aab'))
2316 self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002317
Raymond Hettinger499e1932011-02-23 07:56:53 +00002318
2319################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002320### Run tests
2321################################################################################
2322
Guido van Rossumd8faa362007-04-27 19:54:29 +00002323def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002324 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002325 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002326 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002327 TestUserObjects,
2328 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002329 support.run_unittest(*test_classes)
2330 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002331
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002332
Guido van Rossumd8faa362007-04-27 19:54:29 +00002333if __name__ == "__main__":
2334 test_main(verbose=True)