blob: a1ca958257adf6af64869a551fd658623b701be8 [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 Hettinger7a3602e2015-08-30 09:13:48 -0700684
Raymond Hettinger499e1932011-02-23 07:56:53 +0000685################################################################################
686### Abstract Base Classes
687################################################################################
688
Raymond Hettingerae650182009-01-28 23:33:59 +0000689class ABCTestCase(unittest.TestCase):
690
691 def validate_abstract_methods(self, abc, *names):
692 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
693
694 # everything should work will all required methods are present
695 C = type('C', (abc,), methodstubs)
696 C()
697
698 # instantiation should fail if a required method is missing
699 for name in names:
700 stubs = methodstubs.copy()
701 del stubs[name]
702 C = type('C', (abc,), stubs)
703 self.assertRaises(TypeError, C, name)
704
Florent Xiclunace153f62010-03-08 15:34:35 +0000705 def validate_isinstance(self, abc, name):
706 stub = lambda s, *args: 0
707
708 C = type('C', (object,), {'__hash__': None})
709 setattr(C, name, stub)
710 self.assertIsInstance(C(), abc)
711 self.assertTrue(issubclass(C, abc))
712
713 C = type('C', (object,), {'__hash__': None})
714 self.assertNotIsInstance(C(), abc)
715 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000716
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000717 def validate_comparison(self, instance):
718 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
719 operators = {}
720 for op in ops:
721 name = '__' + op + '__'
722 operators[name] = getattr(operator, name)
723
724 class Other:
725 def __init__(self):
726 self.right_side = False
727 def __eq__(self, other):
728 self.right_side = True
729 return True
730 __lt__ = __eq__
731 __gt__ = __eq__
732 __le__ = __eq__
733 __ge__ = __eq__
734 __ne__ = __eq__
735 __ror__ = __eq__
736 __rand__ = __eq__
737 __rxor__ = __eq__
738 __rsub__ = __eq__
739
740 for name, op in operators.items():
741 if not hasattr(instance, name):
742 continue
743 other = Other()
744 op(instance, other)
745 self.assertTrue(other.right_side,'Right side not called for %s.%s'
746 % (type(instance), name))
747
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700748def _test_gen():
749 yield
750
Raymond Hettingerae650182009-01-28 23:33:59 +0000751class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000752
Yury Selivanov75445082015-05-11 22:57:16 -0400753 def test_Awaitable(self):
754 def gen():
755 yield
756
757 @types.coroutine
758 def coro():
759 yield
760
761 async def new_coro():
762 pass
763
764 class Bar:
765 def __await__(self):
766 yield
767
768 class MinimalCoro(Coroutine):
769 def send(self, value):
770 return value
771 def throw(self, typ, val=None, tb=None):
772 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400773 def __await__(self):
774 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400775
776 non_samples = [None, int(), gen(), object()]
777 for x in non_samples:
778 self.assertNotIsInstance(x, Awaitable)
779 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
780
781 samples = [Bar(), MinimalCoro()]
782 for x in samples:
783 self.assertIsInstance(x, Awaitable)
784 self.assertTrue(issubclass(type(x), Awaitable))
785
786 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400787 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
788 # flag don't have '__await__' method, hence can't be instances
789 # of Awaitable. Use inspect.isawaitable to detect them.
790 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400791
792 c = new_coro()
793 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300794 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400795
Yury Selivanov56fc6142015-05-29 09:01:29 -0400796 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400797 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400798 self.assertTrue(isinstance(CoroLike(), Awaitable))
799 self.assertTrue(issubclass(CoroLike, Awaitable))
800 CoroLike = None
801 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400802
Yury Selivanov75445082015-05-11 22:57:16 -0400803 def test_Coroutine(self):
804 def gen():
805 yield
806
807 @types.coroutine
808 def coro():
809 yield
810
811 async def new_coro():
812 pass
813
814 class Bar:
815 def __await__(self):
816 yield
817
818 class MinimalCoro(Coroutine):
819 def send(self, value):
820 return value
821 def throw(self, typ, val=None, tb=None):
822 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400823 def __await__(self):
824 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400825
826 non_samples = [None, int(), gen(), object(), Bar()]
827 for x in non_samples:
828 self.assertNotIsInstance(x, Coroutine)
829 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
830
831 samples = [MinimalCoro()]
832 for x in samples:
833 self.assertIsInstance(x, Awaitable)
834 self.assertTrue(issubclass(type(x), Awaitable))
835
836 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400837 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
838 # flag don't have '__await__' method, hence can't be instances
839 # of Coroutine. Use inspect.isawaitable to detect them.
840 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400841
842 c = new_coro()
843 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300844 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400845
Yury Selivanov56fc6142015-05-29 09:01:29 -0400846 class CoroLike:
847 def send(self, value):
848 pass
849 def throw(self, typ, val=None, tb=None):
850 pass
851 def close(self):
852 pass
853 def __await__(self):
854 pass
855 self.assertTrue(isinstance(CoroLike(), Coroutine))
856 self.assertTrue(issubclass(CoroLike, Coroutine))
857
858 class CoroLike:
859 def send(self, value):
860 pass
861 def close(self):
862 pass
863 def __await__(self):
864 pass
865 self.assertFalse(isinstance(CoroLike(), Coroutine))
866 self.assertFalse(issubclass(CoroLike, Coroutine))
867
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000868 def test_Hashable(self):
869 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000870 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000871 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000872 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000873 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000874 # Check some hashables
875 samples = [None,
876 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000877 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000878 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000879 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000880 ]
881 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000882 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000883 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000884 self.assertRaises(TypeError, Hashable)
885 # Check direct subclassing
886 class H(Hashable):
887 def __hash__(self):
888 return super().__hash__()
889 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000890 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000891 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000892 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000893
Yury Selivanove0104ae2015-05-14 12:19:16 -0400894 def test_AsyncIterable(self):
895 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400896 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400897 return self
898 self.assertTrue(isinstance(AI(), AsyncIterable))
899 self.assertTrue(issubclass(AI, AsyncIterable))
900 # Check some non-iterables
901 non_samples = [None, object, []]
902 for x in non_samples:
903 self.assertNotIsInstance(x, AsyncIterable)
904 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
905 self.validate_abstract_methods(AsyncIterable, '__aiter__')
906 self.validate_isinstance(AsyncIterable, '__aiter__')
907
908 def test_AsyncIterator(self):
909 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400910 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400911 return self
912 async def __anext__(self):
913 raise StopAsyncIteration
914 self.assertTrue(isinstance(AI(), AsyncIterator))
915 self.assertTrue(issubclass(AI, AsyncIterator))
916 non_samples = [None, object, []]
917 # Check some non-iterables
918 for x in non_samples:
919 self.assertNotIsInstance(x, AsyncIterator)
920 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
921 # Similarly to regular iterators (see issue 10565)
922 class AnextOnly:
923 async def __anext__(self):
924 raise StopAsyncIteration
925 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
926 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
927
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000928 def test_Iterable(self):
929 # Check some non-iterables
930 non_samples = [None, 42, 3.14, 1j]
931 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000932 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000933 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000934 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000935 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000936 tuple(), list(), set(), frozenset(), dict(),
937 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700938 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000939 (x for x in []),
940 ]
941 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000942 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000943 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000944 # Check direct subclassing
945 class I(Iterable):
946 def __iter__(self):
947 return super().__iter__()
948 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000949 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000950 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000951 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700952 # Check None blocking
953 class It:
954 def __iter__(self): return iter([])
955 class ItBlocked(It):
956 __iter__ = None
957 self.assertTrue(issubclass(It, Iterable))
958 self.assertTrue(isinstance(It(), Iterable))
959 self.assertFalse(issubclass(ItBlocked, Iterable))
960 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000961
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700962 def test_Reversible(self):
963 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100964 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700965 for x in non_samples:
966 self.assertNotIsInstance(x, Reversible)
967 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700968 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100969 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700970 for x in non_reversibles:
971 self.assertNotIsInstance(x, Reversible)
972 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
973 # Check some reversible iterables
974 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
975 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100976 OrderedDict().values(), Counter(), Counter().keys(),
977 Counter().items(), Counter().values(), dict(),
978 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700979 for x in samples:
980 self.assertIsInstance(x, Reversible)
981 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
982 # Check also Mapping, MutableMapping, and Sequence
983 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
984 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
985 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
986 # Check direct subclassing
987 class R(Reversible):
988 def __iter__(self):
989 return iter(list())
990 def __reversed__(self):
991 return iter(list())
992 self.assertEqual(list(reversed(R())), [])
993 self.assertFalse(issubclass(float, R))
994 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700995 # Check reversible non-iterable (which is not Reversible)
996 class RevNoIter:
997 def __reversed__(self): return reversed([])
998 class RevPlusIter(RevNoIter):
999 def __iter__(self): return iter([])
1000 self.assertFalse(issubclass(RevNoIter, Reversible))
1001 self.assertFalse(isinstance(RevNoIter(), Reversible))
1002 self.assertTrue(issubclass(RevPlusIter, Reversible))
1003 self.assertTrue(isinstance(RevPlusIter(), Reversible))
1004 # Check None blocking
1005 class Rev:
1006 def __iter__(self): return iter([])
1007 def __reversed__(self): return reversed([])
1008 class RevItBlocked(Rev):
1009 __iter__ = None
1010 class RevRevBlocked(Rev):
1011 __reversed__ = None
1012 self.assertTrue(issubclass(Rev, Reversible))
1013 self.assertTrue(isinstance(Rev(), Reversible))
1014 self.assertFalse(issubclass(RevItBlocked, Reversible))
1015 self.assertFalse(isinstance(RevItBlocked(), Reversible))
1016 self.assertFalse(issubclass(RevRevBlocked, Reversible))
1017 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001018
Guido van Rossumf0666942016-08-23 10:47:07 -07001019 def test_Collection(self):
1020 # Check some non-collections
1021 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
1022 for x in non_collections:
1023 self.assertNotIsInstance(x, Collection)
1024 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1025 # Check some non-collection iterables
1026 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001027 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -07001028 for x in non_col_iterables:
1029 self.assertNotIsInstance(x, Collection)
1030 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1031 # Check some collections
1032 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001033 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001034 for x in samples:
1035 self.assertIsInstance(x, Collection)
1036 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1037 # Check also Mapping, MutableMapping, etc.
1038 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1039 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1040 self.assertTrue(issubclass(MutableMapping, Collection),
1041 repr(MutableMapping))
1042 self.assertTrue(issubclass(Set, Collection), repr(Set))
1043 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1044 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1045 # Check direct subclassing
1046 class Col(Collection):
1047 def __iter__(self):
1048 return iter(list())
1049 def __len__(self):
1050 return 0
1051 def __contains__(self, item):
1052 return False
1053 class DerCol(Col): pass
1054 self.assertEqual(list(iter(Col())), [])
1055 self.assertFalse(issubclass(list, Col))
1056 self.assertFalse(issubclass(set, Col))
1057 self.assertFalse(issubclass(float, Col))
1058 self.assertEqual(list(iter(DerCol())), [])
1059 self.assertFalse(issubclass(list, DerCol))
1060 self.assertFalse(issubclass(set, DerCol))
1061 self.assertFalse(issubclass(float, DerCol))
1062 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1063 '__contains__')
1064 # Check sized container non-iterable (which is not Collection) etc.
1065 class ColNoIter:
1066 def __len__(self): return 0
1067 def __contains__(self, item): return False
1068 class ColNoSize:
1069 def __iter__(self): return iter([])
1070 def __contains__(self, item): return False
1071 class ColNoCont:
1072 def __iter__(self): return iter([])
1073 def __len__(self): return 0
1074 self.assertFalse(issubclass(ColNoIter, Collection))
1075 self.assertFalse(isinstance(ColNoIter(), Collection))
1076 self.assertFalse(issubclass(ColNoSize, Collection))
1077 self.assertFalse(isinstance(ColNoSize(), Collection))
1078 self.assertFalse(issubclass(ColNoCont, Collection))
1079 self.assertFalse(isinstance(ColNoCont(), Collection))
1080 # Check None blocking
1081 class SizeBlock:
1082 def __iter__(self): return iter([])
1083 def __contains__(self): return False
1084 __len__ = None
1085 class IterBlock:
1086 def __len__(self): return 0
1087 def __contains__(self): return True
1088 __iter__ = None
1089 self.assertFalse(issubclass(SizeBlock, Collection))
1090 self.assertFalse(isinstance(SizeBlock(), Collection))
1091 self.assertFalse(issubclass(IterBlock, Collection))
1092 self.assertFalse(isinstance(IterBlock(), Collection))
1093 # Check None blocking in subclass
1094 class ColImpl:
1095 def __iter__(self):
1096 return iter(list())
1097 def __len__(self):
1098 return 0
1099 def __contains__(self, item):
1100 return False
1101 class NonCol(ColImpl):
1102 __contains__ = None
1103 self.assertFalse(issubclass(NonCol, Collection))
1104 self.assertFalse(isinstance(NonCol(), Collection))
1105
1106
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001107 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001108 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001109 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001110 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001111 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001112 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001113 iter(tuple()), iter(list()), iter(dict()),
1114 iter(set()), iter(frozenset()),
1115 iter(dict().keys()), iter(dict().items()),
1116 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001117 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001118 (x for x in []),
1119 ]
1120 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001121 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001122 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001123 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1124
1125 # Issue 10565
1126 class NextOnly:
1127 def __next__(self):
1128 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001129 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001130 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001131
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001132 def test_Generator(self):
1133 class NonGen1:
1134 def __iter__(self): return self
1135 def __next__(self): return None
1136 def close(self): pass
1137 def throw(self, typ, val=None, tb=None): pass
1138
1139 class NonGen2:
1140 def __iter__(self): return self
1141 def __next__(self): return None
1142 def close(self): pass
1143 def send(self, value): return value
1144
1145 class NonGen3:
1146 def close(self): pass
1147 def send(self, value): return value
1148 def throw(self, typ, val=None, tb=None): pass
1149
1150 non_samples = [
1151 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1152 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1153 for x in non_samples:
1154 self.assertNotIsInstance(x, Generator)
1155 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1156
1157 class Gen:
1158 def __iter__(self): return self
1159 def __next__(self): return None
1160 def close(self): pass
1161 def send(self, value): return value
1162 def throw(self, typ, val=None, tb=None): pass
1163
1164 class MinimalGen(Generator):
1165 def send(self, value):
1166 return value
1167 def throw(self, typ, val=None, tb=None):
1168 super().throw(typ, val, tb)
1169
1170 def gen():
1171 yield 1
1172
1173 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1174 for x in samples:
1175 self.assertIsInstance(x, Iterator)
1176 self.assertIsInstance(x, Generator)
1177 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1178 self.validate_abstract_methods(Generator, 'send', 'throw')
1179
1180 # mixin tests
1181 mgen = MinimalGen()
1182 self.assertIs(mgen, iter(mgen))
1183 self.assertIs(mgen.send(None), next(mgen))
1184 self.assertEqual(2, mgen.send(2))
1185 self.assertIsNone(mgen.close())
1186 self.assertRaises(ValueError, mgen.throw, ValueError)
1187 self.assertRaisesRegex(ValueError, "^huhu$",
1188 mgen.throw, ValueError, ValueError("huhu"))
1189 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1190
1191 class FailOnClose(Generator):
1192 def send(self, value): return value
1193 def throw(self, *args): raise ValueError
1194
1195 self.assertRaises(ValueError, FailOnClose().close)
1196
1197 class IgnoreGeneratorExit(Generator):
1198 def send(self, value): return value
1199 def throw(self, *args): pass
1200
1201 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1202
Yury Selivanov22214ab2016-11-16 18:25:04 -05001203 def test_AsyncGenerator(self):
1204 class NonAGen1:
1205 def __aiter__(self): return self
1206 def __anext__(self): return None
1207 def aclose(self): pass
1208 def athrow(self, typ, val=None, tb=None): pass
1209
1210 class NonAGen2:
1211 def __aiter__(self): return self
1212 def __anext__(self): return None
1213 def aclose(self): pass
1214 def asend(self, value): return value
1215
1216 class NonAGen3:
1217 def aclose(self): pass
1218 def asend(self, value): return value
1219 def athrow(self, typ, val=None, tb=None): pass
1220
1221 non_samples = [
1222 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1223 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1224 for x in non_samples:
1225 self.assertNotIsInstance(x, AsyncGenerator)
1226 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1227
1228 class Gen:
1229 def __aiter__(self): return self
1230 async def __anext__(self): return None
1231 async def aclose(self): pass
1232 async def asend(self, value): return value
1233 async def athrow(self, typ, val=None, tb=None): pass
1234
1235 class MinimalAGen(AsyncGenerator):
1236 async def asend(self, value):
1237 return value
1238 async def athrow(self, typ, val=None, tb=None):
1239 await super().athrow(typ, val, tb)
1240
1241 async def gen():
1242 yield 1
1243
1244 samples = [gen(), Gen(), MinimalAGen()]
1245 for x in samples:
1246 self.assertIsInstance(x, AsyncIterator)
1247 self.assertIsInstance(x, AsyncGenerator)
1248 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1249 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1250
1251 def run_async(coro):
1252 result = None
1253 while True:
1254 try:
1255 coro.send(None)
1256 except StopIteration as ex:
1257 result = ex.args[0] if ex.args else None
1258 break
1259 return result
1260
1261 # mixin tests
1262 mgen = MinimalAGen()
1263 self.assertIs(mgen, mgen.__aiter__())
1264 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1265 self.assertEqual(2, run_async(mgen.asend(2)))
1266 self.assertIsNone(run_async(mgen.aclose()))
1267 with self.assertRaises(ValueError):
1268 run_async(mgen.athrow(ValueError))
1269
1270 class FailOnClose(AsyncGenerator):
1271 async def asend(self, value): return value
1272 async def athrow(self, *args): raise ValueError
1273
1274 with self.assertRaises(ValueError):
1275 run_async(FailOnClose().aclose())
1276
1277 class IgnoreGeneratorExit(AsyncGenerator):
1278 async def asend(self, value): return value
1279 async def athrow(self, *args): pass
1280
1281 with self.assertRaises(RuntimeError):
1282 run_async(IgnoreGeneratorExit().aclose())
1283
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001284 def test_Sized(self):
1285 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001286 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001287 (x for x in []),
1288 ]
1289 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001290 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001291 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001292 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001293 tuple(), list(), set(), frozenset(), dict(),
1294 dict().keys(), dict().items(), dict().values(),
1295 ]
1296 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001297 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001298 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001299 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001300 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001301
1302 def test_Container(self):
1303 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001304 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001305 (x for x in []),
1306 ]
1307 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001308 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001309 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001310 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001311 tuple(), list(), set(), frozenset(), dict(),
1312 dict().keys(), dict().items(),
1313 ]
1314 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001315 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001316 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001317 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001318 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001319
1320 def test_Callable(self):
1321 non_samples = [None, 42, 3.14, 1j,
1322 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001323 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001324 (x for x in []),
1325 ]
1326 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001327 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001328 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001329 samples = [lambda: None,
1330 type, int, object,
1331 len,
1332 list.append, [].append,
1333 ]
1334 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001335 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001336 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001337 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001338 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001339
1340 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001341 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001342 class C(B):
1343 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001344 self.assertTrue(issubclass(C, B))
1345 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001346
1347 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001348 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001349 class C:
1350 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001351 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001352 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001353 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001354
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001355class WithSet(MutableSet):
1356
1357 def __init__(self, it=()):
1358 self.data = set(it)
1359
1360 def __len__(self):
1361 return len(self.data)
1362
1363 def __iter__(self):
1364 return iter(self.data)
1365
1366 def __contains__(self, item):
1367 return item in self.data
1368
1369 def add(self, item):
1370 self.data.add(item)
1371
1372 def discard(self, item):
1373 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001374
Raymond Hettingerae650182009-01-28 23:33:59 +00001375class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001376
1377 # XXX For now, we only test some virtual inheritance properties.
1378 # We should also test the proper behavior of the collection ABCs
1379 # as real base classes or mix-in classes.
1380
1381 def test_Set(self):
1382 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001383 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001384 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001385 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001386 class MySet(Set):
1387 def __contains__(self, x):
1388 return False
1389 def __len__(self):
1390 return 0
1391 def __iter__(self):
1392 return iter([])
1393 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001394
Benjamin Peterson41181742008-07-02 20:22:54 +00001395 def test_hash_Set(self):
1396 class OneTwoThreeSet(Set):
1397 def __init__(self):
1398 self.contents = [1, 2, 3]
1399 def __contains__(self, x):
1400 return x in self.contents
1401 def __len__(self):
1402 return len(self.contents)
1403 def __iter__(self):
1404 return iter(self.contents)
1405 def __hash__(self):
1406 return self._hash()
1407 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001408 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001409
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001410 def test_isdisjoint_Set(self):
1411 class MySet(Set):
1412 def __init__(self, itr):
1413 self.contents = itr
1414 def __contains__(self, x):
1415 return x in self.contents
1416 def __iter__(self):
1417 return iter(self.contents)
1418 def __len__(self):
1419 return len([x for x in self.contents])
1420 s1 = MySet((1, 2, 3))
1421 s2 = MySet((4, 5, 6))
1422 s3 = MySet((1, 5, 6))
1423 self.assertTrue(s1.isdisjoint(s2))
1424 self.assertFalse(s1.isdisjoint(s3))
1425
1426 def test_equality_Set(self):
1427 class MySet(Set):
1428 def __init__(self, itr):
1429 self.contents = itr
1430 def __contains__(self, x):
1431 return x in self.contents
1432 def __iter__(self):
1433 return iter(self.contents)
1434 def __len__(self):
1435 return len([x for x in self.contents])
1436 s1 = MySet((1,))
1437 s2 = MySet((1, 2))
1438 s3 = MySet((3, 4))
1439 s4 = MySet((3, 4))
1440 self.assertTrue(s2 > s1)
1441 self.assertTrue(s1 < s2)
1442 self.assertFalse(s2 <= s1)
1443 self.assertFalse(s2 <= s3)
1444 self.assertFalse(s1 >= s2)
1445 self.assertEqual(s3, s4)
1446 self.assertNotEqual(s2, s3)
1447
1448 def test_arithmetic_Set(self):
1449 class MySet(Set):
1450 def __init__(self, itr):
1451 self.contents = itr
1452 def __contains__(self, x):
1453 return x in self.contents
1454 def __iter__(self):
1455 return iter(self.contents)
1456 def __len__(self):
1457 return len([x for x in self.contents])
1458 s1 = MySet((1, 2, 3))
1459 s2 = MySet((3, 4, 5))
1460 s3 = s1 & s2
1461 self.assertEqual(s3, MySet((3,)))
1462
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001463 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001464 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001465 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001466 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001467 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001468 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1469 'add', 'discard')
1470
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001471 def test_issue_5647(self):
1472 # MutableSet.__iand__ mutated the set during iteration
1473 s = WithSet('abcd')
1474 s &= WithSet('cdef') # This used to fail
1475 self.assertEqual(set(s), set('cd'))
1476
Raymond Hettingerae650182009-01-28 23:33:59 +00001477 def test_issue_4920(self):
1478 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001479 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001480 __slots__=['__s']
1481 def __init__(self,items=None):
1482 if items is None:
1483 items=[]
1484 self.__s=set(items)
1485 def __contains__(self,v):
1486 return v in self.__s
1487 def __iter__(self):
1488 return iter(self.__s)
1489 def __len__(self):
1490 return len(self.__s)
1491 def add(self,v):
1492 result=v not in self.__s
1493 self.__s.add(v)
1494 return result
1495 def discard(self,v):
1496 result=v in self.__s
1497 self.__s.discard(v)
1498 return result
1499 def __repr__(self):
1500 return "MySet(%s)" % repr(list(self))
1501 s = MySet([5,43,2,1])
1502 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001503
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001504 def test_issue8750(self):
1505 empty = WithSet()
1506 full = WithSet(range(10))
1507 s = WithSet(full)
1508 s -= s
1509 self.assertEqual(s, empty)
1510 s = WithSet(full)
1511 s ^= s
1512 self.assertEqual(s, empty)
1513 s = WithSet(full)
1514 s &= s
1515 self.assertEqual(s, full)
1516 s |= s
1517 self.assertEqual(s, full)
1518
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001519 def test_issue16373(self):
1520 # Recursion error comparing comparable and noncomparable
1521 # Set instances
1522 class MyComparableSet(Set):
1523 def __contains__(self, x):
1524 return False
1525 def __len__(self):
1526 return 0
1527 def __iter__(self):
1528 return iter([])
1529 class MyNonComparableSet(Set):
1530 def __contains__(self, x):
1531 return False
1532 def __len__(self):
1533 return 0
1534 def __iter__(self):
1535 return iter([])
1536 def __le__(self, x):
1537 return NotImplemented
1538 def __lt__(self, x):
1539 return NotImplemented
1540
1541 cs = MyComparableSet()
1542 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001543 self.assertFalse(ncs < cs)
1544 self.assertTrue(ncs <= cs)
1545 self.assertFalse(ncs > cs)
1546 self.assertTrue(ncs >= cs)
1547
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001548 def test_issue26915(self):
1549 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001550 class CustomSequence(Sequence):
1551 def __init__(self, seq):
1552 self._seq = seq
1553 def __getitem__(self, index):
1554 return self._seq[index]
1555 def __len__(self):
1556 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001557
1558 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001559 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001560 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001561 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001562 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001563 ItemsView({1: nan, 2: obj}),
1564 ValuesView({1: nan, 2: obj})
1565 ]
1566 for container in containers:
1567 for elem in container:
1568 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001569 self.assertEqual(seq.index(nan), 0)
1570 self.assertEqual(seq.index(obj), 1)
1571 self.assertEqual(seq.count(nan), 2)
1572 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001573
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001574 def assertSameSet(self, s1, s2):
1575 # coerce both to a real set then check equality
1576 self.assertSetEqual(set(s1), set(s2))
1577
Richard Levasseur68f68fa2020-11-21 11:56:24 -08001578 def test_Set_from_iterable(self):
1579 """Verify _from_iterable overriden to an instance method works."""
1580 class SetUsingInstanceFromIterable(MutableSet):
1581 def __init__(self, values, created_by):
1582 if not created_by:
1583 raise ValueError(f'created_by must be specified')
1584 self.created_by = created_by
1585 self._values = set(values)
1586
1587 def _from_iterable(self, values):
1588 return type(self)(values, 'from_iterable')
1589
1590 def __contains__(self, value):
1591 return value in self._values
1592
1593 def __iter__(self):
1594 yield from self._values
1595
1596 def __len__(self):
1597 return len(self._values)
1598
1599 def add(self, value):
1600 self._values.add(value)
1601
1602 def discard(self, value):
1603 self._values.discard(value)
1604
1605 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
1606
1607 actual = impl - {1}
1608 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1609 self.assertEqual('from_iterable', actual.created_by)
1610 self.assertEqual({2, 3}, actual)
1611
1612 actual = impl | {4}
1613 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1614 self.assertEqual('from_iterable', actual.created_by)
1615 self.assertEqual({1, 2, 3, 4}, actual)
1616
1617 actual = impl & {2}
1618 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1619 self.assertEqual('from_iterable', actual.created_by)
1620 self.assertEqual({2}, actual)
1621
1622 actual = impl ^ {3, 4}
1623 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1624 self.assertEqual('from_iterable', actual.created_by)
1625 self.assertEqual({1, 2, 4}, actual)
1626
1627 # NOTE: ixor'ing with a list is important here: internally, __ixor__
1628 # only calls _from_iterable if the other value isn't already a Set.
1629 impl ^= [3, 4]
1630 self.assertIsInstance(impl, SetUsingInstanceFromIterable)
1631 self.assertEqual('test', impl.created_by)
1632 self.assertEqual({1, 2, 4}, impl)
1633
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001634 def test_Set_interoperability_with_real_sets(self):
1635 # Issue: 8743
1636 class ListSet(Set):
1637 def __init__(self, elements=()):
1638 self.data = []
1639 for elem in elements:
1640 if elem not in self.data:
1641 self.data.append(elem)
1642 def __contains__(self, elem):
1643 return elem in self.data
1644 def __iter__(self):
1645 return iter(self.data)
1646 def __len__(self):
1647 return len(self.data)
1648 def __repr__(self):
1649 return 'Set({!r})'.format(self.data)
1650
1651 r1 = set('abc')
1652 r2 = set('bcd')
1653 r3 = set('abcde')
1654 f1 = ListSet('abc')
1655 f2 = ListSet('bcd')
1656 f3 = ListSet('abcde')
1657 l1 = list('abccba')
1658 l2 = list('bcddcb')
1659 l3 = list('abcdeedcba')
1660
1661 target = r1 & r2
1662 self.assertSameSet(f1 & f2, target)
1663 self.assertSameSet(f1 & r2, target)
1664 self.assertSameSet(r2 & f1, target)
1665 self.assertSameSet(f1 & l2, target)
1666
1667 target = r1 | r2
1668 self.assertSameSet(f1 | f2, target)
1669 self.assertSameSet(f1 | r2, target)
1670 self.assertSameSet(r2 | f1, target)
1671 self.assertSameSet(f1 | l2, target)
1672
1673 fwd_target = r1 - r2
1674 rev_target = r2 - r1
1675 self.assertSameSet(f1 - f2, fwd_target)
1676 self.assertSameSet(f2 - f1, rev_target)
1677 self.assertSameSet(f1 - r2, fwd_target)
1678 self.assertSameSet(f2 - r1, rev_target)
1679 self.assertSameSet(r1 - f2, fwd_target)
1680 self.assertSameSet(r2 - f1, rev_target)
1681 self.assertSameSet(f1 - l2, fwd_target)
1682 self.assertSameSet(f2 - l1, rev_target)
1683
1684 target = r1 ^ r2
1685 self.assertSameSet(f1 ^ f2, target)
1686 self.assertSameSet(f1 ^ r2, target)
1687 self.assertSameSet(r2 ^ f1, target)
1688 self.assertSameSet(f1 ^ l2, target)
1689
1690 # Don't change the following to use assertLess or other
1691 # "more specific" unittest assertions. The current
1692 # assertTrue/assertFalse style makes the pattern of test
1693 # case combinations clear and allows us to know for sure
1694 # the exact operator being invoked.
1695
1696 # proper subset
1697 self.assertTrue(f1 < f3)
1698 self.assertFalse(f1 < f1)
1699 self.assertFalse(f1 < f2)
1700 self.assertTrue(r1 < f3)
1701 self.assertFalse(r1 < f1)
1702 self.assertFalse(r1 < f2)
1703 self.assertTrue(r1 < r3)
1704 self.assertFalse(r1 < r1)
1705 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001706 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001707 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001708 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001709 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001710 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001711 f1 < l2
1712
1713 # any subset
1714 self.assertTrue(f1 <= f3)
1715 self.assertTrue(f1 <= f1)
1716 self.assertFalse(f1 <= f2)
1717 self.assertTrue(r1 <= f3)
1718 self.assertTrue(r1 <= f1)
1719 self.assertFalse(r1 <= f2)
1720 self.assertTrue(r1 <= r3)
1721 self.assertTrue(r1 <= r1)
1722 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001723 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001724 f1 <= l3
1725 with self.assertRaises(TypeError):
1726 f1 <= l1
1727 with self.assertRaises(TypeError):
1728 f1 <= l2
1729
1730 # proper superset
1731 self.assertTrue(f3 > f1)
1732 self.assertFalse(f1 > f1)
1733 self.assertFalse(f2 > f1)
1734 self.assertTrue(r3 > r1)
1735 self.assertFalse(f1 > r1)
1736 self.assertFalse(f2 > r1)
1737 self.assertTrue(r3 > r1)
1738 self.assertFalse(r1 > r1)
1739 self.assertFalse(r2 > r1)
1740 with self.assertRaises(TypeError):
1741 f1 > l3
1742 with self.assertRaises(TypeError):
1743 f1 > l1
1744 with self.assertRaises(TypeError):
1745 f1 > l2
1746
1747 # any superset
1748 self.assertTrue(f3 >= f1)
1749 self.assertTrue(f1 >= f1)
1750 self.assertFalse(f2 >= f1)
1751 self.assertTrue(r3 >= r1)
1752 self.assertTrue(f1 >= r1)
1753 self.assertFalse(f2 >= r1)
1754 self.assertTrue(r3 >= r1)
1755 self.assertTrue(r1 >= r1)
1756 self.assertFalse(r2 >= r1)
1757 with self.assertRaises(TypeError):
1758 f1 >= l3
1759 with self.assertRaises(TypeError):
1760 f1 >=l1
1761 with self.assertRaises(TypeError):
1762 f1 >= l2
1763
1764 # equality
1765 self.assertTrue(f1 == f1)
1766 self.assertTrue(r1 == f1)
1767 self.assertTrue(f1 == r1)
1768 self.assertFalse(f1 == f3)
1769 self.assertFalse(r1 == f3)
1770 self.assertFalse(f1 == r3)
1771 self.assertFalse(f1 == l3)
1772 self.assertFalse(f1 == l1)
1773 self.assertFalse(f1 == l2)
1774
1775 # inequality
1776 self.assertFalse(f1 != f1)
1777 self.assertFalse(r1 != f1)
1778 self.assertFalse(f1 != r1)
1779 self.assertTrue(f1 != f3)
1780 self.assertTrue(r1 != f3)
1781 self.assertTrue(f1 != r3)
1782 self.assertTrue(f1 != l3)
1783 self.assertTrue(f1 != l1)
1784 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001785
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001786 def test_Mapping(self):
1787 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001788 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001789 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001790 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1791 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001792 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001793 def __len__(self):
1794 return 0
1795 def __getitem__(self, i):
1796 raise IndexError
1797 def __iter__(self):
1798 return iter(())
1799 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001800 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001801
1802 def test_MutableMapping(self):
1803 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001804 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001805 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001806 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1807 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001808
Raymond Hettinger9117c752010-08-22 07:44:24 +00001809 def test_MutableMapping_subclass(self):
1810 # Test issue 9214
1811 mymap = UserDict()
1812 mymap['red'] = 5
1813 self.assertIsInstance(mymap.keys(), Set)
1814 self.assertIsInstance(mymap.keys(), KeysView)
1815 self.assertIsInstance(mymap.items(), Set)
1816 self.assertIsInstance(mymap.items(), ItemsView)
1817
1818 mymap = UserDict()
1819 mymap['red'] = 5
1820 z = mymap.keys() | {'orange'}
1821 self.assertIsInstance(z, set)
1822 list(z)
1823 mymap['blue'] = 7 # Shouldn't affect 'z'
1824 self.assertEqual(sorted(z), ['orange', 'red'])
1825
1826 mymap = UserDict()
1827 mymap['red'] = 5
1828 z = mymap.items() | {('orange', 3)}
1829 self.assertIsInstance(z, set)
1830 list(z)
1831 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001832 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001833
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001834 def test_Sequence(self):
1835 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001836 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001837 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001838 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001839 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001840 self.assertIsInstance(memoryview(b""), Sequence)
1841 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001842 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001843 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1844 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001845
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001846 def test_Sequence_mixins(self):
1847 class SequenceSubclass(Sequence):
1848 def __init__(self, seq=()):
1849 self.seq = seq
1850
1851 def __getitem__(self, index):
1852 return self.seq[index]
1853
1854 def __len__(self):
1855 return len(self.seq)
1856
1857 # Compare Sequence.index() behavior to (list|str).index() behavior
1858 def assert_index_same(seq1, seq2, index_args):
1859 try:
1860 expected = seq1.index(*index_args)
1861 except ValueError:
1862 with self.assertRaises(ValueError):
1863 seq2.index(*index_args)
1864 else:
1865 actual = seq2.index(*index_args)
1866 self.assertEqual(
1867 actual, expected, '%r.index%s' % (seq1, index_args))
1868
1869 for ty in list, str:
1870 nativeseq = ty('abracadabra')
1871 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1872 seqseq = SequenceSubclass(nativeseq)
1873 for letter in set(nativeseq) | {'z'}:
1874 assert_index_same(nativeseq, seqseq, (letter,))
1875 for start in range(-3, len(nativeseq) + 3):
1876 assert_index_same(nativeseq, seqseq, (letter, start))
1877 for stop in range(-3, len(nativeseq) + 3):
1878 assert_index_same(
1879 nativeseq, seqseq, (letter, start, stop))
1880
Guido van Rossumd05eb002007-11-21 22:26:24 +00001881 def test_ByteString(self):
1882 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001883 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001884 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001885 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001886 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001887 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001888 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001889 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001890
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001891 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001892 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001893 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001894 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001895 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001896 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001897 self.assertTrue(issubclass(sample, MutableSequence))
1898 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001899 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1900 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001901
Eli Bendersky0716a572011-03-04 10:38:14 +00001902 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001903 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001904 # class inherited from it.
1905 class MutableSequenceSubclass(MutableSequence):
1906 def __init__(self):
1907 self.lst = []
1908
1909 def __setitem__(self, index, value):
1910 self.lst[index] = value
1911
1912 def __getitem__(self, index):
1913 return self.lst[index]
1914
1915 def __len__(self):
1916 return len(self.lst)
1917
1918 def __delitem__(self, index):
1919 del self.lst[index]
1920
1921 def insert(self, index, value):
1922 self.lst.insert(index, value)
1923
1924 mss = MutableSequenceSubclass()
1925 mss.append(0)
1926 mss.extend((1, 2, 3, 4))
1927 self.assertEqual(len(mss), 5)
1928 self.assertEqual(mss[3], 3)
1929 mss.reverse()
1930 self.assertEqual(mss[3], 1)
1931 mss.pop()
1932 self.assertEqual(len(mss), 4)
1933 mss.remove(3)
1934 self.assertEqual(len(mss), 3)
1935 mss += (10, 20, 30)
1936 self.assertEqual(len(mss), 6)
1937 self.assertEqual(mss[-1], 30)
1938 mss.clear()
1939 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001940
Naris R1b5f9c92018-08-31 02:56:14 +10001941 # issue 34427
1942 # extending self should not cause infinite loop
1943 items = 'ABCD'
1944 mss2 = MutableSequenceSubclass()
1945 mss2.extend(items + items)
1946 mss.clear()
1947 mss.extend(items)
1948 mss.extend(mss)
1949 self.assertEqual(len(mss), len(mss2))
1950 self.assertEqual(list(mss), list(mss2))
1951
1952
Raymond Hettinger499e1932011-02-23 07:56:53 +00001953################################################################################
1954### Counter
1955################################################################################
1956
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001957class CounterSubclassWithSetItem(Counter):
1958 # Test a counter subclass that overrides __setitem__
1959 def __init__(self, *args, **kwds):
1960 self.called = False
1961 Counter.__init__(self, *args, **kwds)
1962 def __setitem__(self, key, value):
1963 self.called = True
1964 Counter.__setitem__(self, key, value)
1965
1966class CounterSubclassWithGet(Counter):
1967 # Test a counter subclass that overrides get()
1968 def __init__(self, *args, **kwds):
1969 self.called = False
1970 Counter.__init__(self, *args, **kwds)
1971 def get(self, key, default):
1972 self.called = True
1973 return Counter.get(self, key, default)
1974
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001975class TestCounter(unittest.TestCase):
1976
1977 def test_basics(self):
1978 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001979 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1980 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001981 self.assertIsInstance(c, dict)
1982 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001983 self.assertTrue(issubclass(Counter, dict))
1984 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001985 self.assertEqual(len(c), 3)
1986 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001987 self.assertEqual(list(c.values()), [3, 2, 1])
1988 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1989 self.assertEqual(list(c), ['a', 'b', 'c'])
1990 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001991 [('a', 3), ('b', 2), ('c', 1)])
1992 self.assertEqual(c['b'], 2)
1993 self.assertEqual(c['z'], 0)
1994 self.assertEqual(c.__contains__('c'), True)
1995 self.assertEqual(c.__contains__('z'), False)
1996 self.assertEqual(c.get('b', 10), 2)
1997 self.assertEqual(c.get('z', 10), 10)
1998 self.assertEqual(c, dict(a=3, b=2, c=1))
1999 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
2000 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
2001 for i in range(5):
2002 self.assertEqual(c.most_common(i),
2003 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002004 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002005 c['a'] += 1 # increment an existing value
2006 c['b'] -= 2 # sub existing value to zero
2007 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002008 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002009 c['d'] -= 2 # sub from a missing value
2010 c['e'] = -5 # directly assign a missing value
2011 c['f'] += 4 # add to a missing value
2012 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002013 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002014 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002015 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002016 for i in range(3):
2017 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002018 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002019 c.clear()
2020 self.assertEqual(c, {})
2021 self.assertEqual(repr(c), 'Counter()')
2022 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
2023 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002024 c.update(dict(a=5, b=3))
2025 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002026 c.update(Counter('a' * 50 + 'b' * 30))
2027 c.update() # test case with no args
2028 c.__init__('a' * 500 + 'b' * 300)
2029 c.__init__('cdc')
2030 c.__init__()
2031 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
2032 self.assertEqual(c.setdefault('d', 5), 1)
2033 self.assertEqual(c['d'], 1)
2034 self.assertEqual(c.setdefault('e', 5), 5)
2035 self.assertEqual(c['e'], 5)
2036
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002037 def test_init(self):
2038 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
2039 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
2040 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
2041 self.assertRaises(TypeError, Counter, 42)
2042 self.assertRaises(TypeError, Counter, (), ())
2043 self.assertRaises(TypeError, Counter.__init__)
2044
Raymond Hettinger407c7342019-02-21 09:19:00 -08002045 def test_order_preservation(self):
2046 # Input order dictates items() order
2047 self.assertEqual(list(Counter('abracadabra').items()),
2048 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
2049 # letters with same count: ^----------^ ^---------^
2050
2051 # Verify retention of order even when all counts are equal
2052 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
2053 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
2054
2055 # Input order dictates elements() order
2056 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
2057 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
2058 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
2059
2060 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10002061 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08002062 ps = 'aaabbcdddeefggghhijjjkkl'
2063 qs = 'abbcccdeefffhkkllllmmnno'
2064 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
2065 def correctly_ordered(seq):
2066 'Return true if the letters occur in the expected order'
2067 positions = [order[letter] for letter in seq]
2068 return positions == sorted(positions)
2069
2070 p, q = Counter(ps), Counter(qs)
2071 self.assertTrue(correctly_ordered(+p))
2072 self.assertTrue(correctly_ordered(-p))
2073 self.assertTrue(correctly_ordered(p + q))
2074 self.assertTrue(correctly_ordered(p - q))
2075 self.assertTrue(correctly_ordered(p | q))
2076 self.assertTrue(correctly_ordered(p & q))
2077
2078 p, q = Counter(ps), Counter(qs)
2079 p += q
2080 self.assertTrue(correctly_ordered(p))
2081
2082 p, q = Counter(ps), Counter(qs)
2083 p -= q
2084 self.assertTrue(correctly_ordered(p))
2085
2086 p, q = Counter(ps), Counter(qs)
2087 p |= q
2088 self.assertTrue(correctly_ordered(p))
2089
2090 p, q = Counter(ps), Counter(qs)
2091 p &= q
2092 self.assertTrue(correctly_ordered(p))
2093
2094 p, q = Counter(ps), Counter(qs)
2095 p.update(q)
2096 self.assertTrue(correctly_ordered(p))
2097
2098 p, q = Counter(ps), Counter(qs)
2099 p.subtract(q)
2100 self.assertTrue(correctly_ordered(p))
2101
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002102 def test_update(self):
2103 c = Counter()
2104 c.update(self=42)
2105 self.assertEqual(list(c.items()), [('self', 42)])
2106 c = Counter()
2107 c.update(iterable=42)
2108 self.assertEqual(list(c.items()), [('iterable', 42)])
2109 c = Counter()
2110 c.update(iterable=None)
2111 self.assertEqual(list(c.items()), [('iterable', None)])
2112 self.assertRaises(TypeError, Counter().update, 42)
2113 self.assertRaises(TypeError, Counter().update, {}, {})
2114 self.assertRaises(TypeError, Counter.update)
2115
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002116 def test_copying(self):
2117 # Check that counters are copyable, deepcopyable, picklable, and
2118 #have a repr/eval round-trip
2119 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002120 def check(dup):
2121 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2122 self.assertIsNot(dup, words, msg)
2123 self.assertEqual(dup, words)
2124 check(words.copy())
2125 check(copy.copy(words))
2126 check(copy.deepcopy(words))
2127 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2128 with self.subTest(proto=proto):
2129 check(pickle.loads(pickle.dumps(words, proto)))
2130 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002131 update_test = Counter()
2132 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002133 check(update_test)
2134 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002135
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002136 def test_copy_subclass(self):
2137 class MyCounter(Counter):
2138 pass
2139 c = MyCounter('slartibartfast')
2140 d = c.copy()
2141 self.assertEqual(d, c)
2142 self.assertEqual(len(d), len(c))
2143 self.assertEqual(type(d), type(c))
2144
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002145 def test_conversions(self):
2146 # Convert to: set, list, dict
2147 s = 'she sells sea shells by the sea shore'
2148 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2149 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2150 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2151 self.assertEqual(set(Counter(s)), set(s))
2152
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002153 def test_invariant_for_the_in_operator(self):
2154 c = Counter(a=10, b=-2, c=0)
2155 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002156 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002157 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002158
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002159 def test_multiset_operations(self):
2160 # Verify that adding a zero counter will strip zeros and negatives
2161 c = Counter(a=10, b=-2, c=0) + Counter()
2162 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002163
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002164 elements = 'abcd'
2165 for i in range(1000):
2166 # test random pairs of multisets
2167 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002168 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002169 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002170 q.update(h=1, i=-1, j=0)
2171 for counterop, numberop in [
2172 (Counter.__add__, lambda x, y: max(0, x+y)),
2173 (Counter.__sub__, lambda x, y: max(0, x-y)),
2174 (Counter.__or__, lambda x, y: max(0,x,y)),
2175 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002176 ]:
2177 result = counterop(p, q)
2178 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002179 self.assertEqual(numberop(p[x], q[x]), result[x],
2180 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002181 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002182 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002183
2184 elements = 'abcdef'
2185 for i in range(100):
2186 # verify that random multisets with no repeats are exactly like sets
2187 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2188 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2189 for counterop, setop in [
2190 (Counter.__sub__, set.__sub__),
2191 (Counter.__or__, set.__or__),
2192 (Counter.__and__, set.__and__),
2193 ]:
2194 counter_result = counterop(p, q)
2195 set_result = setop(set(p.elements()), set(q.elements()))
2196 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002197
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002198 def test_inplace_operations(self):
2199 elements = 'abcd'
2200 for i in range(1000):
2201 # test random pairs of multisets
2202 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2203 p.update(e=1, f=-1, g=0)
2204 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2205 q.update(h=1, i=-1, j=0)
2206 for inplace_op, regular_op in [
2207 (Counter.__iadd__, Counter.__add__),
2208 (Counter.__isub__, Counter.__sub__),
2209 (Counter.__ior__, Counter.__or__),
2210 (Counter.__iand__, Counter.__and__),
2211 ]:
2212 c = p.copy()
2213 c_id = id(c)
2214 regular_result = regular_op(c, q)
2215 inplace_result = inplace_op(c, q)
2216 self.assertEqual(inplace_result, regular_result)
2217 self.assertEqual(id(inplace_result), c_id)
2218
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002219 def test_subtract(self):
2220 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2221 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2222 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2223 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2224 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2225 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2226 c = Counter('aaabbcd')
2227 c.subtract('aaaabbcce')
2228 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002229
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002230 c = Counter()
2231 c.subtract(self=42)
2232 self.assertEqual(list(c.items()), [('self', -42)])
2233 c = Counter()
2234 c.subtract(iterable=42)
2235 self.assertEqual(list(c.items()), [('iterable', -42)])
2236 self.assertRaises(TypeError, Counter().subtract, 42)
2237 self.assertRaises(TypeError, Counter().subtract, {}, {})
2238 self.assertRaises(TypeError, Counter.subtract)
2239
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002240 def test_unary(self):
2241 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2242 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2243 self.assertEqual(dict(-c), dict(a=5))
2244
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002245 def test_repr_nonsortable(self):
2246 c = Counter(a=2, b=None)
2247 r = repr(c)
2248 self.assertIn("'a': 2", r)
2249 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002250
Raymond Hettinger426e0522011-01-03 02:12:02 +00002251 def test_helper_function(self):
2252 # two paths, one for real dicts and one for other mappings
2253 elems = list('abracadabra')
2254
2255 d = dict()
2256 _count_elements(d, elems)
2257 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2258
2259 m = OrderedDict()
2260 _count_elements(m, elems)
2261 self.assertEqual(m,
2262 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2263
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002264 # test fidelity to the pure python version
2265 c = CounterSubclassWithSetItem('abracadabra')
2266 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002267 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002268 c = CounterSubclassWithGet('abracadabra')
2269 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002270 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002271
Raymond Hettinger60398512020-05-28 08:35:46 -07002272 def test_multiset_operations_equivalent_to_set_operations(self):
2273 # When the multiplicities are all zero or one, multiset operations
2274 # are guaranteed to be equivalent to the corresponding operations
2275 # for regular sets.
2276 s = list(product(('a', 'b', 'c'), range(2)))
2277 powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
2278 counters = [Counter(dict(groups)) for groups in powerset]
2279 for cp, cq in product(counters, repeat=2):
2280 sp = set(cp.elements())
2281 sq = set(cq.elements())
2282 self.assertEqual(set(cp + cq), sp | sq)
2283 self.assertEqual(set(cp - cq), sp - sq)
2284 self.assertEqual(set(cp | cq), sp | sq)
2285 self.assertEqual(set(cp & cq), sp & sq)
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002286 self.assertEqual(cp == cq, sp == sq)
2287 self.assertEqual(cp != cq, sp != sq)
2288 self.assertEqual(cp <= cq, sp <= sq)
2289 self.assertEqual(cp >= cq, sp >= sq)
2290 self.assertEqual(cp < cq, sp < sq)
2291 self.assertEqual(cp > cq, sp > sq)
Raymond Hettinger60398512020-05-28 08:35:46 -07002292
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002293 def test_eq(self):
2294 self.assertEqual(Counter(a=3, b=2, c=0), Counter('ababa'))
2295 self.assertNotEqual(Counter(a=3, b=2), Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002296
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002297 def test_le(self):
2298 self.assertTrue(Counter(a=3, b=2, c=0) <= Counter('ababa'))
2299 self.assertFalse(Counter(a=3, b=2) <= Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002300
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002301 def test_lt(self):
2302 self.assertTrue(Counter(a=3, b=1, c=0) < Counter('ababa'))
2303 self.assertFalse(Counter(a=3, b=2, c=0) < Counter('ababa'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002304
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002305 def test_ge(self):
2306 self.assertTrue(Counter(a=2, b=1, c=0) >= Counter('aab'))
2307 self.assertFalse(Counter(a=3, b=2, c=0) >= Counter('aabd'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002308
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002309 def test_gt(self):
2310 self.assertTrue(Counter(a=3, b=2, c=0) > Counter('aab'))
2311 self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002312
Raymond Hettinger499e1932011-02-23 07:56:53 +00002313
2314################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002315### Run tests
2316################################################################################
2317
Guido van Rossumd8faa362007-04-27 19:54:29 +00002318def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002319 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002320 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002321 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002322 TestUserObjects,
2323 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002324 support.run_unittest(*test_classes)
2325 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002326
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002327
Guido van Rossumd8faa362007-04-27 19:54:29 +00002328if __name__ == "__main__":
2329 test_main(verbose=True)