blob: 54a4cbed44e37911805f7b420355e2be071923a4 [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +02003import collections
4import copy
5import doctest
Serhiy Storchaka052b2df2018-12-31 14:15:16 +02006import inspect
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +02007import operator
8import pickle
9from random import choice, randrange
Raymond Hettinger60398512020-05-28 08:35:46 -070010from itertools import product, chain, combinations
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020011import string
R. David Murray378c0cf2010-02-24 01:46:21 +000012import sys
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020013from test import support
Yury Selivanov75445082015-05-11 22:57:16 -040014import types
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020015import unittest
16
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020017from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger573b44c2015-05-22 16:56:32 -070018from collections import UserDict, UserString, UserList
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000019from collections import ChainMap
Raymond Hettinger32ea1652015-03-21 01:37:37 -070020from collections import deque
Yury Selivanov22214ab2016-11-16 18:25:04 -050021from collections.abc import Awaitable, Coroutine
22from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator
Guido van Rossum16ca06b2016-04-04 10:59:29 -070023from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
Guido van Rossumf0666942016-08-23 10:47:07 -070024from collections.abc import Sized, Container, Callable, Collection
Raymond Hettinger57d1a882011-02-23 00:46:28 +000025from collections.abc import Set, MutableSet
Raymond Hettinger584e8ae2016-05-05 11:14:06 +030026from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
Raymond Hettinger57d1a882011-02-23 00:46:28 +000027from collections.abc import Sequence, MutableSequence
28from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000029
Raymond Hettinger499e1932011-02-23 07:56:53 +000030
Raymond Hettinger573b44c2015-05-22 16:56:32 -070031class TestUserObjects(unittest.TestCase):
32 def _superset_test(self, a, b):
33 self.assertGreaterEqual(
34 set(dir(a)),
35 set(dir(b)),
36 '{a} should have all the methods of {b}'.format(
37 a=a.__name__,
38 b=b.__name__,
39 ),
40 )
Bar Harelf4e1bab2019-05-19 16:57:13 +030041
42 def _copy_test(self, obj):
43 # Test internal copy
44 obj_copy = obj.copy()
45 self.assertIsNot(obj.data, obj_copy.data)
46 self.assertEqual(obj.data, obj_copy.data)
47
48 # Test copy.copy
49 obj.test = [1234] # Make sure instance vars are also copied.
50 obj_copy = copy.copy(obj)
51 self.assertIsNot(obj.data, obj_copy.data)
52 self.assertEqual(obj.data, obj_copy.data)
53 self.assertIs(obj.test, obj_copy.test)
54
Raymond Hettinger573b44c2015-05-22 16:56:32 -070055 def test_str_protocol(self):
56 self._superset_test(UserString, str)
57
58 def test_list_protocol(self):
59 self._superset_test(UserList, list)
60
61 def test_dict_protocol(self):
62 self._superset_test(UserDict, dict)
63
Bar Harelf4e1bab2019-05-19 16:57:13 +030064 def test_list_copy(self):
65 obj = UserList()
66 obj.append(123)
67 self._copy_test(obj)
68
69 def test_dict_copy(self):
70 obj = UserDict()
71 obj[123] = "abc"
72 self._copy_test(obj)
73
Raymond Hettinger573b44c2015-05-22 16:56:32 -070074
Raymond Hettinger499e1932011-02-23 07:56:53 +000075################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000076### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000077################################################################################
78
79class TestChainMap(unittest.TestCase):
80
81 def test_basics(self):
82 c = ChainMap()
83 c['a'] = 1
84 c['b'] = 2
85 d = c.new_child()
86 d['b'] = 20
87 d['c'] = 30
88 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
89 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
90 self.assertEqual(len(d), 3) # check len
91 for key in 'abc': # check contains
92 self.assertIn(key, d)
93 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
94 self.assertEqual(d.get(k, 100), v)
95
96 del d['b'] # unmask a value
97 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
98 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
99 self.assertEqual(len(d), 3) # check len
100 for key in 'abc': # check contains
101 self.assertIn(key, d)
102 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
103 self.assertEqual(d.get(k, 100), v)
104 self.assertIn(repr(d), [ # check repr
105 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
106 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
107 ])
108
109 for e in d.copy(), copy.copy(d): # check shallow copies
110 self.assertEqual(d, e)
111 self.assertEqual(d.maps, e.maps)
112 self.assertIsNot(d, e)
113 self.assertIsNot(d.maps[0], e.maps[0])
114 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
115 self.assertIs(m1, m2)
116
Serhiy Storchakabad12572014-12-15 14:03:42 +0200117 # check deep copies
118 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
119 e = pickle.loads(pickle.dumps(d, proto))
120 self.assertEqual(d, e)
121 self.assertEqual(d.maps, e.maps)
122 self.assertIsNot(d, e)
123 for m1, m2 in zip(d.maps, e.maps):
124 self.assertIsNot(m1, m2, e)
125 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +0000126 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +0200127 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +0000128 self.assertEqual(d, e)
129 self.assertEqual(d.maps, e.maps)
130 self.assertIsNot(d, e)
131 for m1, m2 in zip(d.maps, e.maps):
132 self.assertIsNot(m1, m2, e)
133
Raymond Hettingerd0321312011-02-26 06:53:58 +0000134 f = d.new_child()
135 f['b'] = 5
136 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
137 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
138 self.assertEqual(f['b'], 5) # find first in chain
139 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +0000140
Raymond Hettinger86f093f2019-02-21 09:12:15 -0800141 def test_ordering(self):
142 # Combined order matches a series of dict updates from last to first.
143 # This test relies on the ordering of the underlying dicts.
144
145 baseline = {'music': 'bach', 'art': 'rembrandt'}
146 adjustments = {'art': 'van gogh', 'opera': 'carmen'}
147
148 cm = ChainMap(adjustments, baseline)
149
150 combined = baseline.copy()
151 combined.update(adjustments)
152
153 self.assertEqual(list(combined.items()), list(cm.items()))
154
Martin Pantereb995702016-07-28 01:11:04 +0000155 def test_constructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +0000156 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +0000157 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
158
Raymond Hettingerd0321312011-02-26 06:53:58 +0000159 def test_bool(self):
160 self.assertFalse(ChainMap())
161 self.assertFalse(ChainMap({}, {}))
162 self.assertTrue(ChainMap({1:2}, {}))
163 self.assertTrue(ChainMap({}, {1:2}))
164
Raymond Hettinger499e1932011-02-23 07:56:53 +0000165 def test_missing(self):
166 class DefaultChainMap(ChainMap):
167 def __missing__(self, key):
168 return 999
169 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
170 for k, v in dict(a=1, b=2, c=30, d=999).items():
171 self.assertEqual(d[k], v) # check __getitem__ w/missing
172 for k, v in dict(a=1, b=2, c=30, d=77).items():
173 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
174 for k, v in dict(a=True, b=True, c=True, d=False).items():
175 self.assertEqual(k in d, v) # check __contains__ w/missing
176 self.assertEqual(d.pop('a', 1001), 1, d)
177 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
178 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
179 with self.assertRaises(KeyError):
180 d.popitem()
181
Raymond Hettinger3793f952018-02-11 00:30:31 -0800182 def test_order_preservation(self):
183 d = ChainMap(
184 OrderedDict(j=0, h=88888),
185 OrderedDict(),
186 OrderedDict(i=9999, d=4444, c=3333),
187 OrderedDict(f=666, b=222, g=777, c=333, h=888),
188 OrderedDict(),
189 OrderedDict(e=55, b=22),
190 OrderedDict(a=1, b=2, c=3, d=4, e=5),
191 OrderedDict(),
192 )
193 self.assertEqual(''.join(d), 'abcdefghij')
194 self.assertEqual(list(d.items()),
195 [('a', 1), ('b', 222), ('c', 3333), ('d', 4444),
196 ('e', 55), ('f', 666), ('g', 777), ('h', 88888),
197 ('i', 9999), ('j', 0)])
198
Andreas Poehlmann0be9ce32020-11-30 17:34:15 +0100199 def test_iter_not_calling_getitem_on_maps(self):
200 class DictWithGetItem(UserDict):
201 def __init__(self, *args, **kwds):
202 self.called = False
203 UserDict.__init__(self, *args, **kwds)
204 def __getitem__(self, item):
205 self.called = True
206 UserDict.__getitem__(self, item)
207
208 d = DictWithGetItem(a=1)
209 c = ChainMap(d)
210 d.called = False
211
212 set(c) # iterate over chain map
213 self.assertFalse(d.called, '__getitem__ was called')
214
Raymond Hettinger499e1932011-02-23 07:56:53 +0000215 def test_dict_coercion(self):
216 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
217 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
218 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
219
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000220 def test_new_child(self):
221 'Tests for changes for issue #16613.'
222 c = ChainMap()
223 c['a'] = 1
224 c['b'] = 2
225 m = {'b':20, 'c': 30}
226 d = c.new_child(m)
227 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
228 self.assertIs(m, d.maps[0])
229
230 # Use a different map than a dict
231 class lowerdict(dict):
232 def __getitem__(self, key):
233 if isinstance(key, str):
234 key = key.lower()
235 return dict.__getitem__(self, key)
236 def __contains__(self, key):
237 if isinstance(key, str):
238 key = key.lower()
239 return dict.__contains__(self, key)
240
241 c = ChainMap()
242 c['a'] = 1
243 c['b'] = 2
244 m = lowerdict(b=20, c=30)
245 d = c.new_child(m)
246 self.assertIs(m, d.maps[0])
247 for key in 'abc': # check contains
248 self.assertIn(key, d)
249 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
250 self.assertEqual(d.get(k, 100), v)
251
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700252 def test_union_operators(self):
253 cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
254 cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
255 cm3 = cm1.copy()
256 d = dict(a=10, c=30)
257 pairs = [('c', 3), ('p',0)]
258
259 tmp = cm1 | cm2 # testing between chainmaps
260 self.assertEqual(tmp.maps, [cm1.maps[0] | dict(cm2), *cm1.maps[1:]])
261 cm1 |= cm2
262 self.assertEqual(tmp, cm1)
263
264 tmp = cm2 | d # testing between chainmap and mapping
265 self.assertEqual(tmp.maps, [cm2.maps[0] | d, *cm2.maps[1:]])
266 self.assertEqual((d | cm2).maps, [d | dict(cm2)])
267 cm2 |= d
268 self.assertEqual(tmp, cm2)
269
270 # testing behavior between chainmap and iterable key-value pairs
271 with self.assertRaises(TypeError):
272 cm3 | pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700273 tmp = cm3.copy()
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700274 cm3 |= pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700275 self.assertEqual(cm3.maps, [tmp.maps[0] | dict(pairs), *tmp.maps[1:]])
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700276
277 # testing proper return types for ChainMap and it's subclasses
278 class Subclass(ChainMap):
279 pass
280
281 class SubclassRor(ChainMap):
282 def __ror__(self, other):
283 return super().__ror__(other)
284
285 tmp = ChainMap() | ChainMap()
286 self.assertIs(type(tmp), ChainMap)
287 self.assertIs(type(tmp.maps[0]), dict)
288 tmp = ChainMap() | Subclass()
289 self.assertIs(type(tmp), ChainMap)
290 self.assertIs(type(tmp.maps[0]), dict)
291 tmp = Subclass() | ChainMap()
292 self.assertIs(type(tmp), Subclass)
293 self.assertIs(type(tmp.maps[0]), dict)
294 tmp = ChainMap() | SubclassRor()
295 self.assertIs(type(tmp), SubclassRor)
296 self.assertIs(type(tmp.maps[0]), dict)
297
Raymond Hettinger499e1932011-02-23 07:56:53 +0000298
299################################################################################
300### Named Tuples
301################################################################################
302
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000303TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000304
305class TestNamedTuple(unittest.TestCase):
306
307 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000308 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000309 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000310 self.assertEqual(Point.__slots__, ())
311 self.assertEqual(Point.__module__, __name__)
312 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000313 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000314
315 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
316 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
317 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
318
319 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
320 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
321 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000322 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000323 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
324
325 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000326 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000327
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000328 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000329 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000330 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000331 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000332
Christian Heimesfaf2f632008-01-06 16:59:19 +0000333 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
334 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
335
Raymond Hettinger39482072018-01-10 21:45:19 -0800336 def test_defaults(self):
337 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700338 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800339 self.assertEqual(Point(1, 2), (1, 2))
340 self.assertEqual(Point(1), (1, 20))
341 self.assertEqual(Point(), (10, 20))
342
343 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700344 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800345 self.assertEqual(Point(1, 2), (1, 2))
346 self.assertEqual(Point(1), (1, 20))
347
348 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700349 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800350 self.assertEqual(Point(1, 2), (1, 2))
351 with self.assertRaises(TypeError):
352 Point(1)
353
354 with self.assertRaises(TypeError): # catch too few args
355 Point()
356 with self.assertRaises(TypeError): # catch too many args
357 Point(1, 2, 3)
358 with self.assertRaises(TypeError): # too many defaults
359 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
360 with self.assertRaises(TypeError): # non-iterable defaults
361 Point = namedtuple('Point', 'x y', defaults=10)
362 with self.assertRaises(TypeError): # another non-iterable default
363 Point = namedtuple('Point', 'x y', defaults=False)
364
365 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700366 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800367 self.assertIsNone(Point.__new__.__defaults__, None)
368 self.assertEqual(Point(10, 20), (10, 20))
369 with self.assertRaises(TypeError): # catch too few args
370 Point(10)
371
372 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700373 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800374 self.assertEqual(Point.__new__.__defaults__, (10, 20))
375 self.assertEqual(Point(1, 2), (1, 2))
376 self.assertEqual(Point(1), (1, 20))
377 self.assertEqual(Point(), (10, 20))
378
379 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700380 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800381 self.assertEqual(Point.__new__.__defaults__, (10, 20))
382 self.assertEqual(Point(1, 2), (1, 2))
383 self.assertEqual(Point(1), (1, 20))
384 self.assertEqual(Point(), (10, 20))
385
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200386 def test_readonly(self):
387 Point = namedtuple('Point', 'x y')
388 p = Point(11, 22)
389 with self.assertRaises(AttributeError):
390 p.x = 33
391 with self.assertRaises(AttributeError):
392 del p.x
393 with self.assertRaises(TypeError):
394 p[0] = 33
395 with self.assertRaises(TypeError):
396 del p[0]
397 self.assertEqual(p.x, 11)
398 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800399
R. David Murray378c0cf2010-02-24 01:46:21 +0000400 @unittest.skipIf(sys.flags.optimize >= 2,
401 "Docstrings are omitted with -O2 and above")
402 def test_factory_doc_attr(self):
403 Point = namedtuple('Point', 'x y')
404 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200405 Point.__doc__ = '2D point'
406 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000407
Raymond Hettingereac503a2015-05-13 01:09:59 -0700408 @unittest.skipIf(sys.flags.optimize >= 2,
409 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200410 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700411 Point = namedtuple('Point', 'x y')
412 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200413 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700414 Point.x.__doc__ = 'docstring for Point.x'
415 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200416 # namedtuple can mutate doc of descriptors independently
417 Vector = namedtuple('Vector', 'x y')
418 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
419 Vector.x.__doc__ = 'docstring for Vector.x'
420 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
421
422 @support.cpython_only
423 @unittest.skipIf(sys.flags.optimize >= 2,
424 "Docstrings are omitted with -O2 and above")
425 def test_field_doc_reuse(self):
426 P = namedtuple('P', ['m', 'n'])
427 Q = namedtuple('Q', ['o', 'p'])
428 self.assertIs(P.m.__doc__, Q.o.__doc__)
429 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700430
Ammar Askara86b5222020-04-14 23:36:08 -0700431 @support.cpython_only
432 def test_field_repr(self):
433 Point = namedtuple('Point', 'x y')
434 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'Alias for field number 0')")
435 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'Alias for field number 1')")
436
437 Point.x.__doc__ = 'The x-coordinate'
438 Point.y.__doc__ = 'The y-coordinate'
439
440 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'The x-coordinate')")
441 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'The y-coordinate')")
442
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000443 def test_name_fixer(self):
444 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000445 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
446 [('abc', 'class'), ('abc', '_1')], # field has keyword
447 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
448 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
449 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
450 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000451 ]:
452 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
453
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700454 def test_module_parameter(self):
455 NT = namedtuple('NT', ['x', 'y'], module=collections)
456 self.assertEqual(NT.__module__, collections)
457
Guido van Rossumd8faa362007-04-27 19:54:29 +0000458 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000459 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000460 p = Point(11, 22)
461 self.assertEqual(p, Point(x=11, y=22))
462 self.assertEqual(p, Point(11, y=22))
463 self.assertEqual(p, Point(y=22, x=11))
464 self.assertEqual(p, Point(*(11, 22)))
465 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200466 self.assertRaises(TypeError, Point, 1) # too few args
467 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
468 with self.assertRaises(TypeError): # wrong keyword argument
469 Point(XXX=1, y=2)
470 with self.assertRaises(TypeError): # missing keyword argument
471 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000472 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000473 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200474 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
475 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
476 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
477 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000478
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000479 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000480 p._replace(x=1, error=2)
481 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000482 pass
483 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000484 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000485
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000486 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000487 Point = namedtuple('Point', 'x, y')
488 p = Point(x=11, y=22)
489 self.assertEqual(repr(p), 'Point(x=11, y=22)')
490
491 # verify that fieldspec can be a non-string sequence
492 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000493 p = Point(x=11, y=22)
494 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000495
496 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000497 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000498 p = Point(11, 22)
499
Ezio Melottie9615932010-01-24 19:26:24 +0000500 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000501 self.assertEqual(p, (11, 22)) # matches a real tuple
Min ho Kimc4cacc82019-07-31 08:16:13 +1000502 self.assertEqual(tuple(p), (11, 22)) # coercible to a real tuple
503 self.assertEqual(list(p), [11, 22]) # coercible to a list
Guido van Rossumd8faa362007-04-27 19:54:29 +0000504 self.assertEqual(max(p), 22) # iterable
505 self.assertEqual(max(*p), 22) # star-able
506 x, y = p
507 self.assertEqual(p, (x, y)) # unpacks like a tuple
508 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200509 with self.assertRaises(IndexError):
510 p[3]
511 self.assertEqual(p[-1], 22)
512 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000513
514 self.assertEqual(p.x, x)
515 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200516 with self.assertRaises(AttributeError):
517 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000518
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000519 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000520 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000521 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000522 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000523 self.assertEqual(repr(Zero()), 'Zero()')
524 self.assertEqual(Zero()._asdict(), {})
525 self.assertEqual(Zero()._fields, ())
526
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000527 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000528 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000529 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000530 self.assertEqual(Dot(1).d, 1)
531 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
532 self.assertEqual(Dot(1)._asdict(), {'d':1})
533 self.assertEqual(Dot(1)._replace(d=999), (999,))
534 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000535
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200536 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200537 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000538 for j in range(10)]) for i in range(n)))
539 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000540 Big = namedtuple('Big', names)
541 b = Big(*range(n))
542 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000543 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000544 for pos, name in enumerate(names):
545 self.assertEqual(getattr(b, name), pos)
546 repr(b) # make sure repr() doesn't blow-up
547 d = b._asdict()
548 d_expected = dict(zip(names, range(n)))
549 self.assertEqual(d, d_expected)
550 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
551 b2_expected = list(range(n))
552 b2_expected[1] = 999
553 b2_expected[-5] = 42
554 self.assertEqual(b2, tuple(b2_expected))
555 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000556
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000557 def test_pickle(self):
558 p = TestNT(x=10, y=20, z=30)
559 for module in (pickle,):
560 loads = getattr(module, 'loads')
561 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500562 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000563 q = loads(dumps(p, protocol))
564 self.assertEqual(p, q)
565 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700566 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000567
568 def test_copy(self):
569 p = TestNT(x=10, y=20, z=30)
570 for copier in copy.copy, copy.deepcopy:
571 q = copier(p)
572 self.assertEqual(p, q)
573 self.assertEqual(p._fields, q._fields)
574
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000575 def test_name_conflicts(self):
576 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
577 # failed when used as field names. Test to make sure these now work.
578 T = namedtuple('T', 'itemgetter property self cls tuple')
579 t = T(1, 2, 3, 4, 5)
580 self.assertEqual(t, (1,2,3,4,5))
581 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
582 self.assertEqual(newt, (10,20,30,40,50))
583
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700584 # Broader test of all interesting names taken from the code, old
585 # template, and an example
586 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
587 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
588 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
589 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
590 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
591 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
592 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
593 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
594 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
595 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
596 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
597 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
598 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
599 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
600 'instantiate', 'interning', 'introspection', 'isidentifier',
601 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
602 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
603 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
604 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
605 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
606 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
607 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
608 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
609 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
610 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
611 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
612 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
613 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
614 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000615 T = namedtuple('T', words)
616 # test __new__
617 values = tuple(range(len(words)))
618 t = T(*values)
619 self.assertEqual(t, values)
620 t = T(**dict(zip(T._fields, values)))
621 self.assertEqual(t, values)
622 # test _make
623 t = T._make(values)
624 self.assertEqual(t, values)
625 # exercise __repr__
626 repr(t)
627 # test _asdict
628 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
629 # test _replace
630 t = T._make(values)
631 newvalues = tuple(v*10 for v in values)
632 newt = t._replace(**dict(zip(T._fields, newvalues)))
633 self.assertEqual(newt, newvalues)
634 # test _fields
635 self.assertEqual(T._fields, tuple(words))
636 # test __getnewargs__
637 self.assertEqual(t.__getnewargs__(), values)
638
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000639 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700640 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000641 self.assertEqual(repr(A(1)), 'A(x=1)')
642 # repr should show the name of the subclass
643 class B(A):
644 pass
645 self.assertEqual(repr(B(1)), 'B(x=1)')
646
Raymond Hettinger6538b432016-08-16 10:55:43 -0700647 def test_keyword_only_arguments(self):
648 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700649 with self.assertRaises(TypeError):
650 NT = namedtuple('NT', ['x', 'y'], True)
651
652 NT = namedtuple('NT', ['abc', 'def'], rename=True)
653 self.assertEqual(NT._fields, ('abc', '_1'))
654 with self.assertRaises(TypeError):
655 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000656
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700657 def test_namedtuple_subclass_issue_24931(self):
658 class Point(namedtuple('_Point', ['x', 'y'])):
659 pass
660
661 a = Point(3, 4)
662 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
663
664 a.w = 5
665 self.assertEqual(a.__dict__, {'w': 5})
666
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200667 def test_field_descriptor(self):
668 Point = namedtuple('Point', 'x y')
669 p = Point(11, 22)
670 self.assertTrue(inspect.isdatadescriptor(Point.x))
671 self.assertEqual(Point.x.__get__(p), 11)
672 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
673 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000674
Joe Jevnikf36f8922019-02-21 16:00:40 -0500675 class NewPoint(tuple):
676 x = pickle.loads(pickle.dumps(Point.x))
677 y = pickle.loads(pickle.dumps(Point.y))
678
679 np = NewPoint([1, 2])
680
681 self.assertEqual(np.x, 1)
682 self.assertEqual(np.y, 2)
683
Raymond Hettingerb6d68aa2021-02-04 15:52:16 -0800684 def test_new_builtins_issue_43102(self):
Victor Stinnera3c3ffa2021-02-18 12:35:37 +0100685 obj = namedtuple('C', ())
686 new_func = obj.__new__
687 self.assertEqual(new_func.__globals__['__builtins__'], {})
688 self.assertEqual(new_func.__builtins__, {})
Raymond Hettingerb6d68aa2021-02-04 15:52:16 -0800689
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700690
Raymond Hettinger499e1932011-02-23 07:56:53 +0000691################################################################################
692### Abstract Base Classes
693################################################################################
694
Raymond Hettingerae650182009-01-28 23:33:59 +0000695class ABCTestCase(unittest.TestCase):
696
697 def validate_abstract_methods(self, abc, *names):
698 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
699
700 # everything should work will all required methods are present
701 C = type('C', (abc,), methodstubs)
702 C()
703
704 # instantiation should fail if a required method is missing
705 for name in names:
706 stubs = methodstubs.copy()
707 del stubs[name]
708 C = type('C', (abc,), stubs)
709 self.assertRaises(TypeError, C, name)
710
Florent Xiclunace153f62010-03-08 15:34:35 +0000711 def validate_isinstance(self, abc, name):
712 stub = lambda s, *args: 0
713
714 C = type('C', (object,), {'__hash__': None})
715 setattr(C, name, stub)
716 self.assertIsInstance(C(), abc)
717 self.assertTrue(issubclass(C, abc))
718
719 C = type('C', (object,), {'__hash__': None})
720 self.assertNotIsInstance(C(), abc)
721 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000722
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000723 def validate_comparison(self, instance):
724 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
725 operators = {}
726 for op in ops:
727 name = '__' + op + '__'
728 operators[name] = getattr(operator, name)
729
730 class Other:
731 def __init__(self):
732 self.right_side = False
733 def __eq__(self, other):
734 self.right_side = True
735 return True
736 __lt__ = __eq__
737 __gt__ = __eq__
738 __le__ = __eq__
739 __ge__ = __eq__
740 __ne__ = __eq__
741 __ror__ = __eq__
742 __rand__ = __eq__
743 __rxor__ = __eq__
744 __rsub__ = __eq__
745
746 for name, op in operators.items():
747 if not hasattr(instance, name):
748 continue
749 other = Other()
750 op(instance, other)
751 self.assertTrue(other.right_side,'Right side not called for %s.%s'
752 % (type(instance), name))
753
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700754def _test_gen():
755 yield
756
Raymond Hettingerae650182009-01-28 23:33:59 +0000757class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000758
Yury Selivanov75445082015-05-11 22:57:16 -0400759 def test_Awaitable(self):
760 def gen():
761 yield
762
763 @types.coroutine
764 def coro():
765 yield
766
767 async def new_coro():
768 pass
769
770 class Bar:
771 def __await__(self):
772 yield
773
774 class MinimalCoro(Coroutine):
775 def send(self, value):
776 return value
777 def throw(self, typ, val=None, tb=None):
778 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400779 def __await__(self):
780 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400781
782 non_samples = [None, int(), gen(), object()]
783 for x in non_samples:
784 self.assertNotIsInstance(x, Awaitable)
785 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
786
787 samples = [Bar(), MinimalCoro()]
788 for x in samples:
789 self.assertIsInstance(x, Awaitable)
790 self.assertTrue(issubclass(type(x), Awaitable))
791
792 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400793 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
794 # flag don't have '__await__' method, hence can't be instances
795 # of Awaitable. Use inspect.isawaitable to detect them.
796 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400797
798 c = new_coro()
799 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300800 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400801
Yury Selivanov56fc6142015-05-29 09:01:29 -0400802 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400803 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400804 self.assertTrue(isinstance(CoroLike(), Awaitable))
805 self.assertTrue(issubclass(CoroLike, Awaitable))
806 CoroLike = None
807 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400808
Yury Selivanov75445082015-05-11 22:57:16 -0400809 def test_Coroutine(self):
810 def gen():
811 yield
812
813 @types.coroutine
814 def coro():
815 yield
816
817 async def new_coro():
818 pass
819
820 class Bar:
821 def __await__(self):
822 yield
823
824 class MinimalCoro(Coroutine):
825 def send(self, value):
826 return value
827 def throw(self, typ, val=None, tb=None):
828 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400829 def __await__(self):
830 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400831
832 non_samples = [None, int(), gen(), object(), Bar()]
833 for x in non_samples:
834 self.assertNotIsInstance(x, Coroutine)
835 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
836
837 samples = [MinimalCoro()]
838 for x in samples:
839 self.assertIsInstance(x, Awaitable)
840 self.assertTrue(issubclass(type(x), Awaitable))
841
842 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400843 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
844 # flag don't have '__await__' method, hence can't be instances
845 # of Coroutine. Use inspect.isawaitable to detect them.
846 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400847
848 c = new_coro()
849 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300850 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400851
Yury Selivanov56fc6142015-05-29 09:01:29 -0400852 class CoroLike:
853 def send(self, value):
854 pass
855 def throw(self, typ, val=None, tb=None):
856 pass
857 def close(self):
858 pass
859 def __await__(self):
860 pass
861 self.assertTrue(isinstance(CoroLike(), Coroutine))
862 self.assertTrue(issubclass(CoroLike, Coroutine))
863
864 class CoroLike:
865 def send(self, value):
866 pass
867 def close(self):
868 pass
869 def __await__(self):
870 pass
871 self.assertFalse(isinstance(CoroLike(), Coroutine))
872 self.assertFalse(issubclass(CoroLike, Coroutine))
873
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000874 def test_Hashable(self):
875 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000876 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000877 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000878 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000879 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000880 # Check some hashables
881 samples = [None,
882 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000883 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000884 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000885 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000886 ]
887 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000888 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000889 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000890 self.assertRaises(TypeError, Hashable)
891 # Check direct subclassing
892 class H(Hashable):
893 def __hash__(self):
894 return super().__hash__()
895 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000896 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000897 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000898 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000899
Yury Selivanove0104ae2015-05-14 12:19:16 -0400900 def test_AsyncIterable(self):
901 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400902 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400903 return self
904 self.assertTrue(isinstance(AI(), AsyncIterable))
905 self.assertTrue(issubclass(AI, AsyncIterable))
906 # Check some non-iterables
907 non_samples = [None, object, []]
908 for x in non_samples:
909 self.assertNotIsInstance(x, AsyncIterable)
910 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
911 self.validate_abstract_methods(AsyncIterable, '__aiter__')
912 self.validate_isinstance(AsyncIterable, '__aiter__')
913
914 def test_AsyncIterator(self):
915 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400916 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400917 return self
918 async def __anext__(self):
919 raise StopAsyncIteration
920 self.assertTrue(isinstance(AI(), AsyncIterator))
921 self.assertTrue(issubclass(AI, AsyncIterator))
922 non_samples = [None, object, []]
923 # Check some non-iterables
924 for x in non_samples:
925 self.assertNotIsInstance(x, AsyncIterator)
926 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
927 # Similarly to regular iterators (see issue 10565)
928 class AnextOnly:
929 async def __anext__(self):
930 raise StopAsyncIteration
931 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
932 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
933
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000934 def test_Iterable(self):
935 # Check some non-iterables
936 non_samples = [None, 42, 3.14, 1j]
937 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000938 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000939 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000940 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000941 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000942 tuple(), list(), set(), frozenset(), dict(),
943 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700944 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000945 (x for x in []),
946 ]
947 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000948 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000949 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000950 # Check direct subclassing
951 class I(Iterable):
952 def __iter__(self):
953 return super().__iter__()
954 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000955 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000956 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000957 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700958 # Check None blocking
959 class It:
960 def __iter__(self): return iter([])
961 class ItBlocked(It):
962 __iter__ = None
963 self.assertTrue(issubclass(It, Iterable))
964 self.assertTrue(isinstance(It(), Iterable))
965 self.assertFalse(issubclass(ItBlocked, Iterable))
966 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000967
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700968 def test_Reversible(self):
969 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100970 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700971 for x in non_samples:
972 self.assertNotIsInstance(x, Reversible)
973 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700974 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100975 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700976 for x in non_reversibles:
977 self.assertNotIsInstance(x, Reversible)
978 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
979 # Check some reversible iterables
980 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
981 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100982 OrderedDict().values(), Counter(), Counter().keys(),
983 Counter().items(), Counter().values(), dict(),
984 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700985 for x in samples:
986 self.assertIsInstance(x, Reversible)
987 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
988 # Check also Mapping, MutableMapping, and Sequence
989 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
990 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
991 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
992 # Check direct subclassing
993 class R(Reversible):
994 def __iter__(self):
995 return iter(list())
996 def __reversed__(self):
997 return iter(list())
998 self.assertEqual(list(reversed(R())), [])
999 self.assertFalse(issubclass(float, R))
1000 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001001 # Check reversible non-iterable (which is not Reversible)
1002 class RevNoIter:
1003 def __reversed__(self): return reversed([])
1004 class RevPlusIter(RevNoIter):
1005 def __iter__(self): return iter([])
1006 self.assertFalse(issubclass(RevNoIter, Reversible))
1007 self.assertFalse(isinstance(RevNoIter(), Reversible))
1008 self.assertTrue(issubclass(RevPlusIter, Reversible))
1009 self.assertTrue(isinstance(RevPlusIter(), Reversible))
1010 # Check None blocking
1011 class Rev:
1012 def __iter__(self): return iter([])
1013 def __reversed__(self): return reversed([])
1014 class RevItBlocked(Rev):
1015 __iter__ = None
1016 class RevRevBlocked(Rev):
1017 __reversed__ = None
1018 self.assertTrue(issubclass(Rev, Reversible))
1019 self.assertTrue(isinstance(Rev(), Reversible))
1020 self.assertFalse(issubclass(RevItBlocked, Reversible))
1021 self.assertFalse(isinstance(RevItBlocked(), Reversible))
1022 self.assertFalse(issubclass(RevRevBlocked, Reversible))
1023 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001024
Guido van Rossumf0666942016-08-23 10:47:07 -07001025 def test_Collection(self):
1026 # Check some non-collections
1027 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
1028 for x in non_collections:
1029 self.assertNotIsInstance(x, Collection)
1030 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1031 # Check some non-collection iterables
1032 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001033 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -07001034 for x in non_col_iterables:
1035 self.assertNotIsInstance(x, Collection)
1036 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1037 # Check some collections
1038 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001039 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001040 for x in samples:
1041 self.assertIsInstance(x, Collection)
1042 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1043 # Check also Mapping, MutableMapping, etc.
1044 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1045 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1046 self.assertTrue(issubclass(MutableMapping, Collection),
1047 repr(MutableMapping))
1048 self.assertTrue(issubclass(Set, Collection), repr(Set))
1049 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1050 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1051 # Check direct subclassing
1052 class Col(Collection):
1053 def __iter__(self):
1054 return iter(list())
1055 def __len__(self):
1056 return 0
1057 def __contains__(self, item):
1058 return False
1059 class DerCol(Col): pass
1060 self.assertEqual(list(iter(Col())), [])
1061 self.assertFalse(issubclass(list, Col))
1062 self.assertFalse(issubclass(set, Col))
1063 self.assertFalse(issubclass(float, Col))
1064 self.assertEqual(list(iter(DerCol())), [])
1065 self.assertFalse(issubclass(list, DerCol))
1066 self.assertFalse(issubclass(set, DerCol))
1067 self.assertFalse(issubclass(float, DerCol))
1068 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1069 '__contains__')
1070 # Check sized container non-iterable (which is not Collection) etc.
1071 class ColNoIter:
1072 def __len__(self): return 0
1073 def __contains__(self, item): return False
1074 class ColNoSize:
1075 def __iter__(self): return iter([])
1076 def __contains__(self, item): return False
1077 class ColNoCont:
1078 def __iter__(self): return iter([])
1079 def __len__(self): return 0
1080 self.assertFalse(issubclass(ColNoIter, Collection))
1081 self.assertFalse(isinstance(ColNoIter(), Collection))
1082 self.assertFalse(issubclass(ColNoSize, Collection))
1083 self.assertFalse(isinstance(ColNoSize(), Collection))
1084 self.assertFalse(issubclass(ColNoCont, Collection))
1085 self.assertFalse(isinstance(ColNoCont(), Collection))
1086 # Check None blocking
1087 class SizeBlock:
1088 def __iter__(self): return iter([])
1089 def __contains__(self): return False
1090 __len__ = None
1091 class IterBlock:
1092 def __len__(self): return 0
1093 def __contains__(self): return True
1094 __iter__ = None
1095 self.assertFalse(issubclass(SizeBlock, Collection))
1096 self.assertFalse(isinstance(SizeBlock(), Collection))
1097 self.assertFalse(issubclass(IterBlock, Collection))
1098 self.assertFalse(isinstance(IterBlock(), Collection))
1099 # Check None blocking in subclass
1100 class ColImpl:
1101 def __iter__(self):
1102 return iter(list())
1103 def __len__(self):
1104 return 0
1105 def __contains__(self, item):
1106 return False
1107 class NonCol(ColImpl):
1108 __contains__ = None
1109 self.assertFalse(issubclass(NonCol, Collection))
1110 self.assertFalse(isinstance(NonCol(), Collection))
1111
1112
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001113 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001114 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001115 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001116 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001117 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001118 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001119 iter(tuple()), iter(list()), iter(dict()),
1120 iter(set()), iter(frozenset()),
1121 iter(dict().keys()), iter(dict().items()),
1122 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001123 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001124 (x for x in []),
1125 ]
1126 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001127 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001128 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001129 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1130
1131 # Issue 10565
1132 class NextOnly:
1133 def __next__(self):
1134 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001135 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001136 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001137
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001138 def test_Generator(self):
1139 class NonGen1:
1140 def __iter__(self): return self
1141 def __next__(self): return None
1142 def close(self): pass
1143 def throw(self, typ, val=None, tb=None): pass
1144
1145 class NonGen2:
1146 def __iter__(self): return self
1147 def __next__(self): return None
1148 def close(self): pass
1149 def send(self, value): return value
1150
1151 class NonGen3:
1152 def close(self): pass
1153 def send(self, value): return value
1154 def throw(self, typ, val=None, tb=None): pass
1155
1156 non_samples = [
1157 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1158 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1159 for x in non_samples:
1160 self.assertNotIsInstance(x, Generator)
1161 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1162
1163 class Gen:
1164 def __iter__(self): return self
1165 def __next__(self): return None
1166 def close(self): pass
1167 def send(self, value): return value
1168 def throw(self, typ, val=None, tb=None): pass
1169
1170 class MinimalGen(Generator):
1171 def send(self, value):
1172 return value
1173 def throw(self, typ, val=None, tb=None):
1174 super().throw(typ, val, tb)
1175
1176 def gen():
1177 yield 1
1178
1179 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1180 for x in samples:
1181 self.assertIsInstance(x, Iterator)
1182 self.assertIsInstance(x, Generator)
1183 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1184 self.validate_abstract_methods(Generator, 'send', 'throw')
1185
1186 # mixin tests
1187 mgen = MinimalGen()
1188 self.assertIs(mgen, iter(mgen))
1189 self.assertIs(mgen.send(None), next(mgen))
1190 self.assertEqual(2, mgen.send(2))
1191 self.assertIsNone(mgen.close())
1192 self.assertRaises(ValueError, mgen.throw, ValueError)
1193 self.assertRaisesRegex(ValueError, "^huhu$",
1194 mgen.throw, ValueError, ValueError("huhu"))
1195 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1196
1197 class FailOnClose(Generator):
1198 def send(self, value): return value
1199 def throw(self, *args): raise ValueError
1200
1201 self.assertRaises(ValueError, FailOnClose().close)
1202
1203 class IgnoreGeneratorExit(Generator):
1204 def send(self, value): return value
1205 def throw(self, *args): pass
1206
1207 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1208
Yury Selivanov22214ab2016-11-16 18:25:04 -05001209 def test_AsyncGenerator(self):
1210 class NonAGen1:
1211 def __aiter__(self): return self
1212 def __anext__(self): return None
1213 def aclose(self): pass
1214 def athrow(self, typ, val=None, tb=None): pass
1215
1216 class NonAGen2:
1217 def __aiter__(self): return self
1218 def __anext__(self): return None
1219 def aclose(self): pass
1220 def asend(self, value): return value
1221
1222 class NonAGen3:
1223 def aclose(self): pass
1224 def asend(self, value): return value
1225 def athrow(self, typ, val=None, tb=None): pass
1226
1227 non_samples = [
1228 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1229 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1230 for x in non_samples:
1231 self.assertNotIsInstance(x, AsyncGenerator)
1232 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1233
1234 class Gen:
1235 def __aiter__(self): return self
1236 async def __anext__(self): return None
1237 async def aclose(self): pass
1238 async def asend(self, value): return value
1239 async def athrow(self, typ, val=None, tb=None): pass
1240
1241 class MinimalAGen(AsyncGenerator):
1242 async def asend(self, value):
1243 return value
1244 async def athrow(self, typ, val=None, tb=None):
1245 await super().athrow(typ, val, tb)
1246
1247 async def gen():
1248 yield 1
1249
1250 samples = [gen(), Gen(), MinimalAGen()]
1251 for x in samples:
1252 self.assertIsInstance(x, AsyncIterator)
1253 self.assertIsInstance(x, AsyncGenerator)
1254 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1255 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1256
1257 def run_async(coro):
1258 result = None
1259 while True:
1260 try:
1261 coro.send(None)
1262 except StopIteration as ex:
1263 result = ex.args[0] if ex.args else None
1264 break
1265 return result
1266
1267 # mixin tests
1268 mgen = MinimalAGen()
1269 self.assertIs(mgen, mgen.__aiter__())
1270 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1271 self.assertEqual(2, run_async(mgen.asend(2)))
1272 self.assertIsNone(run_async(mgen.aclose()))
1273 with self.assertRaises(ValueError):
1274 run_async(mgen.athrow(ValueError))
1275
1276 class FailOnClose(AsyncGenerator):
1277 async def asend(self, value): return value
1278 async def athrow(self, *args): raise ValueError
1279
1280 with self.assertRaises(ValueError):
1281 run_async(FailOnClose().aclose())
1282
1283 class IgnoreGeneratorExit(AsyncGenerator):
1284 async def asend(self, value): return value
1285 async def athrow(self, *args): pass
1286
1287 with self.assertRaises(RuntimeError):
1288 run_async(IgnoreGeneratorExit().aclose())
1289
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001290 def test_Sized(self):
1291 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001292 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001293 (x for x in []),
1294 ]
1295 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001296 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001297 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001298 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001299 tuple(), list(), set(), frozenset(), dict(),
1300 dict().keys(), dict().items(), dict().values(),
1301 ]
1302 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001303 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001304 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001305 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001306 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001307
1308 def test_Container(self):
1309 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001310 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001311 (x for x in []),
1312 ]
1313 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001314 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001315 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001316 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001317 tuple(), list(), set(), frozenset(), dict(),
1318 dict().keys(), dict().items(),
1319 ]
1320 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001321 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001322 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001323 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001324 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001325
1326 def test_Callable(self):
1327 non_samples = [None, 42, 3.14, 1j,
1328 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001329 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001330 (x for x in []),
1331 ]
1332 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001333 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001334 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001335 samples = [lambda: None,
1336 type, int, object,
1337 len,
1338 list.append, [].append,
1339 ]
1340 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001341 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001342 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001343 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001344 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001345
1346 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001347 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001348 class C(B):
1349 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001350 self.assertTrue(issubclass(C, B))
1351 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001352
1353 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001354 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001355 class C:
1356 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001357 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001358 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001359 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001360
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001361class WithSet(MutableSet):
1362
1363 def __init__(self, it=()):
1364 self.data = set(it)
1365
1366 def __len__(self):
1367 return len(self.data)
1368
1369 def __iter__(self):
1370 return iter(self.data)
1371
1372 def __contains__(self, item):
1373 return item in self.data
1374
1375 def add(self, item):
1376 self.data.add(item)
1377
1378 def discard(self, item):
1379 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001380
Raymond Hettingerae650182009-01-28 23:33:59 +00001381class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001382
1383 # XXX For now, we only test some virtual inheritance properties.
1384 # We should also test the proper behavior of the collection ABCs
1385 # as real base classes or mix-in classes.
1386
1387 def test_Set(self):
1388 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001389 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001390 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001391 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001392 class MySet(Set):
1393 def __contains__(self, x):
1394 return False
1395 def __len__(self):
1396 return 0
1397 def __iter__(self):
1398 return iter([])
1399 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001400
Benjamin Peterson41181742008-07-02 20:22:54 +00001401 def test_hash_Set(self):
1402 class OneTwoThreeSet(Set):
1403 def __init__(self):
1404 self.contents = [1, 2, 3]
1405 def __contains__(self, x):
1406 return x in self.contents
1407 def __len__(self):
1408 return len(self.contents)
1409 def __iter__(self):
1410 return iter(self.contents)
1411 def __hash__(self):
1412 return self._hash()
1413 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001414 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001415
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001416 def test_isdisjoint_Set(self):
1417 class MySet(Set):
1418 def __init__(self, itr):
1419 self.contents = itr
1420 def __contains__(self, x):
1421 return x in self.contents
1422 def __iter__(self):
1423 return iter(self.contents)
1424 def __len__(self):
1425 return len([x for x in self.contents])
1426 s1 = MySet((1, 2, 3))
1427 s2 = MySet((4, 5, 6))
1428 s3 = MySet((1, 5, 6))
1429 self.assertTrue(s1.isdisjoint(s2))
1430 self.assertFalse(s1.isdisjoint(s3))
1431
1432 def test_equality_Set(self):
1433 class MySet(Set):
1434 def __init__(self, itr):
1435 self.contents = itr
1436 def __contains__(self, x):
1437 return x in self.contents
1438 def __iter__(self):
1439 return iter(self.contents)
1440 def __len__(self):
1441 return len([x for x in self.contents])
1442 s1 = MySet((1,))
1443 s2 = MySet((1, 2))
1444 s3 = MySet((3, 4))
1445 s4 = MySet((3, 4))
1446 self.assertTrue(s2 > s1)
1447 self.assertTrue(s1 < s2)
1448 self.assertFalse(s2 <= s1)
1449 self.assertFalse(s2 <= s3)
1450 self.assertFalse(s1 >= s2)
1451 self.assertEqual(s3, s4)
1452 self.assertNotEqual(s2, s3)
1453
1454 def test_arithmetic_Set(self):
1455 class MySet(Set):
1456 def __init__(self, itr):
1457 self.contents = itr
1458 def __contains__(self, x):
1459 return x in self.contents
1460 def __iter__(self):
1461 return iter(self.contents)
1462 def __len__(self):
1463 return len([x for x in self.contents])
1464 s1 = MySet((1, 2, 3))
1465 s2 = MySet((3, 4, 5))
1466 s3 = s1 & s2
1467 self.assertEqual(s3, MySet((3,)))
1468
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001469 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001470 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001471 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001472 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001473 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001474 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1475 'add', 'discard')
1476
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001477 def test_issue_5647(self):
1478 # MutableSet.__iand__ mutated the set during iteration
1479 s = WithSet('abcd')
1480 s &= WithSet('cdef') # This used to fail
1481 self.assertEqual(set(s), set('cd'))
1482
Raymond Hettingerae650182009-01-28 23:33:59 +00001483 def test_issue_4920(self):
1484 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001485 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001486 __slots__=['__s']
1487 def __init__(self,items=None):
1488 if items is None:
1489 items=[]
1490 self.__s=set(items)
1491 def __contains__(self,v):
1492 return v in self.__s
1493 def __iter__(self):
1494 return iter(self.__s)
1495 def __len__(self):
1496 return len(self.__s)
1497 def add(self,v):
1498 result=v not in self.__s
1499 self.__s.add(v)
1500 return result
1501 def discard(self,v):
1502 result=v in self.__s
1503 self.__s.discard(v)
1504 return result
1505 def __repr__(self):
1506 return "MySet(%s)" % repr(list(self))
1507 s = MySet([5,43,2,1])
1508 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001509
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001510 def test_issue8750(self):
1511 empty = WithSet()
1512 full = WithSet(range(10))
1513 s = WithSet(full)
1514 s -= s
1515 self.assertEqual(s, empty)
1516 s = WithSet(full)
1517 s ^= s
1518 self.assertEqual(s, empty)
1519 s = WithSet(full)
1520 s &= s
1521 self.assertEqual(s, full)
1522 s |= s
1523 self.assertEqual(s, full)
1524
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001525 def test_issue16373(self):
1526 # Recursion error comparing comparable and noncomparable
1527 # Set instances
1528 class MyComparableSet(Set):
1529 def __contains__(self, x):
1530 return False
1531 def __len__(self):
1532 return 0
1533 def __iter__(self):
1534 return iter([])
1535 class MyNonComparableSet(Set):
1536 def __contains__(self, x):
1537 return False
1538 def __len__(self):
1539 return 0
1540 def __iter__(self):
1541 return iter([])
1542 def __le__(self, x):
1543 return NotImplemented
1544 def __lt__(self, x):
1545 return NotImplemented
1546
1547 cs = MyComparableSet()
1548 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001549 self.assertFalse(ncs < cs)
1550 self.assertTrue(ncs <= cs)
1551 self.assertFalse(ncs > cs)
1552 self.assertTrue(ncs >= cs)
1553
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001554 def test_issue26915(self):
1555 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001556 class CustomSequence(Sequence):
1557 def __init__(self, seq):
1558 self._seq = seq
1559 def __getitem__(self, index):
1560 return self._seq[index]
1561 def __len__(self):
1562 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001563
1564 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001565 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001566 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001567 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001568 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001569 ItemsView({1: nan, 2: obj}),
1570 ValuesView({1: nan, 2: obj})
1571 ]
1572 for container in containers:
1573 for elem in container:
1574 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001575 self.assertEqual(seq.index(nan), 0)
1576 self.assertEqual(seq.index(obj), 1)
1577 self.assertEqual(seq.count(nan), 2)
1578 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001579
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001580 def assertSameSet(self, s1, s2):
1581 # coerce both to a real set then check equality
1582 self.assertSetEqual(set(s1), set(s2))
1583
Richard Levasseur68f68fa2020-11-21 11:56:24 -08001584 def test_Set_from_iterable(self):
1585 """Verify _from_iterable overriden to an instance method works."""
1586 class SetUsingInstanceFromIterable(MutableSet):
1587 def __init__(self, values, created_by):
1588 if not created_by:
1589 raise ValueError(f'created_by must be specified')
1590 self.created_by = created_by
1591 self._values = set(values)
1592
1593 def _from_iterable(self, values):
1594 return type(self)(values, 'from_iterable')
1595
1596 def __contains__(self, value):
1597 return value in self._values
1598
1599 def __iter__(self):
1600 yield from self._values
1601
1602 def __len__(self):
1603 return len(self._values)
1604
1605 def add(self, value):
1606 self._values.add(value)
1607
1608 def discard(self, value):
1609 self._values.discard(value)
1610
1611 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
1612
1613 actual = impl - {1}
1614 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1615 self.assertEqual('from_iterable', actual.created_by)
1616 self.assertEqual({2, 3}, actual)
1617
1618 actual = impl | {4}
1619 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1620 self.assertEqual('from_iterable', actual.created_by)
1621 self.assertEqual({1, 2, 3, 4}, actual)
1622
1623 actual = impl & {2}
1624 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1625 self.assertEqual('from_iterable', actual.created_by)
1626 self.assertEqual({2}, actual)
1627
1628 actual = impl ^ {3, 4}
1629 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1630 self.assertEqual('from_iterable', actual.created_by)
1631 self.assertEqual({1, 2, 4}, actual)
1632
1633 # NOTE: ixor'ing with a list is important here: internally, __ixor__
1634 # only calls _from_iterable if the other value isn't already a Set.
1635 impl ^= [3, 4]
1636 self.assertIsInstance(impl, SetUsingInstanceFromIterable)
1637 self.assertEqual('test', impl.created_by)
1638 self.assertEqual({1, 2, 4}, impl)
1639
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001640 def test_Set_interoperability_with_real_sets(self):
1641 # Issue: 8743
1642 class ListSet(Set):
1643 def __init__(self, elements=()):
1644 self.data = []
1645 for elem in elements:
1646 if elem not in self.data:
1647 self.data.append(elem)
1648 def __contains__(self, elem):
1649 return elem in self.data
1650 def __iter__(self):
1651 return iter(self.data)
1652 def __len__(self):
1653 return len(self.data)
1654 def __repr__(self):
1655 return 'Set({!r})'.format(self.data)
1656
1657 r1 = set('abc')
1658 r2 = set('bcd')
1659 r3 = set('abcde')
1660 f1 = ListSet('abc')
1661 f2 = ListSet('bcd')
1662 f3 = ListSet('abcde')
1663 l1 = list('abccba')
1664 l2 = list('bcddcb')
1665 l3 = list('abcdeedcba')
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 target = r1 | r2
1674 self.assertSameSet(f1 | f2, target)
1675 self.assertSameSet(f1 | r2, target)
1676 self.assertSameSet(r2 | f1, target)
1677 self.assertSameSet(f1 | l2, target)
1678
1679 fwd_target = r1 - r2
1680 rev_target = r2 - r1
1681 self.assertSameSet(f1 - f2, fwd_target)
1682 self.assertSameSet(f2 - f1, rev_target)
1683 self.assertSameSet(f1 - r2, fwd_target)
1684 self.assertSameSet(f2 - r1, rev_target)
1685 self.assertSameSet(r1 - f2, fwd_target)
1686 self.assertSameSet(r2 - f1, rev_target)
1687 self.assertSameSet(f1 - l2, fwd_target)
1688 self.assertSameSet(f2 - l1, rev_target)
1689
1690 target = r1 ^ r2
1691 self.assertSameSet(f1 ^ f2, target)
1692 self.assertSameSet(f1 ^ r2, target)
1693 self.assertSameSet(r2 ^ f1, target)
1694 self.assertSameSet(f1 ^ l2, target)
1695
1696 # Don't change the following to use assertLess or other
1697 # "more specific" unittest assertions. The current
1698 # assertTrue/assertFalse style makes the pattern of test
1699 # case combinations clear and allows us to know for sure
1700 # the exact operator being invoked.
1701
1702 # proper subset
1703 self.assertTrue(f1 < f3)
1704 self.assertFalse(f1 < f1)
1705 self.assertFalse(f1 < f2)
1706 self.assertTrue(r1 < f3)
1707 self.assertFalse(r1 < f1)
1708 self.assertFalse(r1 < f2)
1709 self.assertTrue(r1 < r3)
1710 self.assertFalse(r1 < r1)
1711 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001712 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001713 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001714 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001715 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001716 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001717 f1 < l2
1718
1719 # any subset
1720 self.assertTrue(f1 <= f3)
1721 self.assertTrue(f1 <= f1)
1722 self.assertFalse(f1 <= f2)
1723 self.assertTrue(r1 <= f3)
1724 self.assertTrue(r1 <= f1)
1725 self.assertFalse(r1 <= f2)
1726 self.assertTrue(r1 <= r3)
1727 self.assertTrue(r1 <= r1)
1728 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001729 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001730 f1 <= l3
1731 with self.assertRaises(TypeError):
1732 f1 <= l1
1733 with self.assertRaises(TypeError):
1734 f1 <= l2
1735
1736 # proper superset
1737 self.assertTrue(f3 > f1)
1738 self.assertFalse(f1 > f1)
1739 self.assertFalse(f2 > f1)
1740 self.assertTrue(r3 > r1)
1741 self.assertFalse(f1 > r1)
1742 self.assertFalse(f2 > r1)
1743 self.assertTrue(r3 > r1)
1744 self.assertFalse(r1 > r1)
1745 self.assertFalse(r2 > r1)
1746 with self.assertRaises(TypeError):
1747 f1 > l3
1748 with self.assertRaises(TypeError):
1749 f1 > l1
1750 with self.assertRaises(TypeError):
1751 f1 > l2
1752
1753 # any superset
1754 self.assertTrue(f3 >= f1)
1755 self.assertTrue(f1 >= f1)
1756 self.assertFalse(f2 >= f1)
1757 self.assertTrue(r3 >= r1)
1758 self.assertTrue(f1 >= r1)
1759 self.assertFalse(f2 >= r1)
1760 self.assertTrue(r3 >= r1)
1761 self.assertTrue(r1 >= r1)
1762 self.assertFalse(r2 >= r1)
1763 with self.assertRaises(TypeError):
1764 f1 >= l3
1765 with self.assertRaises(TypeError):
1766 f1 >=l1
1767 with self.assertRaises(TypeError):
1768 f1 >= l2
1769
1770 # equality
1771 self.assertTrue(f1 == f1)
1772 self.assertTrue(r1 == f1)
1773 self.assertTrue(f1 == r1)
1774 self.assertFalse(f1 == f3)
1775 self.assertFalse(r1 == f3)
1776 self.assertFalse(f1 == r3)
1777 self.assertFalse(f1 == l3)
1778 self.assertFalse(f1 == l1)
1779 self.assertFalse(f1 == l2)
1780
1781 # inequality
1782 self.assertFalse(f1 != f1)
1783 self.assertFalse(r1 != f1)
1784 self.assertFalse(f1 != r1)
1785 self.assertTrue(f1 != f3)
1786 self.assertTrue(r1 != f3)
1787 self.assertTrue(f1 != r3)
1788 self.assertTrue(f1 != l3)
1789 self.assertTrue(f1 != l1)
1790 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001791
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001792 def test_Mapping(self):
1793 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001794 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001795 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001796 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1797 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001798 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001799 def __len__(self):
1800 return 0
1801 def __getitem__(self, i):
1802 raise IndexError
1803 def __iter__(self):
1804 return iter(())
1805 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001806 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001807
1808 def test_MutableMapping(self):
1809 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001810 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001811 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001812 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1813 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001814
Raymond Hettinger9117c752010-08-22 07:44:24 +00001815 def test_MutableMapping_subclass(self):
1816 # Test issue 9214
1817 mymap = UserDict()
1818 mymap['red'] = 5
1819 self.assertIsInstance(mymap.keys(), Set)
1820 self.assertIsInstance(mymap.keys(), KeysView)
1821 self.assertIsInstance(mymap.items(), Set)
1822 self.assertIsInstance(mymap.items(), ItemsView)
1823
1824 mymap = UserDict()
1825 mymap['red'] = 5
1826 z = mymap.keys() | {'orange'}
1827 self.assertIsInstance(z, set)
1828 list(z)
1829 mymap['blue'] = 7 # Shouldn't affect 'z'
1830 self.assertEqual(sorted(z), ['orange', 'red'])
1831
1832 mymap = UserDict()
1833 mymap['red'] = 5
1834 z = mymap.items() | {('orange', 3)}
1835 self.assertIsInstance(z, set)
1836 list(z)
1837 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001838 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001839
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001840 def test_Sequence(self):
1841 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001842 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001843 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001844 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001845 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001846 self.assertIsInstance(memoryview(b""), Sequence)
1847 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001848 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001849 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1850 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001851
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001852 def test_Sequence_mixins(self):
1853 class SequenceSubclass(Sequence):
1854 def __init__(self, seq=()):
1855 self.seq = seq
1856
1857 def __getitem__(self, index):
1858 return self.seq[index]
1859
1860 def __len__(self):
1861 return len(self.seq)
1862
1863 # Compare Sequence.index() behavior to (list|str).index() behavior
1864 def assert_index_same(seq1, seq2, index_args):
1865 try:
1866 expected = seq1.index(*index_args)
1867 except ValueError:
1868 with self.assertRaises(ValueError):
1869 seq2.index(*index_args)
1870 else:
1871 actual = seq2.index(*index_args)
1872 self.assertEqual(
1873 actual, expected, '%r.index%s' % (seq1, index_args))
1874
1875 for ty in list, str:
1876 nativeseq = ty('abracadabra')
1877 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1878 seqseq = SequenceSubclass(nativeseq)
1879 for letter in set(nativeseq) | {'z'}:
1880 assert_index_same(nativeseq, seqseq, (letter,))
1881 for start in range(-3, len(nativeseq) + 3):
1882 assert_index_same(nativeseq, seqseq, (letter, start))
1883 for stop in range(-3, len(nativeseq) + 3):
1884 assert_index_same(
1885 nativeseq, seqseq, (letter, start, stop))
1886
Guido van Rossumd05eb002007-11-21 22:26:24 +00001887 def test_ByteString(self):
1888 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001889 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001890 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001891 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001892 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001893 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001894 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001895 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001896
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001897 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001898 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001899 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001900 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001901 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001902 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001903 self.assertTrue(issubclass(sample, MutableSequence))
1904 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001905 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1906 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001907
Eli Bendersky0716a572011-03-04 10:38:14 +00001908 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001909 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001910 # class inherited from it.
1911 class MutableSequenceSubclass(MutableSequence):
1912 def __init__(self):
1913 self.lst = []
1914
1915 def __setitem__(self, index, value):
1916 self.lst[index] = value
1917
1918 def __getitem__(self, index):
1919 return self.lst[index]
1920
1921 def __len__(self):
1922 return len(self.lst)
1923
1924 def __delitem__(self, index):
1925 del self.lst[index]
1926
1927 def insert(self, index, value):
1928 self.lst.insert(index, value)
1929
1930 mss = MutableSequenceSubclass()
1931 mss.append(0)
1932 mss.extend((1, 2, 3, 4))
1933 self.assertEqual(len(mss), 5)
1934 self.assertEqual(mss[3], 3)
1935 mss.reverse()
1936 self.assertEqual(mss[3], 1)
1937 mss.pop()
1938 self.assertEqual(len(mss), 4)
1939 mss.remove(3)
1940 self.assertEqual(len(mss), 3)
1941 mss += (10, 20, 30)
1942 self.assertEqual(len(mss), 6)
1943 self.assertEqual(mss[-1], 30)
1944 mss.clear()
1945 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001946
Naris R1b5f9c92018-08-31 02:56:14 +10001947 # issue 34427
1948 # extending self should not cause infinite loop
1949 items = 'ABCD'
1950 mss2 = MutableSequenceSubclass()
1951 mss2.extend(items + items)
1952 mss.clear()
1953 mss.extend(items)
1954 mss.extend(mss)
1955 self.assertEqual(len(mss), len(mss2))
1956 self.assertEqual(list(mss), list(mss2))
1957
1958
Raymond Hettinger499e1932011-02-23 07:56:53 +00001959################################################################################
1960### Counter
1961################################################################################
1962
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001963class CounterSubclassWithSetItem(Counter):
1964 # Test a counter subclass that overrides __setitem__
1965 def __init__(self, *args, **kwds):
1966 self.called = False
1967 Counter.__init__(self, *args, **kwds)
1968 def __setitem__(self, key, value):
1969 self.called = True
1970 Counter.__setitem__(self, key, value)
1971
1972class CounterSubclassWithGet(Counter):
1973 # Test a counter subclass that overrides get()
1974 def __init__(self, *args, **kwds):
1975 self.called = False
1976 Counter.__init__(self, *args, **kwds)
1977 def get(self, key, default):
1978 self.called = True
1979 return Counter.get(self, key, default)
1980
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001981class TestCounter(unittest.TestCase):
1982
1983 def test_basics(self):
1984 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001985 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1986 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001987 self.assertIsInstance(c, dict)
1988 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001989 self.assertTrue(issubclass(Counter, dict))
1990 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001991 self.assertEqual(len(c), 3)
1992 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001993 self.assertEqual(list(c.values()), [3, 2, 1])
1994 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1995 self.assertEqual(list(c), ['a', 'b', 'c'])
1996 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001997 [('a', 3), ('b', 2), ('c', 1)])
1998 self.assertEqual(c['b'], 2)
1999 self.assertEqual(c['z'], 0)
2000 self.assertEqual(c.__contains__('c'), True)
2001 self.assertEqual(c.__contains__('z'), False)
2002 self.assertEqual(c.get('b', 10), 2)
2003 self.assertEqual(c.get('z', 10), 10)
2004 self.assertEqual(c, dict(a=3, b=2, c=1))
2005 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
2006 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
2007 for i in range(5):
2008 self.assertEqual(c.most_common(i),
2009 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002010 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002011 c['a'] += 1 # increment an existing value
2012 c['b'] -= 2 # sub existing value to zero
2013 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002014 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002015 c['d'] -= 2 # sub from a missing value
2016 c['e'] = -5 # directly assign a missing value
2017 c['f'] += 4 # add to a missing value
2018 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002019 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002020 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002021 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002022 for i in range(3):
2023 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002024 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002025 c.clear()
2026 self.assertEqual(c, {})
2027 self.assertEqual(repr(c), 'Counter()')
2028 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
2029 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002030 c.update(dict(a=5, b=3))
2031 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002032 c.update(Counter('a' * 50 + 'b' * 30))
2033 c.update() # test case with no args
2034 c.__init__('a' * 500 + 'b' * 300)
2035 c.__init__('cdc')
2036 c.__init__()
2037 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
2038 self.assertEqual(c.setdefault('d', 5), 1)
2039 self.assertEqual(c['d'], 1)
2040 self.assertEqual(c.setdefault('e', 5), 5)
2041 self.assertEqual(c['e'], 5)
2042
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002043 def test_init(self):
2044 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
2045 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
2046 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
2047 self.assertRaises(TypeError, Counter, 42)
2048 self.assertRaises(TypeError, Counter, (), ())
2049 self.assertRaises(TypeError, Counter.__init__)
2050
Raymond Hettinger407c7342019-02-21 09:19:00 -08002051 def test_order_preservation(self):
2052 # Input order dictates items() order
2053 self.assertEqual(list(Counter('abracadabra').items()),
2054 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
2055 # letters with same count: ^----------^ ^---------^
2056
2057 # Verify retention of order even when all counts are equal
2058 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
2059 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
2060
2061 # Input order dictates elements() order
2062 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
2063 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
2064 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
2065
2066 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10002067 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08002068 ps = 'aaabbcdddeefggghhijjjkkl'
2069 qs = 'abbcccdeefffhkkllllmmnno'
2070 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
2071 def correctly_ordered(seq):
2072 'Return true if the letters occur in the expected order'
2073 positions = [order[letter] for letter in seq]
2074 return positions == sorted(positions)
2075
2076 p, q = Counter(ps), Counter(qs)
2077 self.assertTrue(correctly_ordered(+p))
2078 self.assertTrue(correctly_ordered(-p))
2079 self.assertTrue(correctly_ordered(p + q))
2080 self.assertTrue(correctly_ordered(p - q))
2081 self.assertTrue(correctly_ordered(p | q))
2082 self.assertTrue(correctly_ordered(p & q))
2083
2084 p, q = Counter(ps), Counter(qs)
2085 p += q
2086 self.assertTrue(correctly_ordered(p))
2087
2088 p, q = Counter(ps), Counter(qs)
2089 p -= q
2090 self.assertTrue(correctly_ordered(p))
2091
2092 p, q = Counter(ps), Counter(qs)
2093 p |= q
2094 self.assertTrue(correctly_ordered(p))
2095
2096 p, q = Counter(ps), Counter(qs)
2097 p &= q
2098 self.assertTrue(correctly_ordered(p))
2099
2100 p, q = Counter(ps), Counter(qs)
2101 p.update(q)
2102 self.assertTrue(correctly_ordered(p))
2103
2104 p, q = Counter(ps), Counter(qs)
2105 p.subtract(q)
2106 self.assertTrue(correctly_ordered(p))
2107
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002108 def test_update(self):
2109 c = Counter()
2110 c.update(self=42)
2111 self.assertEqual(list(c.items()), [('self', 42)])
2112 c = Counter()
2113 c.update(iterable=42)
2114 self.assertEqual(list(c.items()), [('iterable', 42)])
2115 c = Counter()
2116 c.update(iterable=None)
2117 self.assertEqual(list(c.items()), [('iterable', None)])
2118 self.assertRaises(TypeError, Counter().update, 42)
2119 self.assertRaises(TypeError, Counter().update, {}, {})
2120 self.assertRaises(TypeError, Counter.update)
2121
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002122 def test_copying(self):
2123 # Check that counters are copyable, deepcopyable, picklable, and
2124 #have a repr/eval round-trip
2125 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002126 def check(dup):
2127 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2128 self.assertIsNot(dup, words, msg)
2129 self.assertEqual(dup, words)
2130 check(words.copy())
2131 check(copy.copy(words))
2132 check(copy.deepcopy(words))
2133 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2134 with self.subTest(proto=proto):
2135 check(pickle.loads(pickle.dumps(words, proto)))
2136 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002137 update_test = Counter()
2138 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002139 check(update_test)
2140 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002141
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002142 def test_copy_subclass(self):
2143 class MyCounter(Counter):
2144 pass
2145 c = MyCounter('slartibartfast')
2146 d = c.copy()
2147 self.assertEqual(d, c)
2148 self.assertEqual(len(d), len(c))
2149 self.assertEqual(type(d), type(c))
2150
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002151 def test_conversions(self):
2152 # Convert to: set, list, dict
2153 s = 'she sells sea shells by the sea shore'
2154 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2155 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2156 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2157 self.assertEqual(set(Counter(s)), set(s))
2158
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002159 def test_invariant_for_the_in_operator(self):
2160 c = Counter(a=10, b=-2, c=0)
2161 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002162 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002163 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002164
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002165 def test_multiset_operations(self):
2166 # Verify that adding a zero counter will strip zeros and negatives
2167 c = Counter(a=10, b=-2, c=0) + Counter()
2168 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002169
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002170 elements = 'abcd'
2171 for i in range(1000):
2172 # test random pairs of multisets
2173 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002174 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002175 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002176 q.update(h=1, i=-1, j=0)
2177 for counterop, numberop in [
2178 (Counter.__add__, lambda x, y: max(0, x+y)),
2179 (Counter.__sub__, lambda x, y: max(0, x-y)),
2180 (Counter.__or__, lambda x, y: max(0,x,y)),
2181 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002182 ]:
2183 result = counterop(p, q)
2184 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002185 self.assertEqual(numberop(p[x], q[x]), result[x],
2186 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002187 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002188 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002189
2190 elements = 'abcdef'
2191 for i in range(100):
2192 # verify that random multisets with no repeats are exactly like sets
2193 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2194 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2195 for counterop, setop in [
2196 (Counter.__sub__, set.__sub__),
2197 (Counter.__or__, set.__or__),
2198 (Counter.__and__, set.__and__),
2199 ]:
2200 counter_result = counterop(p, q)
2201 set_result = setop(set(p.elements()), set(q.elements()))
2202 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002203
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002204 def test_inplace_operations(self):
2205 elements = 'abcd'
2206 for i in range(1000):
2207 # test random pairs of multisets
2208 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2209 p.update(e=1, f=-1, g=0)
2210 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2211 q.update(h=1, i=-1, j=0)
2212 for inplace_op, regular_op in [
2213 (Counter.__iadd__, Counter.__add__),
2214 (Counter.__isub__, Counter.__sub__),
2215 (Counter.__ior__, Counter.__or__),
2216 (Counter.__iand__, Counter.__and__),
2217 ]:
2218 c = p.copy()
2219 c_id = id(c)
2220 regular_result = regular_op(c, q)
2221 inplace_result = inplace_op(c, q)
2222 self.assertEqual(inplace_result, regular_result)
2223 self.assertEqual(id(inplace_result), c_id)
2224
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002225 def test_subtract(self):
2226 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2227 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2228 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2229 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2230 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2231 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2232 c = Counter('aaabbcd')
2233 c.subtract('aaaabbcce')
2234 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002235
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002236 c = Counter()
2237 c.subtract(self=42)
2238 self.assertEqual(list(c.items()), [('self', -42)])
2239 c = Counter()
2240 c.subtract(iterable=42)
2241 self.assertEqual(list(c.items()), [('iterable', -42)])
2242 self.assertRaises(TypeError, Counter().subtract, 42)
2243 self.assertRaises(TypeError, Counter().subtract, {}, {})
2244 self.assertRaises(TypeError, Counter.subtract)
2245
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002246 def test_unary(self):
2247 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2248 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2249 self.assertEqual(dict(-c), dict(a=5))
2250
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002251 def test_repr_nonsortable(self):
2252 c = Counter(a=2, b=None)
2253 r = repr(c)
2254 self.assertIn("'a': 2", r)
2255 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002256
Raymond Hettinger426e0522011-01-03 02:12:02 +00002257 def test_helper_function(self):
2258 # two paths, one for real dicts and one for other mappings
2259 elems = list('abracadabra')
2260
2261 d = dict()
2262 _count_elements(d, elems)
2263 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2264
2265 m = OrderedDict()
2266 _count_elements(m, elems)
2267 self.assertEqual(m,
2268 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2269
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002270 # test fidelity to the pure python version
2271 c = CounterSubclassWithSetItem('abracadabra')
2272 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002273 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002274 c = CounterSubclassWithGet('abracadabra')
2275 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002276 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002277
Raymond Hettinger60398512020-05-28 08:35:46 -07002278 def test_multiset_operations_equivalent_to_set_operations(self):
2279 # When the multiplicities are all zero or one, multiset operations
2280 # are guaranteed to be equivalent to the corresponding operations
2281 # for regular sets.
2282 s = list(product(('a', 'b', 'c'), range(2)))
2283 powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
2284 counters = [Counter(dict(groups)) for groups in powerset]
2285 for cp, cq in product(counters, repeat=2):
2286 sp = set(cp.elements())
2287 sq = set(cq.elements())
2288 self.assertEqual(set(cp + cq), sp | sq)
2289 self.assertEqual(set(cp - cq), sp - sq)
2290 self.assertEqual(set(cp | cq), sp | sq)
2291 self.assertEqual(set(cp & cq), sp & sq)
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002292 self.assertEqual(cp == cq, sp == sq)
2293 self.assertEqual(cp != cq, sp != sq)
2294 self.assertEqual(cp <= cq, sp <= sq)
2295 self.assertEqual(cp >= cq, sp >= sq)
2296 self.assertEqual(cp < cq, sp < sq)
2297 self.assertEqual(cp > cq, sp > sq)
Raymond Hettinger60398512020-05-28 08:35:46 -07002298
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002299 def test_eq(self):
2300 self.assertEqual(Counter(a=3, b=2, c=0), Counter('ababa'))
2301 self.assertNotEqual(Counter(a=3, b=2), Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002302
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002303 def test_le(self):
2304 self.assertTrue(Counter(a=3, b=2, c=0) <= Counter('ababa'))
2305 self.assertFalse(Counter(a=3, b=2) <= Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002306
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002307 def test_lt(self):
2308 self.assertTrue(Counter(a=3, b=1, c=0) < Counter('ababa'))
2309 self.assertFalse(Counter(a=3, b=2, c=0) < Counter('ababa'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002310
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002311 def test_ge(self):
2312 self.assertTrue(Counter(a=2, b=1, c=0) >= Counter('aab'))
2313 self.assertFalse(Counter(a=3, b=2, c=0) >= Counter('aabd'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002314
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002315 def test_gt(self):
2316 self.assertTrue(Counter(a=3, b=2, c=0) > Counter('aab'))
2317 self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002318
Raymond Hettinger499e1932011-02-23 07:56:53 +00002319
2320################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002321### Run tests
2322################################################################################
2323
Guido van Rossumd8faa362007-04-27 19:54:29 +00002324def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002325 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002326 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002327 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002328 TestUserObjects,
2329 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002330 support.run_unittest(*test_classes)
2331 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002332
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002333
Guido van Rossumd8faa362007-04-27 19:54:29 +00002334if __name__ == "__main__":
2335 test_main(verbose=True)