blob: 30303f00ba5c1753e5c2c27dd4daecad88583960 [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
Kamil Turek9923df92021-03-14 04:15:44 +0100252 c = ChainMap({'a': 1, 'b': 2})
253 d = c.new_child(b=20, c=30)
254 self.assertEqual(d.maps, [{'b': 20, 'c': 30}, {'a': 1, 'b': 2}])
255
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700256 def test_union_operators(self):
257 cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
258 cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
259 cm3 = cm1.copy()
260 d = dict(a=10, c=30)
261 pairs = [('c', 3), ('p',0)]
262
263 tmp = cm1 | cm2 # testing between chainmaps
264 self.assertEqual(tmp.maps, [cm1.maps[0] | dict(cm2), *cm1.maps[1:]])
265 cm1 |= cm2
266 self.assertEqual(tmp, cm1)
267
268 tmp = cm2 | d # testing between chainmap and mapping
269 self.assertEqual(tmp.maps, [cm2.maps[0] | d, *cm2.maps[1:]])
270 self.assertEqual((d | cm2).maps, [d | dict(cm2)])
271 cm2 |= d
272 self.assertEqual(tmp, cm2)
273
274 # testing behavior between chainmap and iterable key-value pairs
275 with self.assertRaises(TypeError):
276 cm3 | pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700277 tmp = cm3.copy()
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700278 cm3 |= pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700279 self.assertEqual(cm3.maps, [tmp.maps[0] | dict(pairs), *tmp.maps[1:]])
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700280
281 # testing proper return types for ChainMap and it's subclasses
282 class Subclass(ChainMap):
283 pass
284
285 class SubclassRor(ChainMap):
286 def __ror__(self, other):
287 return super().__ror__(other)
288
289 tmp = ChainMap() | ChainMap()
290 self.assertIs(type(tmp), ChainMap)
291 self.assertIs(type(tmp.maps[0]), dict)
292 tmp = ChainMap() | Subclass()
293 self.assertIs(type(tmp), ChainMap)
294 self.assertIs(type(tmp.maps[0]), dict)
295 tmp = Subclass() | ChainMap()
296 self.assertIs(type(tmp), Subclass)
297 self.assertIs(type(tmp.maps[0]), dict)
298 tmp = ChainMap() | SubclassRor()
299 self.assertIs(type(tmp), SubclassRor)
300 self.assertIs(type(tmp.maps[0]), dict)
301
Raymond Hettinger499e1932011-02-23 07:56:53 +0000302
303################################################################################
304### Named Tuples
305################################################################################
306
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000307TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000308
309class TestNamedTuple(unittest.TestCase):
310
311 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000312 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000313 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000314 self.assertEqual(Point.__slots__, ())
315 self.assertEqual(Point.__module__, __name__)
316 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000317 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000318
319 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
320 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
321 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
322
323 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
324 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
325 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000326 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000327 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
328
329 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000330 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000331
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000332 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000333 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000334 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000335 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000336
Christian Heimesfaf2f632008-01-06 16:59:19 +0000337 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
338 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
339
Raymond Hettinger39482072018-01-10 21:45:19 -0800340 def test_defaults(self):
341 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700342 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800343 self.assertEqual(Point(1, 2), (1, 2))
344 self.assertEqual(Point(1), (1, 20))
345 self.assertEqual(Point(), (10, 20))
346
347 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700348 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800349 self.assertEqual(Point(1, 2), (1, 2))
350 self.assertEqual(Point(1), (1, 20))
351
352 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700353 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800354 self.assertEqual(Point(1, 2), (1, 2))
355 with self.assertRaises(TypeError):
356 Point(1)
357
358 with self.assertRaises(TypeError): # catch too few args
359 Point()
360 with self.assertRaises(TypeError): # catch too many args
361 Point(1, 2, 3)
362 with self.assertRaises(TypeError): # too many defaults
363 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
364 with self.assertRaises(TypeError): # non-iterable defaults
365 Point = namedtuple('Point', 'x y', defaults=10)
366 with self.assertRaises(TypeError): # another non-iterable default
367 Point = namedtuple('Point', 'x y', defaults=False)
368
369 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700370 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800371 self.assertIsNone(Point.__new__.__defaults__, None)
372 self.assertEqual(Point(10, 20), (10, 20))
373 with self.assertRaises(TypeError): # catch too few args
374 Point(10)
375
376 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700377 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800378 self.assertEqual(Point.__new__.__defaults__, (10, 20))
379 self.assertEqual(Point(1, 2), (1, 2))
380 self.assertEqual(Point(1), (1, 20))
381 self.assertEqual(Point(), (10, 20))
382
383 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700384 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800385 self.assertEqual(Point.__new__.__defaults__, (10, 20))
386 self.assertEqual(Point(1, 2), (1, 2))
387 self.assertEqual(Point(1), (1, 20))
388 self.assertEqual(Point(), (10, 20))
389
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200390 def test_readonly(self):
391 Point = namedtuple('Point', 'x y')
392 p = Point(11, 22)
393 with self.assertRaises(AttributeError):
394 p.x = 33
395 with self.assertRaises(AttributeError):
396 del p.x
397 with self.assertRaises(TypeError):
398 p[0] = 33
399 with self.assertRaises(TypeError):
400 del p[0]
401 self.assertEqual(p.x, 11)
402 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800403
R. David Murray378c0cf2010-02-24 01:46:21 +0000404 @unittest.skipIf(sys.flags.optimize >= 2,
405 "Docstrings are omitted with -O2 and above")
406 def test_factory_doc_attr(self):
407 Point = namedtuple('Point', 'x y')
408 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200409 Point.__doc__ = '2D point'
410 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000411
Raymond Hettingereac503a2015-05-13 01:09:59 -0700412 @unittest.skipIf(sys.flags.optimize >= 2,
413 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200414 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700415 Point = namedtuple('Point', 'x y')
416 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200417 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700418 Point.x.__doc__ = 'docstring for Point.x'
419 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200420 # namedtuple can mutate doc of descriptors independently
421 Vector = namedtuple('Vector', 'x y')
422 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
423 Vector.x.__doc__ = 'docstring for Vector.x'
424 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
425
426 @support.cpython_only
427 @unittest.skipIf(sys.flags.optimize >= 2,
428 "Docstrings are omitted with -O2 and above")
429 def test_field_doc_reuse(self):
430 P = namedtuple('P', ['m', 'n'])
431 Q = namedtuple('Q', ['o', 'p'])
432 self.assertIs(P.m.__doc__, Q.o.__doc__)
433 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700434
Ammar Askara86b5222020-04-14 23:36:08 -0700435 @support.cpython_only
436 def test_field_repr(self):
437 Point = namedtuple('Point', 'x y')
438 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'Alias for field number 0')")
439 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'Alias for field number 1')")
440
441 Point.x.__doc__ = 'The x-coordinate'
442 Point.y.__doc__ = 'The y-coordinate'
443
444 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'The x-coordinate')")
445 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'The y-coordinate')")
446
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000447 def test_name_fixer(self):
448 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000449 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
450 [('abc', 'class'), ('abc', '_1')], # field has keyword
451 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
452 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
453 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
454 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000455 ]:
456 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
457
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700458 def test_module_parameter(self):
459 NT = namedtuple('NT', ['x', 'y'], module=collections)
460 self.assertEqual(NT.__module__, collections)
461
Guido van Rossumd8faa362007-04-27 19:54:29 +0000462 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000463 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000464 p = Point(11, 22)
465 self.assertEqual(p, Point(x=11, y=22))
466 self.assertEqual(p, Point(11, y=22))
467 self.assertEqual(p, Point(y=22, x=11))
468 self.assertEqual(p, Point(*(11, 22)))
469 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200470 self.assertRaises(TypeError, Point, 1) # too few args
471 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
472 with self.assertRaises(TypeError): # wrong keyword argument
473 Point(XXX=1, y=2)
474 with self.assertRaises(TypeError): # missing keyword argument
475 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000476 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000477 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200478 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
479 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
480 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
481 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000482
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000483 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000484 p._replace(x=1, error=2)
485 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000486 pass
487 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000488 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000489
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000490 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000491 Point = namedtuple('Point', 'x, y')
492 p = Point(x=11, y=22)
493 self.assertEqual(repr(p), 'Point(x=11, y=22)')
494
495 # verify that fieldspec can be a non-string sequence
496 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000497 p = Point(x=11, y=22)
498 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000499
500 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000501 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000502 p = Point(11, 22)
503
Ezio Melottie9615932010-01-24 19:26:24 +0000504 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000505 self.assertEqual(p, (11, 22)) # matches a real tuple
Min ho Kimc4cacc82019-07-31 08:16:13 +1000506 self.assertEqual(tuple(p), (11, 22)) # coercible to a real tuple
507 self.assertEqual(list(p), [11, 22]) # coercible to a list
Guido van Rossumd8faa362007-04-27 19:54:29 +0000508 self.assertEqual(max(p), 22) # iterable
509 self.assertEqual(max(*p), 22) # star-able
510 x, y = p
511 self.assertEqual(p, (x, y)) # unpacks like a tuple
512 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200513 with self.assertRaises(IndexError):
514 p[3]
515 self.assertEqual(p[-1], 22)
516 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000517
518 self.assertEqual(p.x, x)
519 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200520 with self.assertRaises(AttributeError):
521 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000522
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000523 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000524 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000525 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000526 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000527 self.assertEqual(repr(Zero()), 'Zero()')
528 self.assertEqual(Zero()._asdict(), {})
529 self.assertEqual(Zero()._fields, ())
530
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000531 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000532 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000533 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000534 self.assertEqual(Dot(1).d, 1)
535 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
536 self.assertEqual(Dot(1)._asdict(), {'d':1})
537 self.assertEqual(Dot(1)._replace(d=999), (999,))
538 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000539
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200540 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200541 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000542 for j in range(10)]) for i in range(n)))
543 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000544 Big = namedtuple('Big', names)
545 b = Big(*range(n))
546 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000547 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000548 for pos, name in enumerate(names):
549 self.assertEqual(getattr(b, name), pos)
550 repr(b) # make sure repr() doesn't blow-up
551 d = b._asdict()
552 d_expected = dict(zip(names, range(n)))
553 self.assertEqual(d, d_expected)
554 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
555 b2_expected = list(range(n))
556 b2_expected[1] = 999
557 b2_expected[-5] = 42
558 self.assertEqual(b2, tuple(b2_expected))
559 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000560
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000561 def test_pickle(self):
562 p = TestNT(x=10, y=20, z=30)
563 for module in (pickle,):
564 loads = getattr(module, 'loads')
565 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500566 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000567 q = loads(dumps(p, protocol))
568 self.assertEqual(p, q)
569 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700570 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000571
572 def test_copy(self):
573 p = TestNT(x=10, y=20, z=30)
574 for copier in copy.copy, copy.deepcopy:
575 q = copier(p)
576 self.assertEqual(p, q)
577 self.assertEqual(p._fields, q._fields)
578
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000579 def test_name_conflicts(self):
580 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
581 # failed when used as field names. Test to make sure these now work.
582 T = namedtuple('T', 'itemgetter property self cls tuple')
583 t = T(1, 2, 3, 4, 5)
584 self.assertEqual(t, (1,2,3,4,5))
585 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
586 self.assertEqual(newt, (10,20,30,40,50))
587
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700588 # Broader test of all interesting names taken from the code, old
589 # template, and an example
590 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
591 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
592 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
593 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
594 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
595 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
596 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
597 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
598 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
599 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
600 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
601 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
602 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
603 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
604 'instantiate', 'interning', 'introspection', 'isidentifier',
605 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
606 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
607 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
608 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
609 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
610 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
611 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
612 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
613 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
614 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
615 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
616 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
617 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
618 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000619 T = namedtuple('T', words)
620 # test __new__
621 values = tuple(range(len(words)))
622 t = T(*values)
623 self.assertEqual(t, values)
624 t = T(**dict(zip(T._fields, values)))
625 self.assertEqual(t, values)
626 # test _make
627 t = T._make(values)
628 self.assertEqual(t, values)
629 # exercise __repr__
630 repr(t)
631 # test _asdict
632 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
633 # test _replace
634 t = T._make(values)
635 newvalues = tuple(v*10 for v in values)
636 newt = t._replace(**dict(zip(T._fields, newvalues)))
637 self.assertEqual(newt, newvalues)
638 # test _fields
639 self.assertEqual(T._fields, tuple(words))
640 # test __getnewargs__
641 self.assertEqual(t.__getnewargs__(), values)
642
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000643 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700644 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000645 self.assertEqual(repr(A(1)), 'A(x=1)')
646 # repr should show the name of the subclass
647 class B(A):
648 pass
649 self.assertEqual(repr(B(1)), 'B(x=1)')
650
Raymond Hettinger6538b432016-08-16 10:55:43 -0700651 def test_keyword_only_arguments(self):
652 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700653 with self.assertRaises(TypeError):
654 NT = namedtuple('NT', ['x', 'y'], True)
655
656 NT = namedtuple('NT', ['abc', 'def'], rename=True)
657 self.assertEqual(NT._fields, ('abc', '_1'))
658 with self.assertRaises(TypeError):
659 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000660
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700661 def test_namedtuple_subclass_issue_24931(self):
662 class Point(namedtuple('_Point', ['x', 'y'])):
663 pass
664
665 a = Point(3, 4)
666 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
667
668 a.w = 5
669 self.assertEqual(a.__dict__, {'w': 5})
670
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200671 def test_field_descriptor(self):
672 Point = namedtuple('Point', 'x y')
673 p = Point(11, 22)
674 self.assertTrue(inspect.isdatadescriptor(Point.x))
675 self.assertEqual(Point.x.__get__(p), 11)
676 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
677 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000678
Joe Jevnikf36f8922019-02-21 16:00:40 -0500679 class NewPoint(tuple):
680 x = pickle.loads(pickle.dumps(Point.x))
681 y = pickle.loads(pickle.dumps(Point.y))
682
683 np = NewPoint([1, 2])
684
685 self.assertEqual(np.x, 1)
686 self.assertEqual(np.y, 2)
687
Raymond Hettingerb6d68aa2021-02-04 15:52:16 -0800688 def test_new_builtins_issue_43102(self):
Victor Stinnera3c3ffa2021-02-18 12:35:37 +0100689 obj = namedtuple('C', ())
690 new_func = obj.__new__
691 self.assertEqual(new_func.__globals__['__builtins__'], {})
692 self.assertEqual(new_func.__builtins__, {})
Raymond Hettingerb6d68aa2021-02-04 15:52:16 -0800693
Brandt Bucher145bf262021-02-26 14:51:55 -0800694 def test_match_args(self):
695 Point = namedtuple('Point', 'x y')
696 self.assertEqual(Point.__match_args__, ('x', 'y'))
697
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700698
Raymond Hettinger499e1932011-02-23 07:56:53 +0000699################################################################################
700### Abstract Base Classes
701################################################################################
702
Raymond Hettingerae650182009-01-28 23:33:59 +0000703class ABCTestCase(unittest.TestCase):
704
705 def validate_abstract_methods(self, abc, *names):
706 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
707
708 # everything should work will all required methods are present
709 C = type('C', (abc,), methodstubs)
710 C()
711
712 # instantiation should fail if a required method is missing
713 for name in names:
714 stubs = methodstubs.copy()
715 del stubs[name]
716 C = type('C', (abc,), stubs)
717 self.assertRaises(TypeError, C, name)
718
Florent Xiclunace153f62010-03-08 15:34:35 +0000719 def validate_isinstance(self, abc, name):
720 stub = lambda s, *args: 0
721
722 C = type('C', (object,), {'__hash__': None})
723 setattr(C, name, stub)
724 self.assertIsInstance(C(), abc)
725 self.assertTrue(issubclass(C, abc))
726
727 C = type('C', (object,), {'__hash__': None})
728 self.assertNotIsInstance(C(), abc)
729 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000730
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000731 def validate_comparison(self, instance):
732 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
733 operators = {}
734 for op in ops:
735 name = '__' + op + '__'
736 operators[name] = getattr(operator, name)
737
738 class Other:
739 def __init__(self):
740 self.right_side = False
741 def __eq__(self, other):
742 self.right_side = True
743 return True
744 __lt__ = __eq__
745 __gt__ = __eq__
746 __le__ = __eq__
747 __ge__ = __eq__
748 __ne__ = __eq__
749 __ror__ = __eq__
750 __rand__ = __eq__
751 __rxor__ = __eq__
752 __rsub__ = __eq__
753
754 for name, op in operators.items():
755 if not hasattr(instance, name):
756 continue
757 other = Other()
758 op(instance, other)
759 self.assertTrue(other.right_side,'Right side not called for %s.%s'
760 % (type(instance), name))
761
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700762def _test_gen():
763 yield
764
Raymond Hettingerae650182009-01-28 23:33:59 +0000765class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000766
Yury Selivanov75445082015-05-11 22:57:16 -0400767 def test_Awaitable(self):
768 def gen():
769 yield
770
771 @types.coroutine
772 def coro():
773 yield
774
775 async def new_coro():
776 pass
777
778 class Bar:
779 def __await__(self):
780 yield
781
782 class MinimalCoro(Coroutine):
783 def send(self, value):
784 return value
785 def throw(self, typ, val=None, tb=None):
786 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400787 def __await__(self):
788 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400789
790 non_samples = [None, int(), gen(), object()]
791 for x in non_samples:
792 self.assertNotIsInstance(x, Awaitable)
793 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
794
795 samples = [Bar(), MinimalCoro()]
796 for x in samples:
797 self.assertIsInstance(x, Awaitable)
798 self.assertTrue(issubclass(type(x), Awaitable))
799
800 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400801 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
802 # flag don't have '__await__' method, hence can't be instances
803 # of Awaitable. Use inspect.isawaitable to detect them.
804 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400805
806 c = new_coro()
807 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300808 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400809
Yury Selivanov56fc6142015-05-29 09:01:29 -0400810 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400811 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400812 self.assertTrue(isinstance(CoroLike(), Awaitable))
813 self.assertTrue(issubclass(CoroLike, Awaitable))
814 CoroLike = None
815 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400816
Yury Selivanov75445082015-05-11 22:57:16 -0400817 def test_Coroutine(self):
818 def gen():
819 yield
820
821 @types.coroutine
822 def coro():
823 yield
824
825 async def new_coro():
826 pass
827
828 class Bar:
829 def __await__(self):
830 yield
831
832 class MinimalCoro(Coroutine):
833 def send(self, value):
834 return value
835 def throw(self, typ, val=None, tb=None):
836 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400837 def __await__(self):
838 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400839
840 non_samples = [None, int(), gen(), object(), Bar()]
841 for x in non_samples:
842 self.assertNotIsInstance(x, Coroutine)
843 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
844
845 samples = [MinimalCoro()]
846 for x in samples:
847 self.assertIsInstance(x, Awaitable)
848 self.assertTrue(issubclass(type(x), Awaitable))
849
850 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400851 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
852 # flag don't have '__await__' method, hence can't be instances
853 # of Coroutine. Use inspect.isawaitable to detect them.
854 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400855
856 c = new_coro()
857 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300858 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400859
Yury Selivanov56fc6142015-05-29 09:01:29 -0400860 class CoroLike:
861 def send(self, value):
862 pass
863 def throw(self, typ, val=None, tb=None):
864 pass
865 def close(self):
866 pass
867 def __await__(self):
868 pass
869 self.assertTrue(isinstance(CoroLike(), Coroutine))
870 self.assertTrue(issubclass(CoroLike, Coroutine))
871
872 class CoroLike:
873 def send(self, value):
874 pass
875 def close(self):
876 pass
877 def __await__(self):
878 pass
879 self.assertFalse(isinstance(CoroLike(), Coroutine))
880 self.assertFalse(issubclass(CoroLike, Coroutine))
881
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000882 def test_Hashable(self):
883 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000884 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000885 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000886 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000887 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000888 # Check some hashables
889 samples = [None,
890 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000891 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000892 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000893 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000894 ]
895 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000896 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000897 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000898 self.assertRaises(TypeError, Hashable)
899 # Check direct subclassing
900 class H(Hashable):
901 def __hash__(self):
902 return super().__hash__()
903 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000904 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000905 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000906 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000907
Yury Selivanove0104ae2015-05-14 12:19:16 -0400908 def test_AsyncIterable(self):
909 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400910 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400911 return self
912 self.assertTrue(isinstance(AI(), AsyncIterable))
913 self.assertTrue(issubclass(AI, AsyncIterable))
914 # Check some non-iterables
915 non_samples = [None, object, []]
916 for x in non_samples:
917 self.assertNotIsInstance(x, AsyncIterable)
918 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
919 self.validate_abstract_methods(AsyncIterable, '__aiter__')
920 self.validate_isinstance(AsyncIterable, '__aiter__')
921
922 def test_AsyncIterator(self):
923 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400924 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400925 return self
926 async def __anext__(self):
927 raise StopAsyncIteration
928 self.assertTrue(isinstance(AI(), AsyncIterator))
929 self.assertTrue(issubclass(AI, AsyncIterator))
930 non_samples = [None, object, []]
931 # Check some non-iterables
932 for x in non_samples:
933 self.assertNotIsInstance(x, AsyncIterator)
934 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
935 # Similarly to regular iterators (see issue 10565)
936 class AnextOnly:
937 async def __anext__(self):
938 raise StopAsyncIteration
939 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
940 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
941
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000942 def test_Iterable(self):
943 # Check some non-iterables
944 non_samples = [None, 42, 3.14, 1j]
945 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000946 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000947 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000948 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000949 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000950 tuple(), list(), set(), frozenset(), dict(),
951 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700952 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000953 (x for x in []),
954 ]
955 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000956 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000957 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000958 # Check direct subclassing
959 class I(Iterable):
960 def __iter__(self):
961 return super().__iter__()
962 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000963 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000964 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000965 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700966 # Check None blocking
967 class It:
968 def __iter__(self): return iter([])
969 class ItBlocked(It):
970 __iter__ = None
971 self.assertTrue(issubclass(It, Iterable))
972 self.assertTrue(isinstance(It(), Iterable))
973 self.assertFalse(issubclass(ItBlocked, Iterable))
974 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000975
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700976 def test_Reversible(self):
977 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100978 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700979 for x in non_samples:
980 self.assertNotIsInstance(x, Reversible)
981 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700982 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100983 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700984 for x in non_reversibles:
985 self.assertNotIsInstance(x, Reversible)
986 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
987 # Check some reversible iterables
988 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
989 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100990 OrderedDict().values(), Counter(), Counter().keys(),
991 Counter().items(), Counter().values(), dict(),
992 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700993 for x in samples:
994 self.assertIsInstance(x, Reversible)
995 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
996 # Check also Mapping, MutableMapping, and Sequence
997 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
998 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
999 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
1000 # Check direct subclassing
1001 class R(Reversible):
1002 def __iter__(self):
1003 return iter(list())
1004 def __reversed__(self):
1005 return iter(list())
1006 self.assertEqual(list(reversed(R())), [])
1007 self.assertFalse(issubclass(float, R))
1008 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001009 # Check reversible non-iterable (which is not Reversible)
1010 class RevNoIter:
1011 def __reversed__(self): return reversed([])
1012 class RevPlusIter(RevNoIter):
1013 def __iter__(self): return iter([])
1014 self.assertFalse(issubclass(RevNoIter, Reversible))
1015 self.assertFalse(isinstance(RevNoIter(), Reversible))
1016 self.assertTrue(issubclass(RevPlusIter, Reversible))
1017 self.assertTrue(isinstance(RevPlusIter(), Reversible))
1018 # Check None blocking
1019 class Rev:
1020 def __iter__(self): return iter([])
1021 def __reversed__(self): return reversed([])
1022 class RevItBlocked(Rev):
1023 __iter__ = None
1024 class RevRevBlocked(Rev):
1025 __reversed__ = None
1026 self.assertTrue(issubclass(Rev, Reversible))
1027 self.assertTrue(isinstance(Rev(), Reversible))
1028 self.assertFalse(issubclass(RevItBlocked, Reversible))
1029 self.assertFalse(isinstance(RevItBlocked(), Reversible))
1030 self.assertFalse(issubclass(RevRevBlocked, Reversible))
1031 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001032
Guido van Rossumf0666942016-08-23 10:47:07 -07001033 def test_Collection(self):
1034 # Check some non-collections
1035 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
1036 for x in non_collections:
1037 self.assertNotIsInstance(x, Collection)
1038 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1039 # Check some non-collection iterables
1040 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001041 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -07001042 for x in non_col_iterables:
1043 self.assertNotIsInstance(x, Collection)
1044 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1045 # Check some collections
1046 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001047 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001048 for x in samples:
1049 self.assertIsInstance(x, Collection)
1050 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1051 # Check also Mapping, MutableMapping, etc.
1052 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1053 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1054 self.assertTrue(issubclass(MutableMapping, Collection),
1055 repr(MutableMapping))
1056 self.assertTrue(issubclass(Set, Collection), repr(Set))
1057 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1058 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1059 # Check direct subclassing
1060 class Col(Collection):
1061 def __iter__(self):
1062 return iter(list())
1063 def __len__(self):
1064 return 0
1065 def __contains__(self, item):
1066 return False
1067 class DerCol(Col): pass
1068 self.assertEqual(list(iter(Col())), [])
1069 self.assertFalse(issubclass(list, Col))
1070 self.assertFalse(issubclass(set, Col))
1071 self.assertFalse(issubclass(float, Col))
1072 self.assertEqual(list(iter(DerCol())), [])
1073 self.assertFalse(issubclass(list, DerCol))
1074 self.assertFalse(issubclass(set, DerCol))
1075 self.assertFalse(issubclass(float, DerCol))
1076 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1077 '__contains__')
1078 # Check sized container non-iterable (which is not Collection) etc.
1079 class ColNoIter:
1080 def __len__(self): return 0
1081 def __contains__(self, item): return False
1082 class ColNoSize:
1083 def __iter__(self): return iter([])
1084 def __contains__(self, item): return False
1085 class ColNoCont:
1086 def __iter__(self): return iter([])
1087 def __len__(self): return 0
1088 self.assertFalse(issubclass(ColNoIter, Collection))
1089 self.assertFalse(isinstance(ColNoIter(), Collection))
1090 self.assertFalse(issubclass(ColNoSize, Collection))
1091 self.assertFalse(isinstance(ColNoSize(), Collection))
1092 self.assertFalse(issubclass(ColNoCont, Collection))
1093 self.assertFalse(isinstance(ColNoCont(), Collection))
1094 # Check None blocking
1095 class SizeBlock:
1096 def __iter__(self): return iter([])
1097 def __contains__(self): return False
1098 __len__ = None
1099 class IterBlock:
1100 def __len__(self): return 0
1101 def __contains__(self): return True
1102 __iter__ = None
1103 self.assertFalse(issubclass(SizeBlock, Collection))
1104 self.assertFalse(isinstance(SizeBlock(), Collection))
1105 self.assertFalse(issubclass(IterBlock, Collection))
1106 self.assertFalse(isinstance(IterBlock(), Collection))
1107 # Check None blocking in subclass
1108 class ColImpl:
1109 def __iter__(self):
1110 return iter(list())
1111 def __len__(self):
1112 return 0
1113 def __contains__(self, item):
1114 return False
1115 class NonCol(ColImpl):
1116 __contains__ = None
1117 self.assertFalse(issubclass(NonCol, Collection))
1118 self.assertFalse(isinstance(NonCol(), Collection))
1119
1120
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001121 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001122 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001123 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001124 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001125 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001126 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001127 iter(tuple()), iter(list()), iter(dict()),
1128 iter(set()), iter(frozenset()),
1129 iter(dict().keys()), iter(dict().items()),
1130 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001131 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001132 (x for x in []),
1133 ]
1134 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001135 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001136 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001137 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1138
1139 # Issue 10565
1140 class NextOnly:
1141 def __next__(self):
1142 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001143 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001144 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001145
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001146 def test_Generator(self):
1147 class NonGen1:
1148 def __iter__(self): return self
1149 def __next__(self): return None
1150 def close(self): pass
1151 def throw(self, typ, val=None, tb=None): pass
1152
1153 class NonGen2:
1154 def __iter__(self): return self
1155 def __next__(self): return None
1156 def close(self): pass
1157 def send(self, value): return value
1158
1159 class NonGen3:
1160 def close(self): pass
1161 def send(self, value): return value
1162 def throw(self, typ, val=None, tb=None): pass
1163
1164 non_samples = [
1165 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1166 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1167 for x in non_samples:
1168 self.assertNotIsInstance(x, Generator)
1169 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1170
1171 class Gen:
1172 def __iter__(self): return self
1173 def __next__(self): return None
1174 def close(self): pass
1175 def send(self, value): return value
1176 def throw(self, typ, val=None, tb=None): pass
1177
1178 class MinimalGen(Generator):
1179 def send(self, value):
1180 return value
1181 def throw(self, typ, val=None, tb=None):
1182 super().throw(typ, val, tb)
1183
1184 def gen():
1185 yield 1
1186
1187 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1188 for x in samples:
1189 self.assertIsInstance(x, Iterator)
1190 self.assertIsInstance(x, Generator)
1191 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1192 self.validate_abstract_methods(Generator, 'send', 'throw')
1193
1194 # mixin tests
1195 mgen = MinimalGen()
1196 self.assertIs(mgen, iter(mgen))
1197 self.assertIs(mgen.send(None), next(mgen))
1198 self.assertEqual(2, mgen.send(2))
1199 self.assertIsNone(mgen.close())
1200 self.assertRaises(ValueError, mgen.throw, ValueError)
1201 self.assertRaisesRegex(ValueError, "^huhu$",
1202 mgen.throw, ValueError, ValueError("huhu"))
1203 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1204
1205 class FailOnClose(Generator):
1206 def send(self, value): return value
1207 def throw(self, *args): raise ValueError
1208
1209 self.assertRaises(ValueError, FailOnClose().close)
1210
1211 class IgnoreGeneratorExit(Generator):
1212 def send(self, value): return value
1213 def throw(self, *args): pass
1214
1215 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1216
Yury Selivanov22214ab2016-11-16 18:25:04 -05001217 def test_AsyncGenerator(self):
1218 class NonAGen1:
1219 def __aiter__(self): return self
1220 def __anext__(self): return None
1221 def aclose(self): pass
1222 def athrow(self, typ, val=None, tb=None): pass
1223
1224 class NonAGen2:
1225 def __aiter__(self): return self
1226 def __anext__(self): return None
1227 def aclose(self): pass
1228 def asend(self, value): return value
1229
1230 class NonAGen3:
1231 def aclose(self): pass
1232 def asend(self, value): return value
1233 def athrow(self, typ, val=None, tb=None): pass
1234
1235 non_samples = [
1236 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1237 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1238 for x in non_samples:
1239 self.assertNotIsInstance(x, AsyncGenerator)
1240 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1241
1242 class Gen:
1243 def __aiter__(self): return self
1244 async def __anext__(self): return None
1245 async def aclose(self): pass
1246 async def asend(self, value): return value
1247 async def athrow(self, typ, val=None, tb=None): pass
1248
1249 class MinimalAGen(AsyncGenerator):
1250 async def asend(self, value):
1251 return value
1252 async def athrow(self, typ, val=None, tb=None):
1253 await super().athrow(typ, val, tb)
1254
1255 async def gen():
1256 yield 1
1257
1258 samples = [gen(), Gen(), MinimalAGen()]
1259 for x in samples:
1260 self.assertIsInstance(x, AsyncIterator)
1261 self.assertIsInstance(x, AsyncGenerator)
1262 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1263 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1264
1265 def run_async(coro):
1266 result = None
1267 while True:
1268 try:
1269 coro.send(None)
1270 except StopIteration as ex:
1271 result = ex.args[0] if ex.args else None
1272 break
1273 return result
1274
1275 # mixin tests
1276 mgen = MinimalAGen()
1277 self.assertIs(mgen, mgen.__aiter__())
1278 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1279 self.assertEqual(2, run_async(mgen.asend(2)))
1280 self.assertIsNone(run_async(mgen.aclose()))
1281 with self.assertRaises(ValueError):
1282 run_async(mgen.athrow(ValueError))
1283
1284 class FailOnClose(AsyncGenerator):
1285 async def asend(self, value): return value
1286 async def athrow(self, *args): raise ValueError
1287
1288 with self.assertRaises(ValueError):
1289 run_async(FailOnClose().aclose())
1290
1291 class IgnoreGeneratorExit(AsyncGenerator):
1292 async def asend(self, value): return value
1293 async def athrow(self, *args): pass
1294
1295 with self.assertRaises(RuntimeError):
1296 run_async(IgnoreGeneratorExit().aclose())
1297
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001298 def test_Sized(self):
1299 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001300 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001301 (x for x in []),
1302 ]
1303 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001304 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001305 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001306 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001307 tuple(), list(), set(), frozenset(), dict(),
1308 dict().keys(), dict().items(), dict().values(),
1309 ]
1310 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001311 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001312 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001313 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001314 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001315
1316 def test_Container(self):
1317 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001318 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001319 (x for x in []),
1320 ]
1321 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001322 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001323 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001324 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001325 tuple(), list(), set(), frozenset(), dict(),
1326 dict().keys(), dict().items(),
1327 ]
1328 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001329 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001330 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001331 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001332 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001333
1334 def test_Callable(self):
1335 non_samples = [None, 42, 3.14, 1j,
1336 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001337 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001338 (x for x in []),
1339 ]
1340 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001341 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001342 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001343 samples = [lambda: None,
1344 type, int, object,
1345 len,
1346 list.append, [].append,
1347 ]
1348 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001349 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001350 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001351 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001352 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001353
1354 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001355 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001356 class C(B):
1357 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001358 self.assertTrue(issubclass(C, B))
1359 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001360
1361 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001362 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001363 class C:
1364 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001365 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001366 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001367 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001368
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001369class WithSet(MutableSet):
1370
1371 def __init__(self, it=()):
1372 self.data = set(it)
1373
1374 def __len__(self):
1375 return len(self.data)
1376
1377 def __iter__(self):
1378 return iter(self.data)
1379
1380 def __contains__(self, item):
1381 return item in self.data
1382
1383 def add(self, item):
1384 self.data.add(item)
1385
1386 def discard(self, item):
1387 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001388
Raymond Hettingerae650182009-01-28 23:33:59 +00001389class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001390
1391 # XXX For now, we only test some virtual inheritance properties.
1392 # We should also test the proper behavior of the collection ABCs
1393 # as real base classes or mix-in classes.
1394
1395 def test_Set(self):
1396 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001397 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001398 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001399 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001400 class MySet(Set):
1401 def __contains__(self, x):
1402 return False
1403 def __len__(self):
1404 return 0
1405 def __iter__(self):
1406 return iter([])
1407 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001408
Benjamin Peterson41181742008-07-02 20:22:54 +00001409 def test_hash_Set(self):
1410 class OneTwoThreeSet(Set):
1411 def __init__(self):
1412 self.contents = [1, 2, 3]
1413 def __contains__(self, x):
1414 return x in self.contents
1415 def __len__(self):
1416 return len(self.contents)
1417 def __iter__(self):
1418 return iter(self.contents)
1419 def __hash__(self):
1420 return self._hash()
1421 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001422 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001423
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001424 def test_isdisjoint_Set(self):
1425 class MySet(Set):
1426 def __init__(self, itr):
1427 self.contents = itr
1428 def __contains__(self, x):
1429 return x in self.contents
1430 def __iter__(self):
1431 return iter(self.contents)
1432 def __len__(self):
1433 return len([x for x in self.contents])
1434 s1 = MySet((1, 2, 3))
1435 s2 = MySet((4, 5, 6))
1436 s3 = MySet((1, 5, 6))
1437 self.assertTrue(s1.isdisjoint(s2))
1438 self.assertFalse(s1.isdisjoint(s3))
1439
1440 def test_equality_Set(self):
1441 class MySet(Set):
1442 def __init__(self, itr):
1443 self.contents = itr
1444 def __contains__(self, x):
1445 return x in self.contents
1446 def __iter__(self):
1447 return iter(self.contents)
1448 def __len__(self):
1449 return len([x for x in self.contents])
1450 s1 = MySet((1,))
1451 s2 = MySet((1, 2))
1452 s3 = MySet((3, 4))
1453 s4 = MySet((3, 4))
1454 self.assertTrue(s2 > s1)
1455 self.assertTrue(s1 < s2)
1456 self.assertFalse(s2 <= s1)
1457 self.assertFalse(s2 <= s3)
1458 self.assertFalse(s1 >= s2)
1459 self.assertEqual(s3, s4)
1460 self.assertNotEqual(s2, s3)
1461
1462 def test_arithmetic_Set(self):
1463 class MySet(Set):
1464 def __init__(self, itr):
1465 self.contents = itr
1466 def __contains__(self, x):
1467 return x in self.contents
1468 def __iter__(self):
1469 return iter(self.contents)
1470 def __len__(self):
1471 return len([x for x in self.contents])
1472 s1 = MySet((1, 2, 3))
1473 s2 = MySet((3, 4, 5))
1474 s3 = s1 & s2
1475 self.assertEqual(s3, MySet((3,)))
1476
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001477 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001478 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001479 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001480 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001481 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001482 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1483 'add', 'discard')
1484
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001485 def test_issue_5647(self):
1486 # MutableSet.__iand__ mutated the set during iteration
1487 s = WithSet('abcd')
1488 s &= WithSet('cdef') # This used to fail
1489 self.assertEqual(set(s), set('cd'))
1490
Raymond Hettingerae650182009-01-28 23:33:59 +00001491 def test_issue_4920(self):
1492 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001493 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001494 __slots__=['__s']
1495 def __init__(self,items=None):
1496 if items is None:
1497 items=[]
1498 self.__s=set(items)
1499 def __contains__(self,v):
1500 return v in self.__s
1501 def __iter__(self):
1502 return iter(self.__s)
1503 def __len__(self):
1504 return len(self.__s)
1505 def add(self,v):
1506 result=v not in self.__s
1507 self.__s.add(v)
1508 return result
1509 def discard(self,v):
1510 result=v in self.__s
1511 self.__s.discard(v)
1512 return result
1513 def __repr__(self):
1514 return "MySet(%s)" % repr(list(self))
1515 s = MySet([5,43,2,1])
1516 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001517
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001518 def test_issue8750(self):
1519 empty = WithSet()
1520 full = WithSet(range(10))
1521 s = WithSet(full)
1522 s -= s
1523 self.assertEqual(s, empty)
1524 s = WithSet(full)
1525 s ^= s
1526 self.assertEqual(s, empty)
1527 s = WithSet(full)
1528 s &= s
1529 self.assertEqual(s, full)
1530 s |= s
1531 self.assertEqual(s, full)
1532
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001533 def test_issue16373(self):
1534 # Recursion error comparing comparable and noncomparable
1535 # Set instances
1536 class MyComparableSet(Set):
1537 def __contains__(self, x):
1538 return False
1539 def __len__(self):
1540 return 0
1541 def __iter__(self):
1542 return iter([])
1543 class MyNonComparableSet(Set):
1544 def __contains__(self, x):
1545 return False
1546 def __len__(self):
1547 return 0
1548 def __iter__(self):
1549 return iter([])
1550 def __le__(self, x):
1551 return NotImplemented
1552 def __lt__(self, x):
1553 return NotImplemented
1554
1555 cs = MyComparableSet()
1556 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001557 self.assertFalse(ncs < cs)
1558 self.assertTrue(ncs <= cs)
1559 self.assertFalse(ncs > cs)
1560 self.assertTrue(ncs >= cs)
1561
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001562 def test_issue26915(self):
1563 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001564 class CustomSequence(Sequence):
1565 def __init__(self, seq):
1566 self._seq = seq
1567 def __getitem__(self, index):
1568 return self._seq[index]
1569 def __len__(self):
1570 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001571
1572 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001573 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001574 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001575 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001576 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001577 ItemsView({1: nan, 2: obj}),
1578 ValuesView({1: nan, 2: obj})
1579 ]
1580 for container in containers:
1581 for elem in container:
1582 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001583 self.assertEqual(seq.index(nan), 0)
1584 self.assertEqual(seq.index(obj), 1)
1585 self.assertEqual(seq.count(nan), 2)
1586 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001587
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001588 def assertSameSet(self, s1, s2):
1589 # coerce both to a real set then check equality
1590 self.assertSetEqual(set(s1), set(s2))
1591
Richard Levasseur68f68fa2020-11-21 11:56:24 -08001592 def test_Set_from_iterable(self):
1593 """Verify _from_iterable overriden to an instance method works."""
1594 class SetUsingInstanceFromIterable(MutableSet):
1595 def __init__(self, values, created_by):
1596 if not created_by:
1597 raise ValueError(f'created_by must be specified')
1598 self.created_by = created_by
1599 self._values = set(values)
1600
1601 def _from_iterable(self, values):
1602 return type(self)(values, 'from_iterable')
1603
1604 def __contains__(self, value):
1605 return value in self._values
1606
1607 def __iter__(self):
1608 yield from self._values
1609
1610 def __len__(self):
1611 return len(self._values)
1612
1613 def add(self, value):
1614 self._values.add(value)
1615
1616 def discard(self, value):
1617 self._values.discard(value)
1618
1619 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
1620
1621 actual = impl - {1}
1622 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1623 self.assertEqual('from_iterable', actual.created_by)
1624 self.assertEqual({2, 3}, actual)
1625
1626 actual = impl | {4}
1627 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1628 self.assertEqual('from_iterable', actual.created_by)
1629 self.assertEqual({1, 2, 3, 4}, actual)
1630
1631 actual = impl & {2}
1632 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1633 self.assertEqual('from_iterable', actual.created_by)
1634 self.assertEqual({2}, actual)
1635
1636 actual = impl ^ {3, 4}
1637 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1638 self.assertEqual('from_iterable', actual.created_by)
1639 self.assertEqual({1, 2, 4}, actual)
1640
1641 # NOTE: ixor'ing with a list is important here: internally, __ixor__
1642 # only calls _from_iterable if the other value isn't already a Set.
1643 impl ^= [3, 4]
1644 self.assertIsInstance(impl, SetUsingInstanceFromIterable)
1645 self.assertEqual('test', impl.created_by)
1646 self.assertEqual({1, 2, 4}, impl)
1647
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001648 def test_Set_interoperability_with_real_sets(self):
1649 # Issue: 8743
1650 class ListSet(Set):
1651 def __init__(self, elements=()):
1652 self.data = []
1653 for elem in elements:
1654 if elem not in self.data:
1655 self.data.append(elem)
1656 def __contains__(self, elem):
1657 return elem in self.data
1658 def __iter__(self):
1659 return iter(self.data)
1660 def __len__(self):
1661 return len(self.data)
1662 def __repr__(self):
1663 return 'Set({!r})'.format(self.data)
1664
1665 r1 = set('abc')
1666 r2 = set('bcd')
1667 r3 = set('abcde')
1668 f1 = ListSet('abc')
1669 f2 = ListSet('bcd')
1670 f3 = ListSet('abcde')
1671 l1 = list('abccba')
1672 l2 = list('bcddcb')
1673 l3 = list('abcdeedcba')
1674
1675 target = r1 & r2
1676 self.assertSameSet(f1 & f2, target)
1677 self.assertSameSet(f1 & r2, target)
1678 self.assertSameSet(r2 & f1, target)
1679 self.assertSameSet(f1 & l2, target)
1680
1681 target = r1 | r2
1682 self.assertSameSet(f1 | f2, target)
1683 self.assertSameSet(f1 | r2, target)
1684 self.assertSameSet(r2 | f1, target)
1685 self.assertSameSet(f1 | l2, target)
1686
1687 fwd_target = r1 - r2
1688 rev_target = r2 - r1
1689 self.assertSameSet(f1 - f2, fwd_target)
1690 self.assertSameSet(f2 - f1, rev_target)
1691 self.assertSameSet(f1 - r2, fwd_target)
1692 self.assertSameSet(f2 - r1, rev_target)
1693 self.assertSameSet(r1 - f2, fwd_target)
1694 self.assertSameSet(r2 - f1, rev_target)
1695 self.assertSameSet(f1 - l2, fwd_target)
1696 self.assertSameSet(f2 - l1, rev_target)
1697
1698 target = r1 ^ r2
1699 self.assertSameSet(f1 ^ f2, target)
1700 self.assertSameSet(f1 ^ r2, target)
1701 self.assertSameSet(r2 ^ f1, target)
1702 self.assertSameSet(f1 ^ l2, target)
1703
1704 # Don't change the following to use assertLess or other
1705 # "more specific" unittest assertions. The current
1706 # assertTrue/assertFalse style makes the pattern of test
1707 # case combinations clear and allows us to know for sure
1708 # the exact operator being invoked.
1709
1710 # proper subset
1711 self.assertTrue(f1 < f3)
1712 self.assertFalse(f1 < f1)
1713 self.assertFalse(f1 < f2)
1714 self.assertTrue(r1 < f3)
1715 self.assertFalse(r1 < f1)
1716 self.assertFalse(r1 < f2)
1717 self.assertTrue(r1 < r3)
1718 self.assertFalse(r1 < r1)
1719 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001720 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001721 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001722 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001723 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001724 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001725 f1 < l2
1726
1727 # any subset
1728 self.assertTrue(f1 <= f3)
1729 self.assertTrue(f1 <= f1)
1730 self.assertFalse(f1 <= f2)
1731 self.assertTrue(r1 <= f3)
1732 self.assertTrue(r1 <= f1)
1733 self.assertFalse(r1 <= f2)
1734 self.assertTrue(r1 <= r3)
1735 self.assertTrue(r1 <= r1)
1736 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001737 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001738 f1 <= l3
1739 with self.assertRaises(TypeError):
1740 f1 <= l1
1741 with self.assertRaises(TypeError):
1742 f1 <= l2
1743
1744 # proper superset
1745 self.assertTrue(f3 > f1)
1746 self.assertFalse(f1 > f1)
1747 self.assertFalse(f2 > f1)
1748 self.assertTrue(r3 > r1)
1749 self.assertFalse(f1 > r1)
1750 self.assertFalse(f2 > r1)
1751 self.assertTrue(r3 > r1)
1752 self.assertFalse(r1 > r1)
1753 self.assertFalse(r2 > r1)
1754 with self.assertRaises(TypeError):
1755 f1 > l3
1756 with self.assertRaises(TypeError):
1757 f1 > l1
1758 with self.assertRaises(TypeError):
1759 f1 > l2
1760
1761 # any superset
1762 self.assertTrue(f3 >= f1)
1763 self.assertTrue(f1 >= f1)
1764 self.assertFalse(f2 >= f1)
1765 self.assertTrue(r3 >= r1)
1766 self.assertTrue(f1 >= r1)
1767 self.assertFalse(f2 >= r1)
1768 self.assertTrue(r3 >= r1)
1769 self.assertTrue(r1 >= r1)
1770 self.assertFalse(r2 >= r1)
1771 with self.assertRaises(TypeError):
1772 f1 >= l3
1773 with self.assertRaises(TypeError):
1774 f1 >=l1
1775 with self.assertRaises(TypeError):
1776 f1 >= l2
1777
1778 # equality
1779 self.assertTrue(f1 == f1)
1780 self.assertTrue(r1 == f1)
1781 self.assertTrue(f1 == r1)
1782 self.assertFalse(f1 == f3)
1783 self.assertFalse(r1 == f3)
1784 self.assertFalse(f1 == r3)
1785 self.assertFalse(f1 == l3)
1786 self.assertFalse(f1 == l1)
1787 self.assertFalse(f1 == l2)
1788
1789 # inequality
1790 self.assertFalse(f1 != f1)
1791 self.assertFalse(r1 != f1)
1792 self.assertFalse(f1 != r1)
1793 self.assertTrue(f1 != f3)
1794 self.assertTrue(r1 != f3)
1795 self.assertTrue(f1 != r3)
1796 self.assertTrue(f1 != l3)
1797 self.assertTrue(f1 != l1)
1798 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001799
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001800 def test_Mapping(self):
1801 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001802 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001803 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001804 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1805 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001806 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001807 def __len__(self):
1808 return 0
1809 def __getitem__(self, i):
1810 raise IndexError
1811 def __iter__(self):
1812 return iter(())
1813 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001814 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001815
1816 def test_MutableMapping(self):
1817 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001818 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001819 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001820 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1821 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001822
Raymond Hettinger9117c752010-08-22 07:44:24 +00001823 def test_MutableMapping_subclass(self):
1824 # Test issue 9214
1825 mymap = UserDict()
1826 mymap['red'] = 5
1827 self.assertIsInstance(mymap.keys(), Set)
1828 self.assertIsInstance(mymap.keys(), KeysView)
1829 self.assertIsInstance(mymap.items(), Set)
1830 self.assertIsInstance(mymap.items(), ItemsView)
1831
1832 mymap = UserDict()
1833 mymap['red'] = 5
1834 z = mymap.keys() | {'orange'}
1835 self.assertIsInstance(z, set)
1836 list(z)
1837 mymap['blue'] = 7 # Shouldn't affect 'z'
1838 self.assertEqual(sorted(z), ['orange', 'red'])
1839
1840 mymap = UserDict()
1841 mymap['red'] = 5
1842 z = mymap.items() | {('orange', 3)}
1843 self.assertIsInstance(z, set)
1844 list(z)
1845 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001846 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001847
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001848 def test_Sequence(self):
1849 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001850 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001851 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001852 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001853 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001854 self.assertIsInstance(memoryview(b""), Sequence)
1855 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001856 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001857 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1858 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001859
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001860 def test_Sequence_mixins(self):
1861 class SequenceSubclass(Sequence):
1862 def __init__(self, seq=()):
1863 self.seq = seq
1864
1865 def __getitem__(self, index):
1866 return self.seq[index]
1867
1868 def __len__(self):
1869 return len(self.seq)
1870
1871 # Compare Sequence.index() behavior to (list|str).index() behavior
1872 def assert_index_same(seq1, seq2, index_args):
1873 try:
1874 expected = seq1.index(*index_args)
1875 except ValueError:
1876 with self.assertRaises(ValueError):
1877 seq2.index(*index_args)
1878 else:
1879 actual = seq2.index(*index_args)
1880 self.assertEqual(
1881 actual, expected, '%r.index%s' % (seq1, index_args))
1882
1883 for ty in list, str:
1884 nativeseq = ty('abracadabra')
1885 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1886 seqseq = SequenceSubclass(nativeseq)
1887 for letter in set(nativeseq) | {'z'}:
1888 assert_index_same(nativeseq, seqseq, (letter,))
1889 for start in range(-3, len(nativeseq) + 3):
1890 assert_index_same(nativeseq, seqseq, (letter, start))
1891 for stop in range(-3, len(nativeseq) + 3):
1892 assert_index_same(
1893 nativeseq, seqseq, (letter, start, stop))
1894
Guido van Rossumd05eb002007-11-21 22:26:24 +00001895 def test_ByteString(self):
1896 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001897 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001898 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001899 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001900 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001901 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001902 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001903 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001904
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001905 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001906 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001907 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001908 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001909 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001910 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001911 self.assertTrue(issubclass(sample, MutableSequence))
1912 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001913 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1914 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001915
Eli Bendersky0716a572011-03-04 10:38:14 +00001916 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001917 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001918 # class inherited from it.
1919 class MutableSequenceSubclass(MutableSequence):
1920 def __init__(self):
1921 self.lst = []
1922
1923 def __setitem__(self, index, value):
1924 self.lst[index] = value
1925
1926 def __getitem__(self, index):
1927 return self.lst[index]
1928
1929 def __len__(self):
1930 return len(self.lst)
1931
1932 def __delitem__(self, index):
1933 del self.lst[index]
1934
1935 def insert(self, index, value):
1936 self.lst.insert(index, value)
1937
1938 mss = MutableSequenceSubclass()
1939 mss.append(0)
1940 mss.extend((1, 2, 3, 4))
1941 self.assertEqual(len(mss), 5)
1942 self.assertEqual(mss[3], 3)
1943 mss.reverse()
1944 self.assertEqual(mss[3], 1)
1945 mss.pop()
1946 self.assertEqual(len(mss), 4)
1947 mss.remove(3)
1948 self.assertEqual(len(mss), 3)
1949 mss += (10, 20, 30)
1950 self.assertEqual(len(mss), 6)
1951 self.assertEqual(mss[-1], 30)
1952 mss.clear()
1953 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001954
Naris R1b5f9c92018-08-31 02:56:14 +10001955 # issue 34427
1956 # extending self should not cause infinite loop
1957 items = 'ABCD'
1958 mss2 = MutableSequenceSubclass()
1959 mss2.extend(items + items)
1960 mss.clear()
1961 mss.extend(items)
1962 mss.extend(mss)
1963 self.assertEqual(len(mss), len(mss2))
1964 self.assertEqual(list(mss), list(mss2))
1965
1966
Raymond Hettinger499e1932011-02-23 07:56:53 +00001967################################################################################
1968### Counter
1969################################################################################
1970
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001971class CounterSubclassWithSetItem(Counter):
1972 # Test a counter subclass that overrides __setitem__
1973 def __init__(self, *args, **kwds):
1974 self.called = False
1975 Counter.__init__(self, *args, **kwds)
1976 def __setitem__(self, key, value):
1977 self.called = True
1978 Counter.__setitem__(self, key, value)
1979
1980class CounterSubclassWithGet(Counter):
1981 # Test a counter subclass that overrides get()
1982 def __init__(self, *args, **kwds):
1983 self.called = False
1984 Counter.__init__(self, *args, **kwds)
1985 def get(self, key, default):
1986 self.called = True
1987 return Counter.get(self, key, default)
1988
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001989class TestCounter(unittest.TestCase):
1990
1991 def test_basics(self):
1992 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001993 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1994 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001995 self.assertIsInstance(c, dict)
1996 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001997 self.assertTrue(issubclass(Counter, dict))
1998 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001999 self.assertEqual(len(c), 3)
2000 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002001 self.assertEqual(list(c.values()), [3, 2, 1])
2002 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
2003 self.assertEqual(list(c), ['a', 'b', 'c'])
2004 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002005 [('a', 3), ('b', 2), ('c', 1)])
2006 self.assertEqual(c['b'], 2)
2007 self.assertEqual(c['z'], 0)
2008 self.assertEqual(c.__contains__('c'), True)
2009 self.assertEqual(c.__contains__('z'), False)
2010 self.assertEqual(c.get('b', 10), 2)
2011 self.assertEqual(c.get('z', 10), 10)
2012 self.assertEqual(c, dict(a=3, b=2, c=1))
2013 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
2014 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
2015 for i in range(5):
2016 self.assertEqual(c.most_common(i),
2017 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002018 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002019 c['a'] += 1 # increment an existing value
2020 c['b'] -= 2 # sub existing value to zero
2021 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002022 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002023 c['d'] -= 2 # sub from a missing value
2024 c['e'] = -5 # directly assign a missing value
2025 c['f'] += 4 # add to a missing value
2026 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002027 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002028 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002029 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002030 for i in range(3):
2031 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002032 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002033 c.clear()
2034 self.assertEqual(c, {})
2035 self.assertEqual(repr(c), 'Counter()')
2036 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
2037 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002038 c.update(dict(a=5, b=3))
2039 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002040 c.update(Counter('a' * 50 + 'b' * 30))
2041 c.update() # test case with no args
2042 c.__init__('a' * 500 + 'b' * 300)
2043 c.__init__('cdc')
2044 c.__init__()
2045 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
2046 self.assertEqual(c.setdefault('d', 5), 1)
2047 self.assertEqual(c['d'], 1)
2048 self.assertEqual(c.setdefault('e', 5), 5)
2049 self.assertEqual(c['e'], 5)
2050
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002051 def test_init(self):
2052 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
2053 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
2054 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
2055 self.assertRaises(TypeError, Counter, 42)
2056 self.assertRaises(TypeError, Counter, (), ())
2057 self.assertRaises(TypeError, Counter.__init__)
2058
Raymond Hettinger407c7342019-02-21 09:19:00 -08002059 def test_order_preservation(self):
2060 # Input order dictates items() order
2061 self.assertEqual(list(Counter('abracadabra').items()),
2062 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
2063 # letters with same count: ^----------^ ^---------^
2064
2065 # Verify retention of order even when all counts are equal
2066 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
2067 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
2068
2069 # Input order dictates elements() order
2070 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
2071 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
2072 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
2073
2074 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10002075 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08002076 ps = 'aaabbcdddeefggghhijjjkkl'
2077 qs = 'abbcccdeefffhkkllllmmnno'
2078 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
2079 def correctly_ordered(seq):
2080 'Return true if the letters occur in the expected order'
2081 positions = [order[letter] for letter in seq]
2082 return positions == sorted(positions)
2083
2084 p, q = Counter(ps), Counter(qs)
2085 self.assertTrue(correctly_ordered(+p))
2086 self.assertTrue(correctly_ordered(-p))
2087 self.assertTrue(correctly_ordered(p + q))
2088 self.assertTrue(correctly_ordered(p - q))
2089 self.assertTrue(correctly_ordered(p | q))
2090 self.assertTrue(correctly_ordered(p & q))
2091
2092 p, q = Counter(ps), Counter(qs)
2093 p += q
2094 self.assertTrue(correctly_ordered(p))
2095
2096 p, q = Counter(ps), Counter(qs)
2097 p -= q
2098 self.assertTrue(correctly_ordered(p))
2099
2100 p, q = Counter(ps), Counter(qs)
2101 p |= q
2102 self.assertTrue(correctly_ordered(p))
2103
2104 p, q = Counter(ps), Counter(qs)
2105 p &= q
2106 self.assertTrue(correctly_ordered(p))
2107
2108 p, q = Counter(ps), Counter(qs)
2109 p.update(q)
2110 self.assertTrue(correctly_ordered(p))
2111
2112 p, q = Counter(ps), Counter(qs)
2113 p.subtract(q)
2114 self.assertTrue(correctly_ordered(p))
2115
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002116 def test_update(self):
2117 c = Counter()
2118 c.update(self=42)
2119 self.assertEqual(list(c.items()), [('self', 42)])
2120 c = Counter()
2121 c.update(iterable=42)
2122 self.assertEqual(list(c.items()), [('iterable', 42)])
2123 c = Counter()
2124 c.update(iterable=None)
2125 self.assertEqual(list(c.items()), [('iterable', None)])
2126 self.assertRaises(TypeError, Counter().update, 42)
2127 self.assertRaises(TypeError, Counter().update, {}, {})
2128 self.assertRaises(TypeError, Counter.update)
2129
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002130 def test_copying(self):
2131 # Check that counters are copyable, deepcopyable, picklable, and
2132 #have a repr/eval round-trip
2133 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002134 def check(dup):
2135 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2136 self.assertIsNot(dup, words, msg)
2137 self.assertEqual(dup, words)
2138 check(words.copy())
2139 check(copy.copy(words))
2140 check(copy.deepcopy(words))
2141 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2142 with self.subTest(proto=proto):
2143 check(pickle.loads(pickle.dumps(words, proto)))
2144 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002145 update_test = Counter()
2146 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002147 check(update_test)
2148 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002149
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002150 def test_copy_subclass(self):
2151 class MyCounter(Counter):
2152 pass
2153 c = MyCounter('slartibartfast')
2154 d = c.copy()
2155 self.assertEqual(d, c)
2156 self.assertEqual(len(d), len(c))
2157 self.assertEqual(type(d), type(c))
2158
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002159 def test_conversions(self):
2160 # Convert to: set, list, dict
2161 s = 'she sells sea shells by the sea shore'
2162 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2163 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2164 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2165 self.assertEqual(set(Counter(s)), set(s))
2166
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002167 def test_invariant_for_the_in_operator(self):
2168 c = Counter(a=10, b=-2, c=0)
2169 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002170 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002171 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002172
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002173 def test_multiset_operations(self):
2174 # Verify that adding a zero counter will strip zeros and negatives
2175 c = Counter(a=10, b=-2, c=0) + Counter()
2176 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002177
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002178 elements = 'abcd'
2179 for i in range(1000):
2180 # test random pairs of multisets
2181 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002182 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002183 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002184 q.update(h=1, i=-1, j=0)
2185 for counterop, numberop in [
2186 (Counter.__add__, lambda x, y: max(0, x+y)),
2187 (Counter.__sub__, lambda x, y: max(0, x-y)),
2188 (Counter.__or__, lambda x, y: max(0,x,y)),
2189 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002190 ]:
2191 result = counterop(p, q)
2192 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002193 self.assertEqual(numberop(p[x], q[x]), result[x],
2194 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002195 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002196 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002197
2198 elements = 'abcdef'
2199 for i in range(100):
2200 # verify that random multisets with no repeats are exactly like sets
2201 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2202 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2203 for counterop, setop in [
2204 (Counter.__sub__, set.__sub__),
2205 (Counter.__or__, set.__or__),
2206 (Counter.__and__, set.__and__),
2207 ]:
2208 counter_result = counterop(p, q)
2209 set_result = setop(set(p.elements()), set(q.elements()))
2210 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002211
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002212 def test_inplace_operations(self):
2213 elements = 'abcd'
2214 for i in range(1000):
2215 # test random pairs of multisets
2216 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2217 p.update(e=1, f=-1, g=0)
2218 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2219 q.update(h=1, i=-1, j=0)
2220 for inplace_op, regular_op in [
2221 (Counter.__iadd__, Counter.__add__),
2222 (Counter.__isub__, Counter.__sub__),
2223 (Counter.__ior__, Counter.__or__),
2224 (Counter.__iand__, Counter.__and__),
2225 ]:
2226 c = p.copy()
2227 c_id = id(c)
2228 regular_result = regular_op(c, q)
2229 inplace_result = inplace_op(c, q)
2230 self.assertEqual(inplace_result, regular_result)
2231 self.assertEqual(id(inplace_result), c_id)
2232
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002233 def test_subtract(self):
2234 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2235 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2236 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2237 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2238 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2239 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2240 c = Counter('aaabbcd')
2241 c.subtract('aaaabbcce')
2242 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002243
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002244 c = Counter()
2245 c.subtract(self=42)
2246 self.assertEqual(list(c.items()), [('self', -42)])
2247 c = Counter()
2248 c.subtract(iterable=42)
2249 self.assertEqual(list(c.items()), [('iterable', -42)])
2250 self.assertRaises(TypeError, Counter().subtract, 42)
2251 self.assertRaises(TypeError, Counter().subtract, {}, {})
2252 self.assertRaises(TypeError, Counter.subtract)
2253
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002254 def test_unary(self):
2255 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2256 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2257 self.assertEqual(dict(-c), dict(a=5))
2258
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002259 def test_repr_nonsortable(self):
2260 c = Counter(a=2, b=None)
2261 r = repr(c)
2262 self.assertIn("'a': 2", r)
2263 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002264
Raymond Hettinger426e0522011-01-03 02:12:02 +00002265 def test_helper_function(self):
2266 # two paths, one for real dicts and one for other mappings
2267 elems = list('abracadabra')
2268
2269 d = dict()
2270 _count_elements(d, elems)
2271 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2272
2273 m = OrderedDict()
2274 _count_elements(m, elems)
2275 self.assertEqual(m,
2276 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2277
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002278 # test fidelity to the pure python version
2279 c = CounterSubclassWithSetItem('abracadabra')
2280 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002281 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002282 c = CounterSubclassWithGet('abracadabra')
2283 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002284 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002285
Raymond Hettinger60398512020-05-28 08:35:46 -07002286 def test_multiset_operations_equivalent_to_set_operations(self):
2287 # When the multiplicities are all zero or one, multiset operations
2288 # are guaranteed to be equivalent to the corresponding operations
2289 # for regular sets.
2290 s = list(product(('a', 'b', 'c'), range(2)))
2291 powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
2292 counters = [Counter(dict(groups)) for groups in powerset]
2293 for cp, cq in product(counters, repeat=2):
2294 sp = set(cp.elements())
2295 sq = set(cq.elements())
2296 self.assertEqual(set(cp + cq), sp | sq)
2297 self.assertEqual(set(cp - cq), sp - sq)
2298 self.assertEqual(set(cp | cq), sp | sq)
2299 self.assertEqual(set(cp & cq), sp & sq)
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002300 self.assertEqual(cp == cq, sp == sq)
2301 self.assertEqual(cp != cq, sp != sq)
2302 self.assertEqual(cp <= cq, sp <= sq)
2303 self.assertEqual(cp >= cq, sp >= sq)
2304 self.assertEqual(cp < cq, sp < sq)
2305 self.assertEqual(cp > cq, sp > sq)
Raymond Hettinger60398512020-05-28 08:35:46 -07002306
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002307 def test_eq(self):
2308 self.assertEqual(Counter(a=3, b=2, c=0), Counter('ababa'))
2309 self.assertNotEqual(Counter(a=3, b=2), Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002310
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002311 def test_le(self):
2312 self.assertTrue(Counter(a=3, b=2, c=0) <= Counter('ababa'))
2313 self.assertFalse(Counter(a=3, b=2) <= Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002314
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002315 def test_lt(self):
2316 self.assertTrue(Counter(a=3, b=1, c=0) < Counter('ababa'))
2317 self.assertFalse(Counter(a=3, b=2, c=0) < Counter('ababa'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002318
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002319 def test_ge(self):
2320 self.assertTrue(Counter(a=2, b=1, c=0) >= Counter('aab'))
2321 self.assertFalse(Counter(a=3, b=2, c=0) >= Counter('aabd'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002322
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002323 def test_gt(self):
2324 self.assertTrue(Counter(a=3, b=2, c=0) > Counter('aab'))
2325 self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002326
Raymond Hettinger499e1932011-02-23 07:56:53 +00002327
2328################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002329### Run tests
2330################################################################################
2331
Guido van Rossumd8faa362007-04-27 19:54:29 +00002332def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002333 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002334 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002335 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002336 TestUserObjects,
2337 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002338 support.run_unittest(*test_classes)
2339 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002340
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002341
Guido van Rossumd8faa362007-04-27 19:54:29 +00002342if __name__ == "__main__":
2343 test_main(verbose=True)