blob: 150c2a1c0e3498e45c5d2080592a958aad48419d [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
Richard Levasseur68f68fa2020-11-21 11:56:24 -08001562 def test_Set_from_iterable(self):
1563 """Verify _from_iterable overriden to an instance method works."""
1564 class SetUsingInstanceFromIterable(MutableSet):
1565 def __init__(self, values, created_by):
1566 if not created_by:
1567 raise ValueError(f'created_by must be specified')
1568 self.created_by = created_by
1569 self._values = set(values)
1570
1571 def _from_iterable(self, values):
1572 return type(self)(values, 'from_iterable')
1573
1574 def __contains__(self, value):
1575 return value in self._values
1576
1577 def __iter__(self):
1578 yield from self._values
1579
1580 def __len__(self):
1581 return len(self._values)
1582
1583 def add(self, value):
1584 self._values.add(value)
1585
1586 def discard(self, value):
1587 self._values.discard(value)
1588
1589 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
1590
1591 actual = impl - {1}
1592 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1593 self.assertEqual('from_iterable', actual.created_by)
1594 self.assertEqual({2, 3}, actual)
1595
1596 actual = impl | {4}
1597 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1598 self.assertEqual('from_iterable', actual.created_by)
1599 self.assertEqual({1, 2, 3, 4}, actual)
1600
1601 actual = impl & {2}
1602 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1603 self.assertEqual('from_iterable', actual.created_by)
1604 self.assertEqual({2}, actual)
1605
1606 actual = impl ^ {3, 4}
1607 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1608 self.assertEqual('from_iterable', actual.created_by)
1609 self.assertEqual({1, 2, 4}, actual)
1610
1611 # NOTE: ixor'ing with a list is important here: internally, __ixor__
1612 # only calls _from_iterable if the other value isn't already a Set.
1613 impl ^= [3, 4]
1614 self.assertIsInstance(impl, SetUsingInstanceFromIterable)
1615 self.assertEqual('test', impl.created_by)
1616 self.assertEqual({1, 2, 4}, impl)
1617
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001618 def test_Set_interoperability_with_real_sets(self):
1619 # Issue: 8743
1620 class ListSet(Set):
1621 def __init__(self, elements=()):
1622 self.data = []
1623 for elem in elements:
1624 if elem not in self.data:
1625 self.data.append(elem)
1626 def __contains__(self, elem):
1627 return elem in self.data
1628 def __iter__(self):
1629 return iter(self.data)
1630 def __len__(self):
1631 return len(self.data)
1632 def __repr__(self):
1633 return 'Set({!r})'.format(self.data)
1634
1635 r1 = set('abc')
1636 r2 = set('bcd')
1637 r3 = set('abcde')
1638 f1 = ListSet('abc')
1639 f2 = ListSet('bcd')
1640 f3 = ListSet('abcde')
1641 l1 = list('abccba')
1642 l2 = list('bcddcb')
1643 l3 = list('abcdeedcba')
1644
1645 target = r1 & r2
1646 self.assertSameSet(f1 & f2, target)
1647 self.assertSameSet(f1 & r2, target)
1648 self.assertSameSet(r2 & f1, target)
1649 self.assertSameSet(f1 & l2, target)
1650
1651 target = r1 | r2
1652 self.assertSameSet(f1 | f2, target)
1653 self.assertSameSet(f1 | r2, target)
1654 self.assertSameSet(r2 | f1, target)
1655 self.assertSameSet(f1 | l2, target)
1656
1657 fwd_target = r1 - r2
1658 rev_target = r2 - r1
1659 self.assertSameSet(f1 - f2, fwd_target)
1660 self.assertSameSet(f2 - f1, rev_target)
1661 self.assertSameSet(f1 - r2, fwd_target)
1662 self.assertSameSet(f2 - r1, rev_target)
1663 self.assertSameSet(r1 - f2, fwd_target)
1664 self.assertSameSet(r2 - f1, rev_target)
1665 self.assertSameSet(f1 - l2, fwd_target)
1666 self.assertSameSet(f2 - l1, rev_target)
1667
1668 target = r1 ^ r2
1669 self.assertSameSet(f1 ^ f2, target)
1670 self.assertSameSet(f1 ^ r2, target)
1671 self.assertSameSet(r2 ^ f1, target)
1672 self.assertSameSet(f1 ^ l2, target)
1673
1674 # Don't change the following to use assertLess or other
1675 # "more specific" unittest assertions. The current
1676 # assertTrue/assertFalse style makes the pattern of test
1677 # case combinations clear and allows us to know for sure
1678 # the exact operator being invoked.
1679
1680 # proper subset
1681 self.assertTrue(f1 < f3)
1682 self.assertFalse(f1 < f1)
1683 self.assertFalse(f1 < f2)
1684 self.assertTrue(r1 < f3)
1685 self.assertFalse(r1 < f1)
1686 self.assertFalse(r1 < f2)
1687 self.assertTrue(r1 < r3)
1688 self.assertFalse(r1 < r1)
1689 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001690 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001691 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001692 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001693 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001694 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001695 f1 < l2
1696
1697 # any subset
1698 self.assertTrue(f1 <= f3)
1699 self.assertTrue(f1 <= f1)
1700 self.assertFalse(f1 <= f2)
1701 self.assertTrue(r1 <= f3)
1702 self.assertTrue(r1 <= f1)
1703 self.assertFalse(r1 <= f2)
1704 self.assertTrue(r1 <= r3)
1705 self.assertTrue(r1 <= r1)
1706 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001707 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001708 f1 <= l3
1709 with self.assertRaises(TypeError):
1710 f1 <= l1
1711 with self.assertRaises(TypeError):
1712 f1 <= l2
1713
1714 # proper superset
1715 self.assertTrue(f3 > f1)
1716 self.assertFalse(f1 > f1)
1717 self.assertFalse(f2 > f1)
1718 self.assertTrue(r3 > r1)
1719 self.assertFalse(f1 > r1)
1720 self.assertFalse(f2 > r1)
1721 self.assertTrue(r3 > r1)
1722 self.assertFalse(r1 > r1)
1723 self.assertFalse(r2 > r1)
1724 with self.assertRaises(TypeError):
1725 f1 > l3
1726 with self.assertRaises(TypeError):
1727 f1 > l1
1728 with self.assertRaises(TypeError):
1729 f1 > l2
1730
1731 # any superset
1732 self.assertTrue(f3 >= f1)
1733 self.assertTrue(f1 >= f1)
1734 self.assertFalse(f2 >= f1)
1735 self.assertTrue(r3 >= r1)
1736 self.assertTrue(f1 >= r1)
1737 self.assertFalse(f2 >= r1)
1738 self.assertTrue(r3 >= r1)
1739 self.assertTrue(r1 >= r1)
1740 self.assertFalse(r2 >= r1)
1741 with self.assertRaises(TypeError):
1742 f1 >= l3
1743 with self.assertRaises(TypeError):
1744 f1 >=l1
1745 with self.assertRaises(TypeError):
1746 f1 >= l2
1747
1748 # equality
1749 self.assertTrue(f1 == f1)
1750 self.assertTrue(r1 == f1)
1751 self.assertTrue(f1 == r1)
1752 self.assertFalse(f1 == f3)
1753 self.assertFalse(r1 == f3)
1754 self.assertFalse(f1 == r3)
1755 self.assertFalse(f1 == l3)
1756 self.assertFalse(f1 == l1)
1757 self.assertFalse(f1 == l2)
1758
1759 # inequality
1760 self.assertFalse(f1 != f1)
1761 self.assertFalse(r1 != f1)
1762 self.assertFalse(f1 != r1)
1763 self.assertTrue(f1 != f3)
1764 self.assertTrue(r1 != f3)
1765 self.assertTrue(f1 != r3)
1766 self.assertTrue(f1 != l3)
1767 self.assertTrue(f1 != l1)
1768 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001769
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001770 def test_Mapping(self):
1771 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001772 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001773 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001774 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1775 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001776 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001777 def __len__(self):
1778 return 0
1779 def __getitem__(self, i):
1780 raise IndexError
1781 def __iter__(self):
1782 return iter(())
1783 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001784 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001785
1786 def test_MutableMapping(self):
1787 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001788 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001789 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001790 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1791 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001792
Raymond Hettinger9117c752010-08-22 07:44:24 +00001793 def test_MutableMapping_subclass(self):
1794 # Test issue 9214
1795 mymap = UserDict()
1796 mymap['red'] = 5
1797 self.assertIsInstance(mymap.keys(), Set)
1798 self.assertIsInstance(mymap.keys(), KeysView)
1799 self.assertIsInstance(mymap.items(), Set)
1800 self.assertIsInstance(mymap.items(), ItemsView)
1801
1802 mymap = UserDict()
1803 mymap['red'] = 5
1804 z = mymap.keys() | {'orange'}
1805 self.assertIsInstance(z, set)
1806 list(z)
1807 mymap['blue'] = 7 # Shouldn't affect 'z'
1808 self.assertEqual(sorted(z), ['orange', 'red'])
1809
1810 mymap = UserDict()
1811 mymap['red'] = 5
1812 z = mymap.items() | {('orange', 3)}
1813 self.assertIsInstance(z, set)
1814 list(z)
1815 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001816 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001817
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001818 def test_Sequence(self):
1819 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001820 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001821 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001822 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001823 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001824 self.assertIsInstance(memoryview(b""), Sequence)
1825 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001826 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001827 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1828 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001829
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001830 def test_Sequence_mixins(self):
1831 class SequenceSubclass(Sequence):
1832 def __init__(self, seq=()):
1833 self.seq = seq
1834
1835 def __getitem__(self, index):
1836 return self.seq[index]
1837
1838 def __len__(self):
1839 return len(self.seq)
1840
1841 # Compare Sequence.index() behavior to (list|str).index() behavior
1842 def assert_index_same(seq1, seq2, index_args):
1843 try:
1844 expected = seq1.index(*index_args)
1845 except ValueError:
1846 with self.assertRaises(ValueError):
1847 seq2.index(*index_args)
1848 else:
1849 actual = seq2.index(*index_args)
1850 self.assertEqual(
1851 actual, expected, '%r.index%s' % (seq1, index_args))
1852
1853 for ty in list, str:
1854 nativeseq = ty('abracadabra')
1855 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1856 seqseq = SequenceSubclass(nativeseq)
1857 for letter in set(nativeseq) | {'z'}:
1858 assert_index_same(nativeseq, seqseq, (letter,))
1859 for start in range(-3, len(nativeseq) + 3):
1860 assert_index_same(nativeseq, seqseq, (letter, start))
1861 for stop in range(-3, len(nativeseq) + 3):
1862 assert_index_same(
1863 nativeseq, seqseq, (letter, start, stop))
1864
Guido van Rossumd05eb002007-11-21 22:26:24 +00001865 def test_ByteString(self):
1866 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001867 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001868 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001869 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001870 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001871 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001872 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001873 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001874
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001875 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001876 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001877 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001878 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001879 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001880 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001881 self.assertTrue(issubclass(sample, MutableSequence))
1882 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001883 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1884 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001885
Eli Bendersky0716a572011-03-04 10:38:14 +00001886 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001887 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001888 # class inherited from it.
1889 class MutableSequenceSubclass(MutableSequence):
1890 def __init__(self):
1891 self.lst = []
1892
1893 def __setitem__(self, index, value):
1894 self.lst[index] = value
1895
1896 def __getitem__(self, index):
1897 return self.lst[index]
1898
1899 def __len__(self):
1900 return len(self.lst)
1901
1902 def __delitem__(self, index):
1903 del self.lst[index]
1904
1905 def insert(self, index, value):
1906 self.lst.insert(index, value)
1907
1908 mss = MutableSequenceSubclass()
1909 mss.append(0)
1910 mss.extend((1, 2, 3, 4))
1911 self.assertEqual(len(mss), 5)
1912 self.assertEqual(mss[3], 3)
1913 mss.reverse()
1914 self.assertEqual(mss[3], 1)
1915 mss.pop()
1916 self.assertEqual(len(mss), 4)
1917 mss.remove(3)
1918 self.assertEqual(len(mss), 3)
1919 mss += (10, 20, 30)
1920 self.assertEqual(len(mss), 6)
1921 self.assertEqual(mss[-1], 30)
1922 mss.clear()
1923 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001924
Naris R1b5f9c92018-08-31 02:56:14 +10001925 # issue 34427
1926 # extending self should not cause infinite loop
1927 items = 'ABCD'
1928 mss2 = MutableSequenceSubclass()
1929 mss2.extend(items + items)
1930 mss.clear()
1931 mss.extend(items)
1932 mss.extend(mss)
1933 self.assertEqual(len(mss), len(mss2))
1934 self.assertEqual(list(mss), list(mss2))
1935
1936
Raymond Hettinger499e1932011-02-23 07:56:53 +00001937################################################################################
1938### Counter
1939################################################################################
1940
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001941class CounterSubclassWithSetItem(Counter):
1942 # Test a counter subclass that overrides __setitem__
1943 def __init__(self, *args, **kwds):
1944 self.called = False
1945 Counter.__init__(self, *args, **kwds)
1946 def __setitem__(self, key, value):
1947 self.called = True
1948 Counter.__setitem__(self, key, value)
1949
1950class CounterSubclassWithGet(Counter):
1951 # Test a counter subclass that overrides get()
1952 def __init__(self, *args, **kwds):
1953 self.called = False
1954 Counter.__init__(self, *args, **kwds)
1955 def get(self, key, default):
1956 self.called = True
1957 return Counter.get(self, key, default)
1958
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001959class TestCounter(unittest.TestCase):
1960
1961 def test_basics(self):
1962 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001963 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1964 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001965 self.assertIsInstance(c, dict)
1966 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001967 self.assertTrue(issubclass(Counter, dict))
1968 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001969 self.assertEqual(len(c), 3)
1970 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001971 self.assertEqual(list(c.values()), [3, 2, 1])
1972 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1973 self.assertEqual(list(c), ['a', 'b', 'c'])
1974 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001975 [('a', 3), ('b', 2), ('c', 1)])
1976 self.assertEqual(c['b'], 2)
1977 self.assertEqual(c['z'], 0)
1978 self.assertEqual(c.__contains__('c'), True)
1979 self.assertEqual(c.__contains__('z'), False)
1980 self.assertEqual(c.get('b', 10), 2)
1981 self.assertEqual(c.get('z', 10), 10)
1982 self.assertEqual(c, dict(a=3, b=2, c=1))
1983 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1984 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1985 for i in range(5):
1986 self.assertEqual(c.most_common(i),
1987 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001988 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001989 c['a'] += 1 # increment an existing value
1990 c['b'] -= 2 # sub existing value to zero
1991 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001992 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001993 c['d'] -= 2 # sub from a missing value
1994 c['e'] = -5 # directly assign a missing value
1995 c['f'] += 4 # add to a missing value
1996 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001997 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001998 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001999 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002000 for i in range(3):
2001 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002002 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002003 c.clear()
2004 self.assertEqual(c, {})
2005 self.assertEqual(repr(c), 'Counter()')
2006 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
2007 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002008 c.update(dict(a=5, b=3))
2009 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002010 c.update(Counter('a' * 50 + 'b' * 30))
2011 c.update() # test case with no args
2012 c.__init__('a' * 500 + 'b' * 300)
2013 c.__init__('cdc')
2014 c.__init__()
2015 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
2016 self.assertEqual(c.setdefault('d', 5), 1)
2017 self.assertEqual(c['d'], 1)
2018 self.assertEqual(c.setdefault('e', 5), 5)
2019 self.assertEqual(c['e'], 5)
2020
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002021 def test_init(self):
2022 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
2023 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
2024 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
2025 self.assertRaises(TypeError, Counter, 42)
2026 self.assertRaises(TypeError, Counter, (), ())
2027 self.assertRaises(TypeError, Counter.__init__)
2028
Raymond Hettinger407c7342019-02-21 09:19:00 -08002029 def test_order_preservation(self):
2030 # Input order dictates items() order
2031 self.assertEqual(list(Counter('abracadabra').items()),
2032 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
2033 # letters with same count: ^----------^ ^---------^
2034
2035 # Verify retention of order even when all counts are equal
2036 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
2037 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
2038
2039 # Input order dictates elements() order
2040 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
2041 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
2042 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
2043
2044 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10002045 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08002046 ps = 'aaabbcdddeefggghhijjjkkl'
2047 qs = 'abbcccdeefffhkkllllmmnno'
2048 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
2049 def correctly_ordered(seq):
2050 'Return true if the letters occur in the expected order'
2051 positions = [order[letter] for letter in seq]
2052 return positions == sorted(positions)
2053
2054 p, q = Counter(ps), Counter(qs)
2055 self.assertTrue(correctly_ordered(+p))
2056 self.assertTrue(correctly_ordered(-p))
2057 self.assertTrue(correctly_ordered(p + q))
2058 self.assertTrue(correctly_ordered(p - q))
2059 self.assertTrue(correctly_ordered(p | q))
2060 self.assertTrue(correctly_ordered(p & q))
2061
2062 p, q = Counter(ps), Counter(qs)
2063 p += q
2064 self.assertTrue(correctly_ordered(p))
2065
2066 p, q = Counter(ps), Counter(qs)
2067 p -= q
2068 self.assertTrue(correctly_ordered(p))
2069
2070 p, q = Counter(ps), Counter(qs)
2071 p |= q
2072 self.assertTrue(correctly_ordered(p))
2073
2074 p, q = Counter(ps), Counter(qs)
2075 p &= q
2076 self.assertTrue(correctly_ordered(p))
2077
2078 p, q = Counter(ps), Counter(qs)
2079 p.update(q)
2080 self.assertTrue(correctly_ordered(p))
2081
2082 p, q = Counter(ps), Counter(qs)
2083 p.subtract(q)
2084 self.assertTrue(correctly_ordered(p))
2085
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002086 def test_update(self):
2087 c = Counter()
2088 c.update(self=42)
2089 self.assertEqual(list(c.items()), [('self', 42)])
2090 c = Counter()
2091 c.update(iterable=42)
2092 self.assertEqual(list(c.items()), [('iterable', 42)])
2093 c = Counter()
2094 c.update(iterable=None)
2095 self.assertEqual(list(c.items()), [('iterable', None)])
2096 self.assertRaises(TypeError, Counter().update, 42)
2097 self.assertRaises(TypeError, Counter().update, {}, {})
2098 self.assertRaises(TypeError, Counter.update)
2099
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002100 def test_copying(self):
2101 # Check that counters are copyable, deepcopyable, picklable, and
2102 #have a repr/eval round-trip
2103 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002104 def check(dup):
2105 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2106 self.assertIsNot(dup, words, msg)
2107 self.assertEqual(dup, words)
2108 check(words.copy())
2109 check(copy.copy(words))
2110 check(copy.deepcopy(words))
2111 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2112 with self.subTest(proto=proto):
2113 check(pickle.loads(pickle.dumps(words, proto)))
2114 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002115 update_test = Counter()
2116 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002117 check(update_test)
2118 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002119
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002120 def test_copy_subclass(self):
2121 class MyCounter(Counter):
2122 pass
2123 c = MyCounter('slartibartfast')
2124 d = c.copy()
2125 self.assertEqual(d, c)
2126 self.assertEqual(len(d), len(c))
2127 self.assertEqual(type(d), type(c))
2128
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002129 def test_conversions(self):
2130 # Convert to: set, list, dict
2131 s = 'she sells sea shells by the sea shore'
2132 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2133 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2134 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2135 self.assertEqual(set(Counter(s)), set(s))
2136
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002137 def test_invariant_for_the_in_operator(self):
2138 c = Counter(a=10, b=-2, c=0)
2139 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002140 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002141 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002142
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002143 def test_multiset_operations(self):
2144 # Verify that adding a zero counter will strip zeros and negatives
2145 c = Counter(a=10, b=-2, c=0) + Counter()
2146 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002147
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002148 elements = 'abcd'
2149 for i in range(1000):
2150 # test random pairs of multisets
2151 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002152 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002153 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002154 q.update(h=1, i=-1, j=0)
2155 for counterop, numberop in [
2156 (Counter.__add__, lambda x, y: max(0, x+y)),
2157 (Counter.__sub__, lambda x, y: max(0, x-y)),
2158 (Counter.__or__, lambda x, y: max(0,x,y)),
2159 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002160 ]:
2161 result = counterop(p, q)
2162 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002163 self.assertEqual(numberop(p[x], q[x]), result[x],
2164 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002165 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002166 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002167
2168 elements = 'abcdef'
2169 for i in range(100):
2170 # verify that random multisets with no repeats are exactly like sets
2171 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2172 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2173 for counterop, setop in [
2174 (Counter.__sub__, set.__sub__),
2175 (Counter.__or__, set.__or__),
2176 (Counter.__and__, set.__and__),
2177 ]:
2178 counter_result = counterop(p, q)
2179 set_result = setop(set(p.elements()), set(q.elements()))
2180 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002181
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002182 def test_inplace_operations(self):
2183 elements = 'abcd'
2184 for i in range(1000):
2185 # test random pairs of multisets
2186 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2187 p.update(e=1, f=-1, g=0)
2188 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2189 q.update(h=1, i=-1, j=0)
2190 for inplace_op, regular_op in [
2191 (Counter.__iadd__, Counter.__add__),
2192 (Counter.__isub__, Counter.__sub__),
2193 (Counter.__ior__, Counter.__or__),
2194 (Counter.__iand__, Counter.__and__),
2195 ]:
2196 c = p.copy()
2197 c_id = id(c)
2198 regular_result = regular_op(c, q)
2199 inplace_result = inplace_op(c, q)
2200 self.assertEqual(inplace_result, regular_result)
2201 self.assertEqual(id(inplace_result), c_id)
2202
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002203 def test_subtract(self):
2204 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2205 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2206 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2207 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2208 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2209 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2210 c = Counter('aaabbcd')
2211 c.subtract('aaaabbcce')
2212 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002213
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002214 c = Counter()
2215 c.subtract(self=42)
2216 self.assertEqual(list(c.items()), [('self', -42)])
2217 c = Counter()
2218 c.subtract(iterable=42)
2219 self.assertEqual(list(c.items()), [('iterable', -42)])
2220 self.assertRaises(TypeError, Counter().subtract, 42)
2221 self.assertRaises(TypeError, Counter().subtract, {}, {})
2222 self.assertRaises(TypeError, Counter.subtract)
2223
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002224 def test_unary(self):
2225 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2226 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2227 self.assertEqual(dict(-c), dict(a=5))
2228
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002229 def test_repr_nonsortable(self):
2230 c = Counter(a=2, b=None)
2231 r = repr(c)
2232 self.assertIn("'a': 2", r)
2233 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002234
Raymond Hettinger426e0522011-01-03 02:12:02 +00002235 def test_helper_function(self):
2236 # two paths, one for real dicts and one for other mappings
2237 elems = list('abracadabra')
2238
2239 d = dict()
2240 _count_elements(d, elems)
2241 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2242
2243 m = OrderedDict()
2244 _count_elements(m, elems)
2245 self.assertEqual(m,
2246 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2247
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002248 # test fidelity to the pure python version
2249 c = CounterSubclassWithSetItem('abracadabra')
2250 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002251 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002252 c = CounterSubclassWithGet('abracadabra')
2253 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002254 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002255
Raymond Hettinger60398512020-05-28 08:35:46 -07002256 def test_multiset_operations_equivalent_to_set_operations(self):
2257 # When the multiplicities are all zero or one, multiset operations
2258 # are guaranteed to be equivalent to the corresponding operations
2259 # for regular sets.
2260 s = list(product(('a', 'b', 'c'), range(2)))
2261 powerset = chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
2262 counters = [Counter(dict(groups)) for groups in powerset]
2263 for cp, cq in product(counters, repeat=2):
2264 sp = set(cp.elements())
2265 sq = set(cq.elements())
2266 self.assertEqual(set(cp + cq), sp | sq)
2267 self.assertEqual(set(cp - cq), sp - sq)
2268 self.assertEqual(set(cp | cq), sp | sq)
2269 self.assertEqual(set(cp & cq), sp & sq)
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002270 self.assertEqual(cp == cq, sp == sq)
2271 self.assertEqual(cp != cq, sp != sq)
2272 self.assertEqual(cp <= cq, sp <= sq)
2273 self.assertEqual(cp >= cq, sp >= sq)
2274 self.assertEqual(cp < cq, sp < sq)
2275 self.assertEqual(cp > cq, sp > sq)
Raymond Hettinger60398512020-05-28 08:35:46 -07002276
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002277 def test_eq(self):
2278 self.assertEqual(Counter(a=3, b=2, c=0), Counter('ababa'))
2279 self.assertNotEqual(Counter(a=3, b=2), Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002280
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002281 def test_le(self):
2282 self.assertTrue(Counter(a=3, b=2, c=0) <= Counter('ababa'))
2283 self.assertFalse(Counter(a=3, b=2) <= Counter('babab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002284
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002285 def test_lt(self):
2286 self.assertTrue(Counter(a=3, b=1, c=0) < Counter('ababa'))
2287 self.assertFalse(Counter(a=3, b=2, c=0) < Counter('ababa'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002288
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002289 def test_ge(self):
2290 self.assertTrue(Counter(a=2, b=1, c=0) >= Counter('aab'))
2291 self.assertFalse(Counter(a=3, b=2, c=0) >= Counter('aabd'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002292
Raymond Hettingerb7d79b42020-05-31 14:57:42 -07002293 def test_gt(self):
2294 self.assertTrue(Counter(a=3, b=2, c=0) > Counter('aab'))
2295 self.assertFalse(Counter(a=2, b=1, c=0) > Counter('aab'))
Raymond Hettinger60398512020-05-28 08:35:46 -07002296
Raymond Hettinger499e1932011-02-23 07:56:53 +00002297
2298################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002299### Run tests
2300################################################################################
2301
Guido van Rossumd8faa362007-04-27 19:54:29 +00002302def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002303 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002304 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002305 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002306 TestUserObjects,
2307 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002308 support.run_unittest(*test_classes)
2309 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002310
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002311
Guido van Rossumd8faa362007-04-27 19:54:29 +00002312if __name__ == "__main__":
2313 test_main(verbose=True)