blob: 8d80e88673b89c80d555203e262ae5a88f4eb422 [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
Raymond Hettinger499e1932011-02-23 07:56:53 +0000199 def test_dict_coercion(self):
200 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
201 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
202 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
203
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000204 def test_new_child(self):
205 'Tests for changes for issue #16613.'
206 c = ChainMap()
207 c['a'] = 1
208 c['b'] = 2
209 m = {'b':20, 'c': 30}
210 d = c.new_child(m)
211 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
212 self.assertIs(m, d.maps[0])
213
214 # Use a different map than a dict
215 class lowerdict(dict):
216 def __getitem__(self, key):
217 if isinstance(key, str):
218 key = key.lower()
219 return dict.__getitem__(self, key)
220 def __contains__(self, key):
221 if isinstance(key, str):
222 key = key.lower()
223 return dict.__contains__(self, key)
224
225 c = ChainMap()
226 c['a'] = 1
227 c['b'] = 2
228 m = lowerdict(b=20, c=30)
229 d = c.new_child(m)
230 self.assertIs(m, d.maps[0])
231 for key in 'abc': # check contains
232 self.assertIn(key, d)
233 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
234 self.assertEqual(d.get(k, 100), v)
235
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700236 def test_union_operators(self):
237 cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
238 cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
239 cm3 = cm1.copy()
240 d = dict(a=10, c=30)
241 pairs = [('c', 3), ('p',0)]
242
243 tmp = cm1 | cm2 # testing between chainmaps
244 self.assertEqual(tmp.maps, [cm1.maps[0] | dict(cm2), *cm1.maps[1:]])
245 cm1 |= cm2
246 self.assertEqual(tmp, cm1)
247
248 tmp = cm2 | d # testing between chainmap and mapping
249 self.assertEqual(tmp.maps, [cm2.maps[0] | d, *cm2.maps[1:]])
250 self.assertEqual((d | cm2).maps, [d | dict(cm2)])
251 cm2 |= d
252 self.assertEqual(tmp, cm2)
253
254 # testing behavior between chainmap and iterable key-value pairs
255 with self.assertRaises(TypeError):
256 cm3 | pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700257 tmp = cm3.copy()
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700258 cm3 |= pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700259 self.assertEqual(cm3.maps, [tmp.maps[0] | dict(pairs), *tmp.maps[1:]])
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700260
261 # testing proper return types for ChainMap and it's subclasses
262 class Subclass(ChainMap):
263 pass
264
265 class SubclassRor(ChainMap):
266 def __ror__(self, other):
267 return super().__ror__(other)
268
269 tmp = ChainMap() | ChainMap()
270 self.assertIs(type(tmp), ChainMap)
271 self.assertIs(type(tmp.maps[0]), dict)
272 tmp = ChainMap() | Subclass()
273 self.assertIs(type(tmp), ChainMap)
274 self.assertIs(type(tmp.maps[0]), dict)
275 tmp = Subclass() | ChainMap()
276 self.assertIs(type(tmp), Subclass)
277 self.assertIs(type(tmp.maps[0]), dict)
278 tmp = ChainMap() | SubclassRor()
279 self.assertIs(type(tmp), SubclassRor)
280 self.assertIs(type(tmp.maps[0]), dict)
281
Raymond Hettinger499e1932011-02-23 07:56:53 +0000282
283################################################################################
284### Named Tuples
285################################################################################
286
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000287TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000288
289class TestNamedTuple(unittest.TestCase):
290
291 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000292 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000293 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000294 self.assertEqual(Point.__slots__, ())
295 self.assertEqual(Point.__module__, __name__)
296 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000297 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000298
299 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
300 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
301 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
302
303 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
304 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
305 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000306 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000307 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
308
309 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000310 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000311
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000312 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000313 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000314 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000315 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000316
Christian Heimesfaf2f632008-01-06 16:59:19 +0000317 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
318 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
319
Raymond Hettinger39482072018-01-10 21:45:19 -0800320 def test_defaults(self):
321 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700322 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800323 self.assertEqual(Point(1, 2), (1, 2))
324 self.assertEqual(Point(1), (1, 20))
325 self.assertEqual(Point(), (10, 20))
326
327 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700328 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800329 self.assertEqual(Point(1, 2), (1, 2))
330 self.assertEqual(Point(1), (1, 20))
331
332 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700333 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800334 self.assertEqual(Point(1, 2), (1, 2))
335 with self.assertRaises(TypeError):
336 Point(1)
337
338 with self.assertRaises(TypeError): # catch too few args
339 Point()
340 with self.assertRaises(TypeError): # catch too many args
341 Point(1, 2, 3)
342 with self.assertRaises(TypeError): # too many defaults
343 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
344 with self.assertRaises(TypeError): # non-iterable defaults
345 Point = namedtuple('Point', 'x y', defaults=10)
346 with self.assertRaises(TypeError): # another non-iterable default
347 Point = namedtuple('Point', 'x y', defaults=False)
348
349 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700350 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800351 self.assertIsNone(Point.__new__.__defaults__, None)
352 self.assertEqual(Point(10, 20), (10, 20))
353 with self.assertRaises(TypeError): # catch too few args
354 Point(10)
355
356 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700357 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800358 self.assertEqual(Point.__new__.__defaults__, (10, 20))
359 self.assertEqual(Point(1, 2), (1, 2))
360 self.assertEqual(Point(1), (1, 20))
361 self.assertEqual(Point(), (10, 20))
362
363 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700364 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800365 self.assertEqual(Point.__new__.__defaults__, (10, 20))
366 self.assertEqual(Point(1, 2), (1, 2))
367 self.assertEqual(Point(1), (1, 20))
368 self.assertEqual(Point(), (10, 20))
369
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200370 def test_readonly(self):
371 Point = namedtuple('Point', 'x y')
372 p = Point(11, 22)
373 with self.assertRaises(AttributeError):
374 p.x = 33
375 with self.assertRaises(AttributeError):
376 del p.x
377 with self.assertRaises(TypeError):
378 p[0] = 33
379 with self.assertRaises(TypeError):
380 del p[0]
381 self.assertEqual(p.x, 11)
382 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800383
R. David Murray378c0cf2010-02-24 01:46:21 +0000384 @unittest.skipIf(sys.flags.optimize >= 2,
385 "Docstrings are omitted with -O2 and above")
386 def test_factory_doc_attr(self):
387 Point = namedtuple('Point', 'x y')
388 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200389 Point.__doc__ = '2D point'
390 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000391
Raymond Hettingereac503a2015-05-13 01:09:59 -0700392 @unittest.skipIf(sys.flags.optimize >= 2,
393 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200394 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700395 Point = namedtuple('Point', 'x y')
396 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200397 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700398 Point.x.__doc__ = 'docstring for Point.x'
399 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200400 # namedtuple can mutate doc of descriptors independently
401 Vector = namedtuple('Vector', 'x y')
402 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
403 Vector.x.__doc__ = 'docstring for Vector.x'
404 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
405
406 @support.cpython_only
407 @unittest.skipIf(sys.flags.optimize >= 2,
408 "Docstrings are omitted with -O2 and above")
409 def test_field_doc_reuse(self):
410 P = namedtuple('P', ['m', 'n'])
411 Q = namedtuple('Q', ['o', 'p'])
412 self.assertIs(P.m.__doc__, Q.o.__doc__)
413 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700414
Ammar Askara86b5222020-04-14 23:36:08 -0700415 @support.cpython_only
416 def test_field_repr(self):
417 Point = namedtuple('Point', 'x y')
418 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'Alias for field number 0')")
419 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'Alias for field number 1')")
420
421 Point.x.__doc__ = 'The x-coordinate'
422 Point.y.__doc__ = 'The y-coordinate'
423
424 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'The x-coordinate')")
425 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'The y-coordinate')")
426
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000427 def test_name_fixer(self):
428 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000429 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
430 [('abc', 'class'), ('abc', '_1')], # field has keyword
431 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
432 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
433 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
434 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000435 ]:
436 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
437
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700438 def test_module_parameter(self):
439 NT = namedtuple('NT', ['x', 'y'], module=collections)
440 self.assertEqual(NT.__module__, collections)
441
Guido van Rossumd8faa362007-04-27 19:54:29 +0000442 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000443 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000444 p = Point(11, 22)
445 self.assertEqual(p, Point(x=11, y=22))
446 self.assertEqual(p, Point(11, y=22))
447 self.assertEqual(p, Point(y=22, x=11))
448 self.assertEqual(p, Point(*(11, 22)))
449 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200450 self.assertRaises(TypeError, Point, 1) # too few args
451 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
452 with self.assertRaises(TypeError): # wrong keyword argument
453 Point(XXX=1, y=2)
454 with self.assertRaises(TypeError): # missing keyword argument
455 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000456 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000457 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200458 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
459 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
460 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
461 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000462
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000463 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000464 p._replace(x=1, error=2)
465 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000466 pass
467 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000468 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000469
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000470 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000471 Point = namedtuple('Point', 'x, y')
472 p = Point(x=11, y=22)
473 self.assertEqual(repr(p), 'Point(x=11, y=22)')
474
475 # verify that fieldspec can be a non-string sequence
476 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000477 p = Point(x=11, y=22)
478 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000479
480 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000481 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000482 p = Point(11, 22)
483
Ezio Melottie9615932010-01-24 19:26:24 +0000484 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000485 self.assertEqual(p, (11, 22)) # matches a real tuple
Min ho Kimc4cacc82019-07-31 08:16:13 +1000486 self.assertEqual(tuple(p), (11, 22)) # coercible to a real tuple
487 self.assertEqual(list(p), [11, 22]) # coercible to a list
Guido van Rossumd8faa362007-04-27 19:54:29 +0000488 self.assertEqual(max(p), 22) # iterable
489 self.assertEqual(max(*p), 22) # star-able
490 x, y = p
491 self.assertEqual(p, (x, y)) # unpacks like a tuple
492 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200493 with self.assertRaises(IndexError):
494 p[3]
495 self.assertEqual(p[-1], 22)
496 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000497
498 self.assertEqual(p.x, x)
499 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200500 with self.assertRaises(AttributeError):
501 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000502
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000503 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000504 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000506 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000507 self.assertEqual(repr(Zero()), 'Zero()')
508 self.assertEqual(Zero()._asdict(), {})
509 self.assertEqual(Zero()._fields, ())
510
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000511 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000512 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000513 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000514 self.assertEqual(Dot(1).d, 1)
515 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
516 self.assertEqual(Dot(1)._asdict(), {'d':1})
517 self.assertEqual(Dot(1)._replace(d=999), (999,))
518 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000519
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200520 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200521 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000522 for j in range(10)]) for i in range(n)))
523 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000524 Big = namedtuple('Big', names)
525 b = Big(*range(n))
526 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000527 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000528 for pos, name in enumerate(names):
529 self.assertEqual(getattr(b, name), pos)
530 repr(b) # make sure repr() doesn't blow-up
531 d = b._asdict()
532 d_expected = dict(zip(names, range(n)))
533 self.assertEqual(d, d_expected)
534 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
535 b2_expected = list(range(n))
536 b2_expected[1] = 999
537 b2_expected[-5] = 42
538 self.assertEqual(b2, tuple(b2_expected))
539 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000540
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000541 def test_pickle(self):
542 p = TestNT(x=10, y=20, z=30)
543 for module in (pickle,):
544 loads = getattr(module, 'loads')
545 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500546 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000547 q = loads(dumps(p, protocol))
548 self.assertEqual(p, q)
549 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700550 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000551
552 def test_copy(self):
553 p = TestNT(x=10, y=20, z=30)
554 for copier in copy.copy, copy.deepcopy:
555 q = copier(p)
556 self.assertEqual(p, q)
557 self.assertEqual(p._fields, q._fields)
558
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000559 def test_name_conflicts(self):
560 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
561 # failed when used as field names. Test to make sure these now work.
562 T = namedtuple('T', 'itemgetter property self cls tuple')
563 t = T(1, 2, 3, 4, 5)
564 self.assertEqual(t, (1,2,3,4,5))
565 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
566 self.assertEqual(newt, (10,20,30,40,50))
567
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700568 # Broader test of all interesting names taken from the code, old
569 # template, and an example
570 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
571 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
572 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
573 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
574 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
575 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
576 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
577 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
578 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
579 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
580 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
581 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
582 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
583 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
584 'instantiate', 'interning', 'introspection', 'isidentifier',
585 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
586 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
587 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
588 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
589 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
590 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
591 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
592 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
593 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
594 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
595 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
596 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
597 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
598 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000599 T = namedtuple('T', words)
600 # test __new__
601 values = tuple(range(len(words)))
602 t = T(*values)
603 self.assertEqual(t, values)
604 t = T(**dict(zip(T._fields, values)))
605 self.assertEqual(t, values)
606 # test _make
607 t = T._make(values)
608 self.assertEqual(t, values)
609 # exercise __repr__
610 repr(t)
611 # test _asdict
612 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
613 # test _replace
614 t = T._make(values)
615 newvalues = tuple(v*10 for v in values)
616 newt = t._replace(**dict(zip(T._fields, newvalues)))
617 self.assertEqual(newt, newvalues)
618 # test _fields
619 self.assertEqual(T._fields, tuple(words))
620 # test __getnewargs__
621 self.assertEqual(t.__getnewargs__(), values)
622
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000623 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700624 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000625 self.assertEqual(repr(A(1)), 'A(x=1)')
626 # repr should show the name of the subclass
627 class B(A):
628 pass
629 self.assertEqual(repr(B(1)), 'B(x=1)')
630
Raymond Hettinger6538b432016-08-16 10:55:43 -0700631 def test_keyword_only_arguments(self):
632 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700633 with self.assertRaises(TypeError):
634 NT = namedtuple('NT', ['x', 'y'], True)
635
636 NT = namedtuple('NT', ['abc', 'def'], rename=True)
637 self.assertEqual(NT._fields, ('abc', '_1'))
638 with self.assertRaises(TypeError):
639 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000640
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700641 def test_namedtuple_subclass_issue_24931(self):
642 class Point(namedtuple('_Point', ['x', 'y'])):
643 pass
644
645 a = Point(3, 4)
646 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
647
648 a.w = 5
649 self.assertEqual(a.__dict__, {'w': 5})
650
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200651 def test_field_descriptor(self):
652 Point = namedtuple('Point', 'x y')
653 p = Point(11, 22)
654 self.assertTrue(inspect.isdatadescriptor(Point.x))
655 self.assertEqual(Point.x.__get__(p), 11)
656 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
657 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000658
Joe Jevnikf36f8922019-02-21 16:00:40 -0500659 class NewPoint(tuple):
660 x = pickle.loads(pickle.dumps(Point.x))
661 y = pickle.loads(pickle.dumps(Point.y))
662
663 np = NewPoint([1, 2])
664
665 self.assertEqual(np.x, 1)
666 self.assertEqual(np.y, 2)
667
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700668
Raymond Hettinger499e1932011-02-23 07:56:53 +0000669################################################################################
670### Abstract Base Classes
671################################################################################
672
Raymond Hettingerae650182009-01-28 23:33:59 +0000673class ABCTestCase(unittest.TestCase):
674
675 def validate_abstract_methods(self, abc, *names):
676 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
677
678 # everything should work will all required methods are present
679 C = type('C', (abc,), methodstubs)
680 C()
681
682 # instantiation should fail if a required method is missing
683 for name in names:
684 stubs = methodstubs.copy()
685 del stubs[name]
686 C = type('C', (abc,), stubs)
687 self.assertRaises(TypeError, C, name)
688
Florent Xiclunace153f62010-03-08 15:34:35 +0000689 def validate_isinstance(self, abc, name):
690 stub = lambda s, *args: 0
691
692 C = type('C', (object,), {'__hash__': None})
693 setattr(C, name, stub)
694 self.assertIsInstance(C(), abc)
695 self.assertTrue(issubclass(C, abc))
696
697 C = type('C', (object,), {'__hash__': None})
698 self.assertNotIsInstance(C(), abc)
699 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000700
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000701 def validate_comparison(self, instance):
702 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
703 operators = {}
704 for op in ops:
705 name = '__' + op + '__'
706 operators[name] = getattr(operator, name)
707
708 class Other:
709 def __init__(self):
710 self.right_side = False
711 def __eq__(self, other):
712 self.right_side = True
713 return True
714 __lt__ = __eq__
715 __gt__ = __eq__
716 __le__ = __eq__
717 __ge__ = __eq__
718 __ne__ = __eq__
719 __ror__ = __eq__
720 __rand__ = __eq__
721 __rxor__ = __eq__
722 __rsub__ = __eq__
723
724 for name, op in operators.items():
725 if not hasattr(instance, name):
726 continue
727 other = Other()
728 op(instance, other)
729 self.assertTrue(other.right_side,'Right side not called for %s.%s'
730 % (type(instance), name))
731
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700732def _test_gen():
733 yield
734
Raymond Hettingerae650182009-01-28 23:33:59 +0000735class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000736
Yury Selivanov75445082015-05-11 22:57:16 -0400737 def test_Awaitable(self):
738 def gen():
739 yield
740
741 @types.coroutine
742 def coro():
743 yield
744
745 async def new_coro():
746 pass
747
748 class Bar:
749 def __await__(self):
750 yield
751
752 class MinimalCoro(Coroutine):
753 def send(self, value):
754 return value
755 def throw(self, typ, val=None, tb=None):
756 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400757 def __await__(self):
758 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400759
760 non_samples = [None, int(), gen(), object()]
761 for x in non_samples:
762 self.assertNotIsInstance(x, Awaitable)
763 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
764
765 samples = [Bar(), MinimalCoro()]
766 for x in samples:
767 self.assertIsInstance(x, Awaitable)
768 self.assertTrue(issubclass(type(x), Awaitable))
769
770 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400771 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
772 # flag don't have '__await__' method, hence can't be instances
773 # of Awaitable. Use inspect.isawaitable to detect them.
774 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400775
776 c = new_coro()
777 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300778 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400779
Yury Selivanov56fc6142015-05-29 09:01:29 -0400780 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400781 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400782 self.assertTrue(isinstance(CoroLike(), Awaitable))
783 self.assertTrue(issubclass(CoroLike, Awaitable))
784 CoroLike = None
785 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400786
Yury Selivanov75445082015-05-11 22:57:16 -0400787 def test_Coroutine(self):
788 def gen():
789 yield
790
791 @types.coroutine
792 def coro():
793 yield
794
795 async def new_coro():
796 pass
797
798 class Bar:
799 def __await__(self):
800 yield
801
802 class MinimalCoro(Coroutine):
803 def send(self, value):
804 return value
805 def throw(self, typ, val=None, tb=None):
806 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400807 def __await__(self):
808 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400809
810 non_samples = [None, int(), gen(), object(), Bar()]
811 for x in non_samples:
812 self.assertNotIsInstance(x, Coroutine)
813 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
814
815 samples = [MinimalCoro()]
816 for x in samples:
817 self.assertIsInstance(x, Awaitable)
818 self.assertTrue(issubclass(type(x), Awaitable))
819
820 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400821 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
822 # flag don't have '__await__' method, hence can't be instances
823 # of Coroutine. Use inspect.isawaitable to detect them.
824 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400825
826 c = new_coro()
827 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300828 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400829
Yury Selivanov56fc6142015-05-29 09:01:29 -0400830 class CoroLike:
831 def send(self, value):
832 pass
833 def throw(self, typ, val=None, tb=None):
834 pass
835 def close(self):
836 pass
837 def __await__(self):
838 pass
839 self.assertTrue(isinstance(CoroLike(), Coroutine))
840 self.assertTrue(issubclass(CoroLike, Coroutine))
841
842 class CoroLike:
843 def send(self, value):
844 pass
845 def close(self):
846 pass
847 def __await__(self):
848 pass
849 self.assertFalse(isinstance(CoroLike(), Coroutine))
850 self.assertFalse(issubclass(CoroLike, Coroutine))
851
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000852 def test_Hashable(self):
853 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000854 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000855 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000856 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000857 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000858 # Check some hashables
859 samples = [None,
860 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000861 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000862 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000863 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000864 ]
865 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000866 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000867 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000868 self.assertRaises(TypeError, Hashable)
869 # Check direct subclassing
870 class H(Hashable):
871 def __hash__(self):
872 return super().__hash__()
873 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000874 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000875 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000876 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000877
Yury Selivanove0104ae2015-05-14 12:19:16 -0400878 def test_AsyncIterable(self):
879 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400880 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400881 return self
882 self.assertTrue(isinstance(AI(), AsyncIterable))
883 self.assertTrue(issubclass(AI, AsyncIterable))
884 # Check some non-iterables
885 non_samples = [None, object, []]
886 for x in non_samples:
887 self.assertNotIsInstance(x, AsyncIterable)
888 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
889 self.validate_abstract_methods(AsyncIterable, '__aiter__')
890 self.validate_isinstance(AsyncIterable, '__aiter__')
891
892 def test_AsyncIterator(self):
893 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400894 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400895 return self
896 async def __anext__(self):
897 raise StopAsyncIteration
898 self.assertTrue(isinstance(AI(), AsyncIterator))
899 self.assertTrue(issubclass(AI, AsyncIterator))
900 non_samples = [None, object, []]
901 # Check some non-iterables
902 for x in non_samples:
903 self.assertNotIsInstance(x, AsyncIterator)
904 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
905 # Similarly to regular iterators (see issue 10565)
906 class AnextOnly:
907 async def __anext__(self):
908 raise StopAsyncIteration
909 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
910 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
911
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000912 def test_Iterable(self):
913 # Check some non-iterables
914 non_samples = [None, 42, 3.14, 1j]
915 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000916 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000917 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000918 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000919 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000920 tuple(), list(), set(), frozenset(), dict(),
921 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700922 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000923 (x for x in []),
924 ]
925 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000926 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000927 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000928 # Check direct subclassing
929 class I(Iterable):
930 def __iter__(self):
931 return super().__iter__()
932 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000933 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000934 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000935 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700936 # Check None blocking
937 class It:
938 def __iter__(self): return iter([])
939 class ItBlocked(It):
940 __iter__ = None
941 self.assertTrue(issubclass(It, Iterable))
942 self.assertTrue(isinstance(It(), Iterable))
943 self.assertFalse(issubclass(ItBlocked, Iterable))
944 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000945
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700946 def test_Reversible(self):
947 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100948 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700949 for x in non_samples:
950 self.assertNotIsInstance(x, Reversible)
951 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700952 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100953 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700954 for x in non_reversibles:
955 self.assertNotIsInstance(x, Reversible)
956 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
957 # Check some reversible iterables
958 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
959 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100960 OrderedDict().values(), Counter(), Counter().keys(),
961 Counter().items(), Counter().values(), dict(),
962 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700963 for x in samples:
964 self.assertIsInstance(x, Reversible)
965 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
966 # Check also Mapping, MutableMapping, and Sequence
967 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
968 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
969 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
970 # Check direct subclassing
971 class R(Reversible):
972 def __iter__(self):
973 return iter(list())
974 def __reversed__(self):
975 return iter(list())
976 self.assertEqual(list(reversed(R())), [])
977 self.assertFalse(issubclass(float, R))
978 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700979 # Check reversible non-iterable (which is not Reversible)
980 class RevNoIter:
981 def __reversed__(self): return reversed([])
982 class RevPlusIter(RevNoIter):
983 def __iter__(self): return iter([])
984 self.assertFalse(issubclass(RevNoIter, Reversible))
985 self.assertFalse(isinstance(RevNoIter(), Reversible))
986 self.assertTrue(issubclass(RevPlusIter, Reversible))
987 self.assertTrue(isinstance(RevPlusIter(), Reversible))
988 # Check None blocking
989 class Rev:
990 def __iter__(self): return iter([])
991 def __reversed__(self): return reversed([])
992 class RevItBlocked(Rev):
993 __iter__ = None
994 class RevRevBlocked(Rev):
995 __reversed__ = None
996 self.assertTrue(issubclass(Rev, Reversible))
997 self.assertTrue(isinstance(Rev(), Reversible))
998 self.assertFalse(issubclass(RevItBlocked, Reversible))
999 self.assertFalse(isinstance(RevItBlocked(), Reversible))
1000 self.assertFalse(issubclass(RevRevBlocked, Reversible))
1001 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001002
Guido van Rossumf0666942016-08-23 10:47:07 -07001003 def test_Collection(self):
1004 # Check some non-collections
1005 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
1006 for x in non_collections:
1007 self.assertNotIsInstance(x, Collection)
1008 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1009 # Check some non-collection iterables
1010 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001011 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -07001012 for x in non_col_iterables:
1013 self.assertNotIsInstance(x, Collection)
1014 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1015 # Check some collections
1016 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001017 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001018 for x in samples:
1019 self.assertIsInstance(x, Collection)
1020 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1021 # Check also Mapping, MutableMapping, etc.
1022 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1023 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1024 self.assertTrue(issubclass(MutableMapping, Collection),
1025 repr(MutableMapping))
1026 self.assertTrue(issubclass(Set, Collection), repr(Set))
1027 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1028 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1029 # Check direct subclassing
1030 class Col(Collection):
1031 def __iter__(self):
1032 return iter(list())
1033 def __len__(self):
1034 return 0
1035 def __contains__(self, item):
1036 return False
1037 class DerCol(Col): pass
1038 self.assertEqual(list(iter(Col())), [])
1039 self.assertFalse(issubclass(list, Col))
1040 self.assertFalse(issubclass(set, Col))
1041 self.assertFalse(issubclass(float, Col))
1042 self.assertEqual(list(iter(DerCol())), [])
1043 self.assertFalse(issubclass(list, DerCol))
1044 self.assertFalse(issubclass(set, DerCol))
1045 self.assertFalse(issubclass(float, DerCol))
1046 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1047 '__contains__')
1048 # Check sized container non-iterable (which is not Collection) etc.
1049 class ColNoIter:
1050 def __len__(self): return 0
1051 def __contains__(self, item): return False
1052 class ColNoSize:
1053 def __iter__(self): return iter([])
1054 def __contains__(self, item): return False
1055 class ColNoCont:
1056 def __iter__(self): return iter([])
1057 def __len__(self): return 0
1058 self.assertFalse(issubclass(ColNoIter, Collection))
1059 self.assertFalse(isinstance(ColNoIter(), Collection))
1060 self.assertFalse(issubclass(ColNoSize, Collection))
1061 self.assertFalse(isinstance(ColNoSize(), Collection))
1062 self.assertFalse(issubclass(ColNoCont, Collection))
1063 self.assertFalse(isinstance(ColNoCont(), Collection))
1064 # Check None blocking
1065 class SizeBlock:
1066 def __iter__(self): return iter([])
1067 def __contains__(self): return False
1068 __len__ = None
1069 class IterBlock:
1070 def __len__(self): return 0
1071 def __contains__(self): return True
1072 __iter__ = None
1073 self.assertFalse(issubclass(SizeBlock, Collection))
1074 self.assertFalse(isinstance(SizeBlock(), Collection))
1075 self.assertFalse(issubclass(IterBlock, Collection))
1076 self.assertFalse(isinstance(IterBlock(), Collection))
1077 # Check None blocking in subclass
1078 class ColImpl:
1079 def __iter__(self):
1080 return iter(list())
1081 def __len__(self):
1082 return 0
1083 def __contains__(self, item):
1084 return False
1085 class NonCol(ColImpl):
1086 __contains__ = None
1087 self.assertFalse(issubclass(NonCol, Collection))
1088 self.assertFalse(isinstance(NonCol(), Collection))
1089
1090
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001091 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001092 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001093 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001094 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001095 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001096 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001097 iter(tuple()), iter(list()), iter(dict()),
1098 iter(set()), iter(frozenset()),
1099 iter(dict().keys()), iter(dict().items()),
1100 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001101 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001102 (x for x in []),
1103 ]
1104 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001105 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001106 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001107 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1108
1109 # Issue 10565
1110 class NextOnly:
1111 def __next__(self):
1112 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001113 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001114 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001115
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001116 def test_Generator(self):
1117 class NonGen1:
1118 def __iter__(self): return self
1119 def __next__(self): return None
1120 def close(self): pass
1121 def throw(self, typ, val=None, tb=None): pass
1122
1123 class NonGen2:
1124 def __iter__(self): return self
1125 def __next__(self): return None
1126 def close(self): pass
1127 def send(self, value): return value
1128
1129 class NonGen3:
1130 def close(self): pass
1131 def send(self, value): return value
1132 def throw(self, typ, val=None, tb=None): pass
1133
1134 non_samples = [
1135 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1136 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1137 for x in non_samples:
1138 self.assertNotIsInstance(x, Generator)
1139 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1140
1141 class Gen:
1142 def __iter__(self): return self
1143 def __next__(self): return None
1144 def close(self): pass
1145 def send(self, value): return value
1146 def throw(self, typ, val=None, tb=None): pass
1147
1148 class MinimalGen(Generator):
1149 def send(self, value):
1150 return value
1151 def throw(self, typ, val=None, tb=None):
1152 super().throw(typ, val, tb)
1153
1154 def gen():
1155 yield 1
1156
1157 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1158 for x in samples:
1159 self.assertIsInstance(x, Iterator)
1160 self.assertIsInstance(x, Generator)
1161 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1162 self.validate_abstract_methods(Generator, 'send', 'throw')
1163
1164 # mixin tests
1165 mgen = MinimalGen()
1166 self.assertIs(mgen, iter(mgen))
1167 self.assertIs(mgen.send(None), next(mgen))
1168 self.assertEqual(2, mgen.send(2))
1169 self.assertIsNone(mgen.close())
1170 self.assertRaises(ValueError, mgen.throw, ValueError)
1171 self.assertRaisesRegex(ValueError, "^huhu$",
1172 mgen.throw, ValueError, ValueError("huhu"))
1173 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1174
1175 class FailOnClose(Generator):
1176 def send(self, value): return value
1177 def throw(self, *args): raise ValueError
1178
1179 self.assertRaises(ValueError, FailOnClose().close)
1180
1181 class IgnoreGeneratorExit(Generator):
1182 def send(self, value): return value
1183 def throw(self, *args): pass
1184
1185 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1186
Yury Selivanov22214ab2016-11-16 18:25:04 -05001187 def test_AsyncGenerator(self):
1188 class NonAGen1:
1189 def __aiter__(self): return self
1190 def __anext__(self): return None
1191 def aclose(self): pass
1192 def athrow(self, typ, val=None, tb=None): pass
1193
1194 class NonAGen2:
1195 def __aiter__(self): return self
1196 def __anext__(self): return None
1197 def aclose(self): pass
1198 def asend(self, value): return value
1199
1200 class NonAGen3:
1201 def aclose(self): pass
1202 def asend(self, value): return value
1203 def athrow(self, typ, val=None, tb=None): pass
1204
1205 non_samples = [
1206 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1207 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1208 for x in non_samples:
1209 self.assertNotIsInstance(x, AsyncGenerator)
1210 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1211
1212 class Gen:
1213 def __aiter__(self): return self
1214 async def __anext__(self): return None
1215 async def aclose(self): pass
1216 async def asend(self, value): return value
1217 async def athrow(self, typ, val=None, tb=None): pass
1218
1219 class MinimalAGen(AsyncGenerator):
1220 async def asend(self, value):
1221 return value
1222 async def athrow(self, typ, val=None, tb=None):
1223 await super().athrow(typ, val, tb)
1224
1225 async def gen():
1226 yield 1
1227
1228 samples = [gen(), Gen(), MinimalAGen()]
1229 for x in samples:
1230 self.assertIsInstance(x, AsyncIterator)
1231 self.assertIsInstance(x, AsyncGenerator)
1232 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1233 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1234
1235 def run_async(coro):
1236 result = None
1237 while True:
1238 try:
1239 coro.send(None)
1240 except StopIteration as ex:
1241 result = ex.args[0] if ex.args else None
1242 break
1243 return result
1244
1245 # mixin tests
1246 mgen = MinimalAGen()
1247 self.assertIs(mgen, mgen.__aiter__())
1248 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1249 self.assertEqual(2, run_async(mgen.asend(2)))
1250 self.assertIsNone(run_async(mgen.aclose()))
1251 with self.assertRaises(ValueError):
1252 run_async(mgen.athrow(ValueError))
1253
1254 class FailOnClose(AsyncGenerator):
1255 async def asend(self, value): return value
1256 async def athrow(self, *args): raise ValueError
1257
1258 with self.assertRaises(ValueError):
1259 run_async(FailOnClose().aclose())
1260
1261 class IgnoreGeneratorExit(AsyncGenerator):
1262 async def asend(self, value): return value
1263 async def athrow(self, *args): pass
1264
1265 with self.assertRaises(RuntimeError):
1266 run_async(IgnoreGeneratorExit().aclose())
1267
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001268 def test_Sized(self):
1269 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001270 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001271 (x for x in []),
1272 ]
1273 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001274 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001275 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001276 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001277 tuple(), list(), set(), frozenset(), dict(),
1278 dict().keys(), dict().items(), dict().values(),
1279 ]
1280 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001281 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001282 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001283 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001284 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001285
1286 def test_Container(self):
1287 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001288 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001289 (x for x in []),
1290 ]
1291 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001292 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001293 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001294 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001295 tuple(), list(), set(), frozenset(), dict(),
1296 dict().keys(), dict().items(),
1297 ]
1298 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001299 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001300 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001301 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001302 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001303
1304 def test_Callable(self):
1305 non_samples = [None, 42, 3.14, 1j,
1306 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001307 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001308 (x for x in []),
1309 ]
1310 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001311 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001312 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001313 samples = [lambda: None,
1314 type, int, object,
1315 len,
1316 list.append, [].append,
1317 ]
1318 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001319 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001320 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001321 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001322 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001323
1324 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001325 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001326 class C(B):
1327 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001328 self.assertTrue(issubclass(C, B))
1329 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001330
1331 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001332 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001333 class C:
1334 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001335 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001336 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001337 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001338
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001339class WithSet(MutableSet):
1340
1341 def __init__(self, it=()):
1342 self.data = set(it)
1343
1344 def __len__(self):
1345 return len(self.data)
1346
1347 def __iter__(self):
1348 return iter(self.data)
1349
1350 def __contains__(self, item):
1351 return item in self.data
1352
1353 def add(self, item):
1354 self.data.add(item)
1355
1356 def discard(self, item):
1357 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001358
Raymond Hettingerae650182009-01-28 23:33:59 +00001359class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001360
1361 # XXX For now, we only test some virtual inheritance properties.
1362 # We should also test the proper behavior of the collection ABCs
1363 # as real base classes or mix-in classes.
1364
1365 def test_Set(self):
1366 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001367 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001368 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001369 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001370 class MySet(Set):
1371 def __contains__(self, x):
1372 return False
1373 def __len__(self):
1374 return 0
1375 def __iter__(self):
1376 return iter([])
1377 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001378
Benjamin Peterson41181742008-07-02 20:22:54 +00001379 def test_hash_Set(self):
1380 class OneTwoThreeSet(Set):
1381 def __init__(self):
1382 self.contents = [1, 2, 3]
1383 def __contains__(self, x):
1384 return x in self.contents
1385 def __len__(self):
1386 return len(self.contents)
1387 def __iter__(self):
1388 return iter(self.contents)
1389 def __hash__(self):
1390 return self._hash()
1391 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001392 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001393
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001394 def test_isdisjoint_Set(self):
1395 class MySet(Set):
1396 def __init__(self, itr):
1397 self.contents = itr
1398 def __contains__(self, x):
1399 return x in self.contents
1400 def __iter__(self):
1401 return iter(self.contents)
1402 def __len__(self):
1403 return len([x for x in self.contents])
1404 s1 = MySet((1, 2, 3))
1405 s2 = MySet((4, 5, 6))
1406 s3 = MySet((1, 5, 6))
1407 self.assertTrue(s1.isdisjoint(s2))
1408 self.assertFalse(s1.isdisjoint(s3))
1409
1410 def test_equality_Set(self):
1411 class MySet(Set):
1412 def __init__(self, itr):
1413 self.contents = itr
1414 def __contains__(self, x):
1415 return x in self.contents
1416 def __iter__(self):
1417 return iter(self.contents)
1418 def __len__(self):
1419 return len([x for x in self.contents])
1420 s1 = MySet((1,))
1421 s2 = MySet((1, 2))
1422 s3 = MySet((3, 4))
1423 s4 = MySet((3, 4))
1424 self.assertTrue(s2 > s1)
1425 self.assertTrue(s1 < s2)
1426 self.assertFalse(s2 <= s1)
1427 self.assertFalse(s2 <= s3)
1428 self.assertFalse(s1 >= s2)
1429 self.assertEqual(s3, s4)
1430 self.assertNotEqual(s2, s3)
1431
1432 def test_arithmetic_Set(self):
1433 class MySet(Set):
1434 def __init__(self, itr):
1435 self.contents = itr
1436 def __contains__(self, x):
1437 return x in self.contents
1438 def __iter__(self):
1439 return iter(self.contents)
1440 def __len__(self):
1441 return len([x for x in self.contents])
1442 s1 = MySet((1, 2, 3))
1443 s2 = MySet((3, 4, 5))
1444 s3 = s1 & s2
1445 self.assertEqual(s3, MySet((3,)))
1446
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001447 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001448 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001449 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001450 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001451 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001452 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1453 'add', 'discard')
1454
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001455 def test_issue_5647(self):
1456 # MutableSet.__iand__ mutated the set during iteration
1457 s = WithSet('abcd')
1458 s &= WithSet('cdef') # This used to fail
1459 self.assertEqual(set(s), set('cd'))
1460
Raymond Hettingerae650182009-01-28 23:33:59 +00001461 def test_issue_4920(self):
1462 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001463 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001464 __slots__=['__s']
1465 def __init__(self,items=None):
1466 if items is None:
1467 items=[]
1468 self.__s=set(items)
1469 def __contains__(self,v):
1470 return v in self.__s
1471 def __iter__(self):
1472 return iter(self.__s)
1473 def __len__(self):
1474 return len(self.__s)
1475 def add(self,v):
1476 result=v not in self.__s
1477 self.__s.add(v)
1478 return result
1479 def discard(self,v):
1480 result=v in self.__s
1481 self.__s.discard(v)
1482 return result
1483 def __repr__(self):
1484 return "MySet(%s)" % repr(list(self))
1485 s = MySet([5,43,2,1])
1486 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001487
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001488 def test_issue8750(self):
1489 empty = WithSet()
1490 full = WithSet(range(10))
1491 s = WithSet(full)
1492 s -= s
1493 self.assertEqual(s, empty)
1494 s = WithSet(full)
1495 s ^= s
1496 self.assertEqual(s, empty)
1497 s = WithSet(full)
1498 s &= s
1499 self.assertEqual(s, full)
1500 s |= s
1501 self.assertEqual(s, full)
1502
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001503 def test_issue16373(self):
1504 # Recursion error comparing comparable and noncomparable
1505 # Set instances
1506 class MyComparableSet(Set):
1507 def __contains__(self, x):
1508 return False
1509 def __len__(self):
1510 return 0
1511 def __iter__(self):
1512 return iter([])
1513 class MyNonComparableSet(Set):
1514 def __contains__(self, x):
1515 return False
1516 def __len__(self):
1517 return 0
1518 def __iter__(self):
1519 return iter([])
1520 def __le__(self, x):
1521 return NotImplemented
1522 def __lt__(self, x):
1523 return NotImplemented
1524
1525 cs = MyComparableSet()
1526 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001527 self.assertFalse(ncs < cs)
1528 self.assertTrue(ncs <= cs)
1529 self.assertFalse(ncs > cs)
1530 self.assertTrue(ncs >= cs)
1531
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001532 def test_issue26915(self):
1533 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001534 class CustomSequence(Sequence):
1535 def __init__(self, seq):
1536 self._seq = seq
1537 def __getitem__(self, index):
1538 return self._seq[index]
1539 def __len__(self):
1540 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001541
1542 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001543 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001544 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001545 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001546 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001547 ItemsView({1: nan, 2: obj}),
1548 ValuesView({1: nan, 2: obj})
1549 ]
1550 for container in containers:
1551 for elem in container:
1552 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001553 self.assertEqual(seq.index(nan), 0)
1554 self.assertEqual(seq.index(obj), 1)
1555 self.assertEqual(seq.count(nan), 2)
1556 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001557
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001558 def assertSameSet(self, s1, s2):
1559 # coerce both to a real set then check equality
1560 self.assertSetEqual(set(s1), set(s2))
1561
1562 def test_Set_interoperability_with_real_sets(self):
1563 # Issue: 8743
1564 class ListSet(Set):
1565 def __init__(self, elements=()):
1566 self.data = []
1567 for elem in elements:
1568 if elem not in self.data:
1569 self.data.append(elem)
1570 def __contains__(self, elem):
1571 return elem in self.data
1572 def __iter__(self):
1573 return iter(self.data)
1574 def __len__(self):
1575 return len(self.data)
1576 def __repr__(self):
1577 return 'Set({!r})'.format(self.data)
1578
1579 r1 = set('abc')
1580 r2 = set('bcd')
1581 r3 = set('abcde')
1582 f1 = ListSet('abc')
1583 f2 = ListSet('bcd')
1584 f3 = ListSet('abcde')
1585 l1 = list('abccba')
1586 l2 = list('bcddcb')
1587 l3 = list('abcdeedcba')
1588
1589 target = r1 & r2
1590 self.assertSameSet(f1 & f2, target)
1591 self.assertSameSet(f1 & r2, target)
1592 self.assertSameSet(r2 & f1, target)
1593 self.assertSameSet(f1 & l2, target)
1594
1595 target = r1 | r2
1596 self.assertSameSet(f1 | f2, target)
1597 self.assertSameSet(f1 | r2, target)
1598 self.assertSameSet(r2 | f1, target)
1599 self.assertSameSet(f1 | l2, target)
1600
1601 fwd_target = r1 - r2
1602 rev_target = r2 - r1
1603 self.assertSameSet(f1 - f2, fwd_target)
1604 self.assertSameSet(f2 - f1, rev_target)
1605 self.assertSameSet(f1 - r2, fwd_target)
1606 self.assertSameSet(f2 - r1, rev_target)
1607 self.assertSameSet(r1 - f2, fwd_target)
1608 self.assertSameSet(r2 - f1, rev_target)
1609 self.assertSameSet(f1 - l2, fwd_target)
1610 self.assertSameSet(f2 - l1, rev_target)
1611
1612 target = r1 ^ r2
1613 self.assertSameSet(f1 ^ f2, target)
1614 self.assertSameSet(f1 ^ r2, target)
1615 self.assertSameSet(r2 ^ f1, target)
1616 self.assertSameSet(f1 ^ l2, target)
1617
1618 # Don't change the following to use assertLess or other
1619 # "more specific" unittest assertions. The current
1620 # assertTrue/assertFalse style makes the pattern of test
1621 # case combinations clear and allows us to know for sure
1622 # the exact operator being invoked.
1623
1624 # proper subset
1625 self.assertTrue(f1 < f3)
1626 self.assertFalse(f1 < f1)
1627 self.assertFalse(f1 < f2)
1628 self.assertTrue(r1 < f3)
1629 self.assertFalse(r1 < f1)
1630 self.assertFalse(r1 < f2)
1631 self.assertTrue(r1 < r3)
1632 self.assertFalse(r1 < r1)
1633 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001634 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001635 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001636 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001637 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001638 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001639 f1 < l2
1640
1641 # any subset
1642 self.assertTrue(f1 <= f3)
1643 self.assertTrue(f1 <= f1)
1644 self.assertFalse(f1 <= f2)
1645 self.assertTrue(r1 <= f3)
1646 self.assertTrue(r1 <= f1)
1647 self.assertFalse(r1 <= f2)
1648 self.assertTrue(r1 <= r3)
1649 self.assertTrue(r1 <= r1)
1650 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001651 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001652 f1 <= l3
1653 with self.assertRaises(TypeError):
1654 f1 <= l1
1655 with self.assertRaises(TypeError):
1656 f1 <= l2
1657
1658 # proper superset
1659 self.assertTrue(f3 > f1)
1660 self.assertFalse(f1 > f1)
1661 self.assertFalse(f2 > f1)
1662 self.assertTrue(r3 > r1)
1663 self.assertFalse(f1 > r1)
1664 self.assertFalse(f2 > r1)
1665 self.assertTrue(r3 > r1)
1666 self.assertFalse(r1 > r1)
1667 self.assertFalse(r2 > r1)
1668 with self.assertRaises(TypeError):
1669 f1 > l3
1670 with self.assertRaises(TypeError):
1671 f1 > l1
1672 with self.assertRaises(TypeError):
1673 f1 > l2
1674
1675 # any superset
1676 self.assertTrue(f3 >= f1)
1677 self.assertTrue(f1 >= f1)
1678 self.assertFalse(f2 >= f1)
1679 self.assertTrue(r3 >= r1)
1680 self.assertTrue(f1 >= r1)
1681 self.assertFalse(f2 >= r1)
1682 self.assertTrue(r3 >= r1)
1683 self.assertTrue(r1 >= r1)
1684 self.assertFalse(r2 >= r1)
1685 with self.assertRaises(TypeError):
1686 f1 >= l3
1687 with self.assertRaises(TypeError):
1688 f1 >=l1
1689 with self.assertRaises(TypeError):
1690 f1 >= l2
1691
1692 # equality
1693 self.assertTrue(f1 == f1)
1694 self.assertTrue(r1 == f1)
1695 self.assertTrue(f1 == r1)
1696 self.assertFalse(f1 == f3)
1697 self.assertFalse(r1 == f3)
1698 self.assertFalse(f1 == r3)
1699 self.assertFalse(f1 == l3)
1700 self.assertFalse(f1 == l1)
1701 self.assertFalse(f1 == l2)
1702
1703 # inequality
1704 self.assertFalse(f1 != f1)
1705 self.assertFalse(r1 != f1)
1706 self.assertFalse(f1 != r1)
1707 self.assertTrue(f1 != f3)
1708 self.assertTrue(r1 != f3)
1709 self.assertTrue(f1 != r3)
1710 self.assertTrue(f1 != l3)
1711 self.assertTrue(f1 != l1)
1712 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001713
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001714 def test_Mapping(self):
1715 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001716 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001717 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001718 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1719 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001720 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001721 def __len__(self):
1722 return 0
1723 def __getitem__(self, i):
1724 raise IndexError
1725 def __iter__(self):
1726 return iter(())
1727 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001728 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001729
1730 def test_MutableMapping(self):
1731 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001732 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001733 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001734 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1735 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001736
Raymond Hettinger9117c752010-08-22 07:44:24 +00001737 def test_MutableMapping_subclass(self):
1738 # Test issue 9214
1739 mymap = UserDict()
1740 mymap['red'] = 5
1741 self.assertIsInstance(mymap.keys(), Set)
1742 self.assertIsInstance(mymap.keys(), KeysView)
1743 self.assertIsInstance(mymap.items(), Set)
1744 self.assertIsInstance(mymap.items(), ItemsView)
1745
1746 mymap = UserDict()
1747 mymap['red'] = 5
1748 z = mymap.keys() | {'orange'}
1749 self.assertIsInstance(z, set)
1750 list(z)
1751 mymap['blue'] = 7 # Shouldn't affect 'z'
1752 self.assertEqual(sorted(z), ['orange', 'red'])
1753
1754 mymap = UserDict()
1755 mymap['red'] = 5
1756 z = mymap.items() | {('orange', 3)}
1757 self.assertIsInstance(z, set)
1758 list(z)
1759 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001760 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001761
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001762 def test_Sequence(self):
1763 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001764 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001765 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001766 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001767 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001768 self.assertIsInstance(memoryview(b""), Sequence)
1769 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001770 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001771 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1772 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001773
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001774 def test_Sequence_mixins(self):
1775 class SequenceSubclass(Sequence):
1776 def __init__(self, seq=()):
1777 self.seq = seq
1778
1779 def __getitem__(self, index):
1780 return self.seq[index]
1781
1782 def __len__(self):
1783 return len(self.seq)
1784
1785 # Compare Sequence.index() behavior to (list|str).index() behavior
1786 def assert_index_same(seq1, seq2, index_args):
1787 try:
1788 expected = seq1.index(*index_args)
1789 except ValueError:
1790 with self.assertRaises(ValueError):
1791 seq2.index(*index_args)
1792 else:
1793 actual = seq2.index(*index_args)
1794 self.assertEqual(
1795 actual, expected, '%r.index%s' % (seq1, index_args))
1796
1797 for ty in list, str:
1798 nativeseq = ty('abracadabra')
1799 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1800 seqseq = SequenceSubclass(nativeseq)
1801 for letter in set(nativeseq) | {'z'}:
1802 assert_index_same(nativeseq, seqseq, (letter,))
1803 for start in range(-3, len(nativeseq) + 3):
1804 assert_index_same(nativeseq, seqseq, (letter, start))
1805 for stop in range(-3, len(nativeseq) + 3):
1806 assert_index_same(
1807 nativeseq, seqseq, (letter, start, stop))
1808
Guido van Rossumd05eb002007-11-21 22:26:24 +00001809 def test_ByteString(self):
1810 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001811 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001812 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001813 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001814 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001815 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001816 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001817 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001818
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001819 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001820 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001821 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001822 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001823 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001824 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001825 self.assertTrue(issubclass(sample, MutableSequence))
1826 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001827 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1828 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001829
Eli Bendersky0716a572011-03-04 10:38:14 +00001830 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001831 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001832 # class inherited from it.
1833 class MutableSequenceSubclass(MutableSequence):
1834 def __init__(self):
1835 self.lst = []
1836
1837 def __setitem__(self, index, value):
1838 self.lst[index] = value
1839
1840 def __getitem__(self, index):
1841 return self.lst[index]
1842
1843 def __len__(self):
1844 return len(self.lst)
1845
1846 def __delitem__(self, index):
1847 del self.lst[index]
1848
1849 def insert(self, index, value):
1850 self.lst.insert(index, value)
1851
1852 mss = MutableSequenceSubclass()
1853 mss.append(0)
1854 mss.extend((1, 2, 3, 4))
1855 self.assertEqual(len(mss), 5)
1856 self.assertEqual(mss[3], 3)
1857 mss.reverse()
1858 self.assertEqual(mss[3], 1)
1859 mss.pop()
1860 self.assertEqual(len(mss), 4)
1861 mss.remove(3)
1862 self.assertEqual(len(mss), 3)
1863 mss += (10, 20, 30)
1864 self.assertEqual(len(mss), 6)
1865 self.assertEqual(mss[-1], 30)
1866 mss.clear()
1867 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001868
Naris R1b5f9c92018-08-31 02:56:14 +10001869 # issue 34427
1870 # extending self should not cause infinite loop
1871 items = 'ABCD'
1872 mss2 = MutableSequenceSubclass()
1873 mss2.extend(items + items)
1874 mss.clear()
1875 mss.extend(items)
1876 mss.extend(mss)
1877 self.assertEqual(len(mss), len(mss2))
1878 self.assertEqual(list(mss), list(mss2))
1879
1880
Raymond Hettinger499e1932011-02-23 07:56:53 +00001881################################################################################
1882### Counter
1883################################################################################
1884
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001885class CounterSubclassWithSetItem(Counter):
1886 # Test a counter subclass that overrides __setitem__
1887 def __init__(self, *args, **kwds):
1888 self.called = False
1889 Counter.__init__(self, *args, **kwds)
1890 def __setitem__(self, key, value):
1891 self.called = True
1892 Counter.__setitem__(self, key, value)
1893
1894class CounterSubclassWithGet(Counter):
1895 # Test a counter subclass that overrides get()
1896 def __init__(self, *args, **kwds):
1897 self.called = False
1898 Counter.__init__(self, *args, **kwds)
1899 def get(self, key, default):
1900 self.called = True
1901 return Counter.get(self, key, default)
1902
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001903class TestCounter(unittest.TestCase):
1904
1905 def test_basics(self):
1906 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001907 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1908 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001909 self.assertIsInstance(c, dict)
1910 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001911 self.assertTrue(issubclass(Counter, dict))
1912 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001913 self.assertEqual(len(c), 3)
1914 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001915 self.assertEqual(list(c.values()), [3, 2, 1])
1916 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1917 self.assertEqual(list(c), ['a', 'b', 'c'])
1918 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001919 [('a', 3), ('b', 2), ('c', 1)])
1920 self.assertEqual(c['b'], 2)
1921 self.assertEqual(c['z'], 0)
1922 self.assertEqual(c.__contains__('c'), True)
1923 self.assertEqual(c.__contains__('z'), False)
1924 self.assertEqual(c.get('b', 10), 2)
1925 self.assertEqual(c.get('z', 10), 10)
1926 self.assertEqual(c, dict(a=3, b=2, c=1))
1927 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1928 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1929 for i in range(5):
1930 self.assertEqual(c.most_common(i),
1931 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001932 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001933 c['a'] += 1 # increment an existing value
1934 c['b'] -= 2 # sub existing value to zero
1935 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001936 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001937 c['d'] -= 2 # sub from a missing value
1938 c['e'] = -5 # directly assign a missing value
1939 c['f'] += 4 # add to a missing value
1940 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001941 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001942 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001943 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001944 for i in range(3):
1945 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001946 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001947 c.clear()
1948 self.assertEqual(c, {})
1949 self.assertEqual(repr(c), 'Counter()')
1950 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1951 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001952 c.update(dict(a=5, b=3))
1953 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001954 c.update(Counter('a' * 50 + 'b' * 30))
1955 c.update() # test case with no args
1956 c.__init__('a' * 500 + 'b' * 300)
1957 c.__init__('cdc')
1958 c.__init__()
1959 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1960 self.assertEqual(c.setdefault('d', 5), 1)
1961 self.assertEqual(c['d'], 1)
1962 self.assertEqual(c.setdefault('e', 5), 5)
1963 self.assertEqual(c['e'], 5)
1964
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001965 def test_init(self):
1966 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1967 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1968 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1969 self.assertRaises(TypeError, Counter, 42)
1970 self.assertRaises(TypeError, Counter, (), ())
1971 self.assertRaises(TypeError, Counter.__init__)
1972
Raymond Hettinger407c7342019-02-21 09:19:00 -08001973 def test_order_preservation(self):
1974 # Input order dictates items() order
1975 self.assertEqual(list(Counter('abracadabra').items()),
1976 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
1977 # letters with same count: ^----------^ ^---------^
1978
1979 # Verify retention of order even when all counts are equal
1980 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
1981 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
1982
1983 # Input order dictates elements() order
1984 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
1985 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
1986 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
1987
1988 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10001989 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08001990 ps = 'aaabbcdddeefggghhijjjkkl'
1991 qs = 'abbcccdeefffhkkllllmmnno'
1992 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
1993 def correctly_ordered(seq):
1994 'Return true if the letters occur in the expected order'
1995 positions = [order[letter] for letter in seq]
1996 return positions == sorted(positions)
1997
1998 p, q = Counter(ps), Counter(qs)
1999 self.assertTrue(correctly_ordered(+p))
2000 self.assertTrue(correctly_ordered(-p))
2001 self.assertTrue(correctly_ordered(p + q))
2002 self.assertTrue(correctly_ordered(p - q))
2003 self.assertTrue(correctly_ordered(p | q))
2004 self.assertTrue(correctly_ordered(p & q))
2005
2006 p, q = Counter(ps), Counter(qs)
2007 p += q
2008 self.assertTrue(correctly_ordered(p))
2009
2010 p, q = Counter(ps), Counter(qs)
2011 p -= q
2012 self.assertTrue(correctly_ordered(p))
2013
2014 p, q = Counter(ps), Counter(qs)
2015 p |= q
2016 self.assertTrue(correctly_ordered(p))
2017
2018 p, q = Counter(ps), Counter(qs)
2019 p &= q
2020 self.assertTrue(correctly_ordered(p))
2021
2022 p, q = Counter(ps), Counter(qs)
2023 p.update(q)
2024 self.assertTrue(correctly_ordered(p))
2025
2026 p, q = Counter(ps), Counter(qs)
2027 p.subtract(q)
2028 self.assertTrue(correctly_ordered(p))
2029
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002030 def test_update(self):
2031 c = Counter()
2032 c.update(self=42)
2033 self.assertEqual(list(c.items()), [('self', 42)])
2034 c = Counter()
2035 c.update(iterable=42)
2036 self.assertEqual(list(c.items()), [('iterable', 42)])
2037 c = Counter()
2038 c.update(iterable=None)
2039 self.assertEqual(list(c.items()), [('iterable', None)])
2040 self.assertRaises(TypeError, Counter().update, 42)
2041 self.assertRaises(TypeError, Counter().update, {}, {})
2042 self.assertRaises(TypeError, Counter.update)
2043
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002044 def test_copying(self):
2045 # Check that counters are copyable, deepcopyable, picklable, and
2046 #have a repr/eval round-trip
2047 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002048 def check(dup):
2049 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2050 self.assertIsNot(dup, words, msg)
2051 self.assertEqual(dup, words)
2052 check(words.copy())
2053 check(copy.copy(words))
2054 check(copy.deepcopy(words))
2055 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2056 with self.subTest(proto=proto):
2057 check(pickle.loads(pickle.dumps(words, proto)))
2058 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002059 update_test = Counter()
2060 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002061 check(update_test)
2062 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002063
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002064 def test_copy_subclass(self):
2065 class MyCounter(Counter):
2066 pass
2067 c = MyCounter('slartibartfast')
2068 d = c.copy()
2069 self.assertEqual(d, c)
2070 self.assertEqual(len(d), len(c))
2071 self.assertEqual(type(d), type(c))
2072
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002073 def test_conversions(self):
2074 # Convert to: set, list, dict
2075 s = 'she sells sea shells by the sea shore'
2076 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2077 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2078 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2079 self.assertEqual(set(Counter(s)), set(s))
2080
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002081 def test_invariant_for_the_in_operator(self):
2082 c = Counter(a=10, b=-2, c=0)
2083 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002084 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002085 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002086
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002087 def test_multiset_operations(self):
2088 # Verify that adding a zero counter will strip zeros and negatives
2089 c = Counter(a=10, b=-2, c=0) + Counter()
2090 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002091
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002092 elements = 'abcd'
2093 for i in range(1000):
2094 # test random pairs of multisets
2095 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002096 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002097 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002098 q.update(h=1, i=-1, j=0)
2099 for counterop, numberop in [
2100 (Counter.__add__, lambda x, y: max(0, x+y)),
2101 (Counter.__sub__, lambda x, y: max(0, x-y)),
2102 (Counter.__or__, lambda x, y: max(0,x,y)),
2103 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002104 ]:
2105 result = counterop(p, q)
2106 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002107 self.assertEqual(numberop(p[x], q[x]), result[x],
2108 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002109 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002110 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002111
2112 elements = 'abcdef'
2113 for i in range(100):
2114 # verify that random multisets with no repeats are exactly like sets
2115 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2116 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2117 for counterop, setop in [
2118 (Counter.__sub__, set.__sub__),
2119 (Counter.__or__, set.__or__),
2120 (Counter.__and__, set.__and__),
2121 ]:
2122 counter_result = counterop(p, q)
2123 set_result = setop(set(p.elements()), set(q.elements()))
2124 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002125
Raymond Hettinger1ca8fb12019-12-16 01:54:14 -08002126 def test_subset_superset_not_implemented(self):
2127 # Verify that multiset comparison operations are not implemented.
2128
2129 # These operations were intentionally omitted because multiset
2130 # comparison semantics conflict with existing dict equality semantics.
2131
2132 # For multisets, we would expect that if p<=q and p>=q are both true,
2133 # then p==q. However, dict equality semantics require that p!=q when
2134 # one of sets contains an element with a zero count and the other
2135 # doesn't.
2136
2137 p = Counter(a=1, b=0)
2138 q = Counter(a=1, c=0)
2139 self.assertNotEqual(p, q)
2140 with self.assertRaises(TypeError):
2141 p < q
2142 with self.assertRaises(TypeError):
2143 p <= q
2144 with self.assertRaises(TypeError):
2145 p > q
2146 with self.assertRaises(TypeError):
2147 p >= q
2148
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002149 def test_inplace_operations(self):
2150 elements = 'abcd'
2151 for i in range(1000):
2152 # test random pairs of multisets
2153 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2154 p.update(e=1, f=-1, g=0)
2155 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2156 q.update(h=1, i=-1, j=0)
2157 for inplace_op, regular_op in [
2158 (Counter.__iadd__, Counter.__add__),
2159 (Counter.__isub__, Counter.__sub__),
2160 (Counter.__ior__, Counter.__or__),
2161 (Counter.__iand__, Counter.__and__),
2162 ]:
2163 c = p.copy()
2164 c_id = id(c)
2165 regular_result = regular_op(c, q)
2166 inplace_result = inplace_op(c, q)
2167 self.assertEqual(inplace_result, regular_result)
2168 self.assertEqual(id(inplace_result), c_id)
2169
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002170 def test_subtract(self):
2171 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2172 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2173 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2174 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2175 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2176 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2177 c = Counter('aaabbcd')
2178 c.subtract('aaaabbcce')
2179 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002180
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002181 c = Counter()
2182 c.subtract(self=42)
2183 self.assertEqual(list(c.items()), [('self', -42)])
2184 c = Counter()
2185 c.subtract(iterable=42)
2186 self.assertEqual(list(c.items()), [('iterable', -42)])
2187 self.assertRaises(TypeError, Counter().subtract, 42)
2188 self.assertRaises(TypeError, Counter().subtract, {}, {})
2189 self.assertRaises(TypeError, Counter.subtract)
2190
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002191 def test_unary(self):
2192 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2193 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2194 self.assertEqual(dict(-c), dict(a=5))
2195
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002196 def test_repr_nonsortable(self):
2197 c = Counter(a=2, b=None)
2198 r = repr(c)
2199 self.assertIn("'a': 2", r)
2200 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002201
Raymond Hettinger426e0522011-01-03 02:12:02 +00002202 def test_helper_function(self):
2203 # two paths, one for real dicts and one for other mappings
2204 elems = list('abracadabra')
2205
2206 d = dict()
2207 _count_elements(d, elems)
2208 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2209
2210 m = OrderedDict()
2211 _count_elements(m, elems)
2212 self.assertEqual(m,
2213 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2214
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002215 # test fidelity to the pure python version
2216 c = CounterSubclassWithSetItem('abracadabra')
2217 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002218 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002219 c = CounterSubclassWithGet('abracadabra')
2220 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002221 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002222
Raymond Hettinger60398512020-05-28 08:35:46 -07002223 def test_multiset_operations_equivalent_to_set_operations(self):
2224 # When the multiplicities are all zero or one, multiset operations
2225 # are guaranteed to be equivalent to the corresponding operations
2226 # for regular sets.
2227 s = list(product(('a', 'b', 'c'), range(2)))
2228 powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
2229 counters = [Counter(dict(groups)) for groups in powerset]
2230 for cp, cq in product(counters, repeat=2):
2231 sp = set(cp.elements())
2232 sq = set(cq.elements())
2233 self.assertEqual(set(cp + cq), sp | sq)
2234 self.assertEqual(set(cp - cq), sp - sq)
2235 self.assertEqual(set(cp | cq), sp | sq)
2236 self.assertEqual(set(cp & cq), sp & sq)
2237 self.assertEqual(cp.isequal(cq), sp == sq)
2238 self.assertEqual(cp.issubset(cq), sp.issubset(sq))
2239 self.assertEqual(cp.issuperset(cq), sp.issuperset(sq))
2240 self.assertEqual(cp.isdisjoint(cq), sp.isdisjoint(sq))
2241
2242 def test_multiset_equal(self):
2243 self.assertTrue(Counter(a=3, b=2, c=0).isequal('ababa'))
2244 self.assertFalse(Counter(a=3, b=2).isequal('babab'))
2245
2246 def test_multiset_subset(self):
2247 self.assertTrue(Counter(a=3, b=2, c=0).issubset('ababa'))
2248 self.assertFalse(Counter(a=3, b=2).issubset('babab'))
2249
2250 def test_multiset_superset(self):
2251 self.assertTrue(Counter(a=3, b=2, c=0).issuperset('aab'))
2252 self.assertFalse(Counter(a=3, b=2, c=0).issuperset('aabd'))
2253
2254 def test_multiset_disjoint(self):
2255 self.assertTrue(Counter(a=3, b=2, c=0).isdisjoint('cde'))
2256 self.assertFalse(Counter(a=3, b=2, c=0).isdisjoint('bcd'))
2257
2258 def test_multiset_predicates_with_negative_counts(self):
2259 # Multiset predicates run on the output of the elements() method,
2260 # meaning that zero counts and negative counts are ignored.
2261 # The tests below confirm that we get that same results as the
2262 # tests above, even after a negative count has been included
2263 # in either *self* or *other*.
2264 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).isequal('ababa'))
2265 self.assertFalse(Counter(a=3, b=2, d=-1).isequal('babab'))
2266 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).issubset('ababa'))
2267 self.assertFalse(Counter(a=3, b=2, d=-1).issubset('babab'))
2268 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).issuperset('aab'))
2269 self.assertFalse(Counter(a=3, b=2, c=0, d=-1).issuperset('aabd'))
2270 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).isdisjoint('cde'))
2271 self.assertFalse(Counter(a=3, b=2, c=0, d=-1).isdisjoint('bcd'))
2272 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).isequal(Counter(a=3, b=2, c=-1)))
2273 self.assertFalse(Counter(a=3, b=2, d=-1).isequal(Counter(a=2, b=3, c=-1)))
2274 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).issubset(Counter(a=3, b=2, c=-1)))
2275 self.assertFalse(Counter(a=3, b=2, d=-1).issubset(Counter(a=2, b=3, c=-1)))
2276 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).issuperset(Counter(a=2, b=1, c=-1)))
2277 self.assertFalse(Counter(a=3, b=2, c=0, d=-1).issuperset(Counter(a=2, b=1, c=-1, d=1)))
2278 self.assertTrue(Counter(a=3, b=2, c=0, d=-1).isdisjoint(Counter(c=1, d=2, e=3, f=-1)))
2279 self.assertFalse(Counter(a=3, b=2, c=0, d=-1).isdisjoint(Counter(b=1, c=1, d=1, e=-1)))
2280
Raymond Hettinger499e1932011-02-23 07:56:53 +00002281
2282################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002283### Run tests
2284################################################################################
2285
Guido van Rossumd8faa362007-04-27 19:54:29 +00002286def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002287 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002288 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002289 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002290 TestUserObjects,
2291 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002292 support.run_unittest(*test_classes)
2293 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002294
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002295
Guido van Rossumd8faa362007-04-27 19:54:29 +00002296if __name__ == "__main__":
2297 test_main(verbose=True)