blob: 057ec92015cf4f4ef72507bd75c53b52475cc9c2 [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
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020010import string
R. David Murray378c0cf2010-02-24 01:46:21 +000011import sys
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020012from test import support
Yury Selivanov75445082015-05-11 22:57:16 -040013import types
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +020014import unittest
15
Victor Stinner8f4ef3b2019-07-01 18:28:25 +020016from collections import namedtuple, Counter, OrderedDict, _count_elements
Raymond Hettinger573b44c2015-05-22 16:56:32 -070017from collections import UserDict, UserString, UserList
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000018from collections import ChainMap
Raymond Hettinger32ea1652015-03-21 01:37:37 -070019from collections import deque
Yury Selivanov22214ab2016-11-16 18:25:04 -050020from collections.abc import Awaitable, Coroutine
21from collections.abc import AsyncIterator, AsyncIterable, AsyncGenerator
Guido van Rossum16ca06b2016-04-04 10:59:29 -070022from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible
Guido van Rossumf0666942016-08-23 10:47:07 -070023from collections.abc import Sized, Container, Callable, Collection
Raymond Hettinger57d1a882011-02-23 00:46:28 +000024from collections.abc import Set, MutableSet
Raymond Hettinger584e8ae2016-05-05 11:14:06 +030025from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView
Raymond Hettinger57d1a882011-02-23 00:46:28 +000026from collections.abc import Sequence, MutableSequence
27from collections.abc import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000028
Raymond Hettinger499e1932011-02-23 07:56:53 +000029
Raymond Hettinger573b44c2015-05-22 16:56:32 -070030class TestUserObjects(unittest.TestCase):
31 def _superset_test(self, a, b):
32 self.assertGreaterEqual(
33 set(dir(a)),
34 set(dir(b)),
35 '{a} should have all the methods of {b}'.format(
36 a=a.__name__,
37 b=b.__name__,
38 ),
39 )
Bar Harelf4e1bab2019-05-19 16:57:13 +030040
41 def _copy_test(self, obj):
42 # Test internal copy
43 obj_copy = obj.copy()
44 self.assertIsNot(obj.data, obj_copy.data)
45 self.assertEqual(obj.data, obj_copy.data)
46
47 # Test copy.copy
48 obj.test = [1234] # Make sure instance vars are also copied.
49 obj_copy = copy.copy(obj)
50 self.assertIsNot(obj.data, obj_copy.data)
51 self.assertEqual(obj.data, obj_copy.data)
52 self.assertIs(obj.test, obj_copy.test)
53
Raymond Hettinger573b44c2015-05-22 16:56:32 -070054 def test_str_protocol(self):
55 self._superset_test(UserString, str)
56
57 def test_list_protocol(self):
58 self._superset_test(UserList, list)
59
60 def test_dict_protocol(self):
61 self._superset_test(UserDict, dict)
62
Bar Harelf4e1bab2019-05-19 16:57:13 +030063 def test_list_copy(self):
64 obj = UserList()
65 obj.append(123)
66 self._copy_test(obj)
67
68 def test_dict_copy(self):
69 obj = UserDict()
70 obj[123] = "abc"
71 self._copy_test(obj)
72
Raymond Hettinger573b44c2015-05-22 16:56:32 -070073
Raymond Hettinger499e1932011-02-23 07:56:53 +000074################################################################################
Raymond Hettinger9fe1ccf2011-02-26 01:02:51 +000075### ChainMap (helper class for configparser and the string module)
Raymond Hettinger499e1932011-02-23 07:56:53 +000076################################################################################
77
78class TestChainMap(unittest.TestCase):
79
80 def test_basics(self):
81 c = ChainMap()
82 c['a'] = 1
83 c['b'] = 2
84 d = c.new_child()
85 d['b'] = 20
86 d['c'] = 30
87 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
88 self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
89 self.assertEqual(len(d), 3) # check len
90 for key in 'abc': # check contains
91 self.assertIn(key, d)
92 for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
93 self.assertEqual(d.get(k, 100), v)
94
95 del d['b'] # unmask a value
96 self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
97 self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
98 self.assertEqual(len(d), 3) # check len
99 for key in 'abc': # check contains
100 self.assertIn(key, d)
101 for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
102 self.assertEqual(d.get(k, 100), v)
103 self.assertIn(repr(d), [ # check repr
104 type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
105 type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
106 ])
107
108 for e in d.copy(), copy.copy(d): # check shallow copies
109 self.assertEqual(d, e)
110 self.assertEqual(d.maps, e.maps)
111 self.assertIsNot(d, e)
112 self.assertIsNot(d.maps[0], e.maps[0])
113 for m1, m2 in zip(d.maps[1:], e.maps[1:]):
114 self.assertIs(m1, m2)
115
Serhiy Storchakabad12572014-12-15 14:03:42 +0200116 # check deep copies
117 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
118 e = pickle.loads(pickle.dumps(d, proto))
119 self.assertEqual(d, e)
120 self.assertEqual(d.maps, e.maps)
121 self.assertIsNot(d, e)
122 for m1, m2 in zip(d.maps, e.maps):
123 self.assertIsNot(m1, m2, e)
124 for e in [copy.deepcopy(d),
Raymond Hettinger499e1932011-02-23 07:56:53 +0000125 eval(repr(d))
Serhiy Storchakabad12572014-12-15 14:03:42 +0200126 ]:
Raymond Hettinger499e1932011-02-23 07:56:53 +0000127 self.assertEqual(d, e)
128 self.assertEqual(d.maps, e.maps)
129 self.assertIsNot(d, e)
130 for m1, m2 in zip(d.maps, e.maps):
131 self.assertIsNot(m1, m2, e)
132
Raymond Hettingerd0321312011-02-26 06:53:58 +0000133 f = d.new_child()
134 f['b'] = 5
135 self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
136 self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
137 self.assertEqual(f['b'], 5) # find first in chain
138 self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
Raymond Hettinger499e1932011-02-23 07:56:53 +0000139
Raymond Hettinger86f093f2019-02-21 09:12:15 -0800140 def test_ordering(self):
141 # Combined order matches a series of dict updates from last to first.
142 # This test relies on the ordering of the underlying dicts.
143
144 baseline = {'music': 'bach', 'art': 'rembrandt'}
145 adjustments = {'art': 'van gogh', 'opera': 'carmen'}
146
147 cm = ChainMap(adjustments, baseline)
148
149 combined = baseline.copy()
150 combined.update(adjustments)
151
152 self.assertEqual(list(combined.items()), list(cm.items()))
153
Martin Pantereb995702016-07-28 01:11:04 +0000154 def test_constructor(self):
Raymond Hettingerd0321312011-02-26 06:53:58 +0000155 self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
Raymond Hettinger499e1932011-02-23 07:56:53 +0000156 self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
157
Raymond Hettingerd0321312011-02-26 06:53:58 +0000158 def test_bool(self):
159 self.assertFalse(ChainMap())
160 self.assertFalse(ChainMap({}, {}))
161 self.assertTrue(ChainMap({1:2}, {}))
162 self.assertTrue(ChainMap({}, {1:2}))
163
Raymond Hettinger499e1932011-02-23 07:56:53 +0000164 def test_missing(self):
165 class DefaultChainMap(ChainMap):
166 def __missing__(self, key):
167 return 999
168 d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
169 for k, v in dict(a=1, b=2, c=30, d=999).items():
170 self.assertEqual(d[k], v) # check __getitem__ w/missing
171 for k, v in dict(a=1, b=2, c=30, d=77).items():
172 self.assertEqual(d.get(k, 77), v) # check get() w/ missing
173 for k, v in dict(a=True, b=True, c=True, d=False).items():
174 self.assertEqual(k in d, v) # check __contains__ w/missing
175 self.assertEqual(d.pop('a', 1001), 1, d)
176 self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
177 self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
178 with self.assertRaises(KeyError):
179 d.popitem()
180
Raymond Hettinger3793f952018-02-11 00:30:31 -0800181 def test_order_preservation(self):
182 d = ChainMap(
183 OrderedDict(j=0, h=88888),
184 OrderedDict(),
185 OrderedDict(i=9999, d=4444, c=3333),
186 OrderedDict(f=666, b=222, g=777, c=333, h=888),
187 OrderedDict(),
188 OrderedDict(e=55, b=22),
189 OrderedDict(a=1, b=2, c=3, d=4, e=5),
190 OrderedDict(),
191 )
192 self.assertEqual(''.join(d), 'abcdefghij')
193 self.assertEqual(list(d.items()),
194 [('a', 1), ('b', 222), ('c', 3333), ('d', 4444),
195 ('e', 55), ('f', 666), ('g', 777), ('h', 88888),
196 ('i', 9999), ('j', 0)])
197
Miss Islington (bot)cf22aa32020-11-30 09:07:26 -0800198 def test_iter_not_calling_getitem_on_maps(self):
199 class DictWithGetItem(UserDict):
200 def __init__(self, *args, **kwds):
201 self.called = False
202 UserDict.__init__(self, *args, **kwds)
203 def __getitem__(self, item):
204 self.called = True
205 UserDict.__getitem__(self, item)
206
207 d = DictWithGetItem(a=1)
208 c = ChainMap(d)
209 d.called = False
210
211 set(c) # iterate over chain map
212 self.assertFalse(d.called, '__getitem__ was called')
213
Raymond Hettinger499e1932011-02-23 07:56:53 +0000214 def test_dict_coercion(self):
215 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
216 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
217 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
218
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000219 def test_new_child(self):
220 'Tests for changes for issue #16613.'
221 c = ChainMap()
222 c['a'] = 1
223 c['b'] = 2
224 m = {'b':20, 'c': 30}
225 d = c.new_child(m)
226 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
227 self.assertIs(m, d.maps[0])
228
229 # Use a different map than a dict
230 class lowerdict(dict):
231 def __getitem__(self, key):
232 if isinstance(key, str):
233 key = key.lower()
234 return dict.__getitem__(self, key)
235 def __contains__(self, key):
236 if isinstance(key, str):
237 key = key.lower()
238 return dict.__contains__(self, key)
239
240 c = ChainMap()
241 c['a'] = 1
242 c['b'] = 2
243 m = lowerdict(b=20, c=30)
244 d = c.new_child(m)
245 self.assertIs(m, d.maps[0])
246 for key in 'abc': # check contains
247 self.assertIn(key, d)
248 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
249 self.assertEqual(d.get(k, 100), v)
250
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700251 def test_union_operators(self):
252 cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
253 cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
254 cm3 = cm1.copy()
255 d = dict(a=10, c=30)
256 pairs = [('c', 3), ('p',0)]
257
258 tmp = cm1 | cm2 # testing between chainmaps
259 self.assertEqual(tmp.maps, [cm1.maps[0] | dict(cm2), *cm1.maps[1:]])
260 cm1 |= cm2
261 self.assertEqual(tmp, cm1)
262
263 tmp = cm2 | d # testing between chainmap and mapping
264 self.assertEqual(tmp.maps, [cm2.maps[0] | d, *cm2.maps[1:]])
265 self.assertEqual((d | cm2).maps, [d | dict(cm2)])
266 cm2 |= d
267 self.assertEqual(tmp, cm2)
268
269 # testing behavior between chainmap and iterable key-value pairs
270 with self.assertRaises(TypeError):
271 cm3 | pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700272 tmp = cm3.copy()
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700273 cm3 |= pairs
Curtis Bucher0c5ad542020-03-30 09:50:57 -0700274 self.assertEqual(cm3.maps, [tmp.maps[0] | dict(pairs), *tmp.maps[1:]])
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700275
276 # testing proper return types for ChainMap and it's subclasses
277 class Subclass(ChainMap):
278 pass
279
280 class SubclassRor(ChainMap):
281 def __ror__(self, other):
282 return super().__ror__(other)
283
284 tmp = ChainMap() | ChainMap()
285 self.assertIs(type(tmp), ChainMap)
286 self.assertIs(type(tmp.maps[0]), dict)
287 tmp = ChainMap() | Subclass()
288 self.assertIs(type(tmp), ChainMap)
289 self.assertIs(type(tmp.maps[0]), dict)
290 tmp = Subclass() | ChainMap()
291 self.assertIs(type(tmp), Subclass)
292 self.assertIs(type(tmp.maps[0]), dict)
293 tmp = ChainMap() | SubclassRor()
294 self.assertIs(type(tmp), SubclassRor)
295 self.assertIs(type(tmp.maps[0]), dict)
296
Raymond Hettinger499e1932011-02-23 07:56:53 +0000297
298################################################################################
299### Named Tuples
300################################################################################
301
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000302TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000303
304class TestNamedTuple(unittest.TestCase):
305
306 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000307 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000308 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000309 self.assertEqual(Point.__slots__, ())
310 self.assertEqual(Point.__module__, __name__)
311 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000312 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000313
314 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
315 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
316 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
317
318 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
319 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
320 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000321 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000322 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
323
324 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000325 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000326
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000327 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000328 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000329 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000330 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000331
Christian Heimesfaf2f632008-01-06 16:59:19 +0000332 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
333 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
334
Raymond Hettinger39482072018-01-10 21:45:19 -0800335 def test_defaults(self):
336 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700337 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800338 self.assertEqual(Point(1, 2), (1, 2))
339 self.assertEqual(Point(1), (1, 20))
340 self.assertEqual(Point(), (10, 20))
341
342 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700343 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800344 self.assertEqual(Point(1, 2), (1, 2))
345 self.assertEqual(Point(1), (1, 20))
346
347 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700348 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800349 self.assertEqual(Point(1, 2), (1, 2))
350 with self.assertRaises(TypeError):
351 Point(1)
352
353 with self.assertRaises(TypeError): # catch too few args
354 Point()
355 with self.assertRaises(TypeError): # catch too many args
356 Point(1, 2, 3)
357 with self.assertRaises(TypeError): # too many defaults
358 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
359 with self.assertRaises(TypeError): # non-iterable defaults
360 Point = namedtuple('Point', 'x y', defaults=10)
361 with self.assertRaises(TypeError): # another non-iterable default
362 Point = namedtuple('Point', 'x y', defaults=False)
363
364 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700365 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800366 self.assertIsNone(Point.__new__.__defaults__, None)
367 self.assertEqual(Point(10, 20), (10, 20))
368 with self.assertRaises(TypeError): # catch too few args
369 Point(10)
370
371 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700372 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800373 self.assertEqual(Point.__new__.__defaults__, (10, 20))
374 self.assertEqual(Point(1, 2), (1, 2))
375 self.assertEqual(Point(1), (1, 20))
376 self.assertEqual(Point(), (10, 20))
377
378 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700379 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800380 self.assertEqual(Point.__new__.__defaults__, (10, 20))
381 self.assertEqual(Point(1, 2), (1, 2))
382 self.assertEqual(Point(1), (1, 20))
383 self.assertEqual(Point(), (10, 20))
384
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200385 def test_readonly(self):
386 Point = namedtuple('Point', 'x y')
387 p = Point(11, 22)
388 with self.assertRaises(AttributeError):
389 p.x = 33
390 with self.assertRaises(AttributeError):
391 del p.x
392 with self.assertRaises(TypeError):
393 p[0] = 33
394 with self.assertRaises(TypeError):
395 del p[0]
396 self.assertEqual(p.x, 11)
397 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800398
R. David Murray378c0cf2010-02-24 01:46:21 +0000399 @unittest.skipIf(sys.flags.optimize >= 2,
400 "Docstrings are omitted with -O2 and above")
401 def test_factory_doc_attr(self):
402 Point = namedtuple('Point', 'x y')
403 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200404 Point.__doc__ = '2D point'
405 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000406
Raymond Hettingereac503a2015-05-13 01:09:59 -0700407 @unittest.skipIf(sys.flags.optimize >= 2,
408 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200409 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700410 Point = namedtuple('Point', 'x y')
411 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200412 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700413 Point.x.__doc__ = 'docstring for Point.x'
414 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200415 # namedtuple can mutate doc of descriptors independently
416 Vector = namedtuple('Vector', 'x y')
417 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
418 Vector.x.__doc__ = 'docstring for Vector.x'
419 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
420
421 @support.cpython_only
422 @unittest.skipIf(sys.flags.optimize >= 2,
423 "Docstrings are omitted with -O2 and above")
424 def test_field_doc_reuse(self):
425 P = namedtuple('P', ['m', 'n'])
426 Q = namedtuple('Q', ['o', 'p'])
427 self.assertIs(P.m.__doc__, Q.o.__doc__)
428 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700429
Ammar Askara86b5222020-04-14 23:36:08 -0700430 @support.cpython_only
431 def test_field_repr(self):
432 Point = namedtuple('Point', 'x y')
433 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'Alias for field number 0')")
434 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'Alias for field number 1')")
435
436 Point.x.__doc__ = 'The x-coordinate'
437 Point.y.__doc__ = 'The y-coordinate'
438
439 self.assertEqual(repr(Point.x), "_tuplegetter(0, 'The x-coordinate')")
440 self.assertEqual(repr(Point.y), "_tuplegetter(1, 'The y-coordinate')")
441
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000442 def test_name_fixer(self):
443 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000444 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
445 [('abc', 'class'), ('abc', '_1')], # field has keyword
446 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
447 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
448 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
449 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000450 ]:
451 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
452
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700453 def test_module_parameter(self):
454 NT = namedtuple('NT', ['x', 'y'], module=collections)
455 self.assertEqual(NT.__module__, collections)
456
Guido van Rossumd8faa362007-04-27 19:54:29 +0000457 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000458 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000459 p = Point(11, 22)
460 self.assertEqual(p, Point(x=11, y=22))
461 self.assertEqual(p, Point(11, y=22))
462 self.assertEqual(p, Point(y=22, x=11))
463 self.assertEqual(p, Point(*(11, 22)))
464 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200465 self.assertRaises(TypeError, Point, 1) # too few args
466 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
467 with self.assertRaises(TypeError): # wrong keyword argument
468 Point(XXX=1, y=2)
469 with self.assertRaises(TypeError): # missing keyword argument
470 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000471 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000472 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200473 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
474 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
475 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
476 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000477
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000478 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000479 p._replace(x=1, error=2)
480 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000481 pass
482 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000483 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000484
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000485 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000486 Point = namedtuple('Point', 'x, y')
487 p = Point(x=11, y=22)
488 self.assertEqual(repr(p), 'Point(x=11, y=22)')
489
490 # verify that fieldspec can be a non-string sequence
491 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000492 p = Point(x=11, y=22)
493 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000494
495 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000496 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000497 p = Point(11, 22)
498
Ezio Melottie9615932010-01-24 19:26:24 +0000499 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000500 self.assertEqual(p, (11, 22)) # matches a real tuple
Min ho Kimc4cacc82019-07-31 08:16:13 +1000501 self.assertEqual(tuple(p), (11, 22)) # coercible to a real tuple
502 self.assertEqual(list(p), [11, 22]) # coercible to a list
Guido van Rossumd8faa362007-04-27 19:54:29 +0000503 self.assertEqual(max(p), 22) # iterable
504 self.assertEqual(max(*p), 22) # star-able
505 x, y = p
506 self.assertEqual(p, (x, y)) # unpacks like a tuple
507 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200508 with self.assertRaises(IndexError):
509 p[3]
510 self.assertEqual(p[-1], 22)
511 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000512
513 self.assertEqual(p.x, x)
514 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200515 with self.assertRaises(AttributeError):
516 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000517
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000518 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000519 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000520 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000521 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000522 self.assertEqual(repr(Zero()), 'Zero()')
523 self.assertEqual(Zero()._asdict(), {})
524 self.assertEqual(Zero()._fields, ())
525
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000526 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000527 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000528 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000529 self.assertEqual(Dot(1).d, 1)
530 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
531 self.assertEqual(Dot(1)._asdict(), {'d':1})
532 self.assertEqual(Dot(1)._replace(d=999), (999,))
533 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000534
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200535 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200536 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000537 for j in range(10)]) for i in range(n)))
538 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000539 Big = namedtuple('Big', names)
540 b = Big(*range(n))
541 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000542 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000543 for pos, name in enumerate(names):
544 self.assertEqual(getattr(b, name), pos)
545 repr(b) # make sure repr() doesn't blow-up
546 d = b._asdict()
547 d_expected = dict(zip(names, range(n)))
548 self.assertEqual(d, d_expected)
549 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
550 b2_expected = list(range(n))
551 b2_expected[1] = 999
552 b2_expected[-5] = 42
553 self.assertEqual(b2, tuple(b2_expected))
554 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000555
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000556 def test_pickle(self):
557 p = TestNT(x=10, y=20, z=30)
558 for module in (pickle,):
559 loads = getattr(module, 'loads')
560 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500561 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000562 q = loads(dumps(p, protocol))
563 self.assertEqual(p, q)
564 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700565 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000566
567 def test_copy(self):
568 p = TestNT(x=10, y=20, z=30)
569 for copier in copy.copy, copy.deepcopy:
570 q = copier(p)
571 self.assertEqual(p, q)
572 self.assertEqual(p._fields, q._fields)
573
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000574 def test_name_conflicts(self):
575 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
576 # failed when used as field names. Test to make sure these now work.
577 T = namedtuple('T', 'itemgetter property self cls tuple')
578 t = T(1, 2, 3, 4, 5)
579 self.assertEqual(t, (1,2,3,4,5))
580 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
581 self.assertEqual(newt, (10,20,30,40,50))
582
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700583 # Broader test of all interesting names taken from the code, old
584 # template, and an example
585 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
586 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
587 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
588 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
589 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
590 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
591 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
592 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
593 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
594 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
595 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
596 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
597 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
598 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
599 'instantiate', 'interning', 'introspection', 'isidentifier',
600 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
601 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
602 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
603 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
604 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
605 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
606 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
607 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
608 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
609 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
610 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
611 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
612 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
613 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000614 T = namedtuple('T', words)
615 # test __new__
616 values = tuple(range(len(words)))
617 t = T(*values)
618 self.assertEqual(t, values)
619 t = T(**dict(zip(T._fields, values)))
620 self.assertEqual(t, values)
621 # test _make
622 t = T._make(values)
623 self.assertEqual(t, values)
624 # exercise __repr__
625 repr(t)
626 # test _asdict
627 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
628 # test _replace
629 t = T._make(values)
630 newvalues = tuple(v*10 for v in values)
631 newt = t._replace(**dict(zip(T._fields, newvalues)))
632 self.assertEqual(newt, newvalues)
633 # test _fields
634 self.assertEqual(T._fields, tuple(words))
635 # test __getnewargs__
636 self.assertEqual(t.__getnewargs__(), values)
637
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000638 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700639 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000640 self.assertEqual(repr(A(1)), 'A(x=1)')
641 # repr should show the name of the subclass
642 class B(A):
643 pass
644 self.assertEqual(repr(B(1)), 'B(x=1)')
645
Raymond Hettinger6538b432016-08-16 10:55:43 -0700646 def test_keyword_only_arguments(self):
647 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700648 with self.assertRaises(TypeError):
649 NT = namedtuple('NT', ['x', 'y'], True)
650
651 NT = namedtuple('NT', ['abc', 'def'], rename=True)
652 self.assertEqual(NT._fields, ('abc', '_1'))
653 with self.assertRaises(TypeError):
654 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000655
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700656 def test_namedtuple_subclass_issue_24931(self):
657 class Point(namedtuple('_Point', ['x', 'y'])):
658 pass
659
660 a = Point(3, 4)
661 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
662
663 a.w = 5
664 self.assertEqual(a.__dict__, {'w': 5})
665
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200666 def test_field_descriptor(self):
667 Point = namedtuple('Point', 'x y')
668 p = Point(11, 22)
669 self.assertTrue(inspect.isdatadescriptor(Point.x))
670 self.assertEqual(Point.x.__get__(p), 11)
671 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
672 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000673
Joe Jevnikf36f8922019-02-21 16:00:40 -0500674 class NewPoint(tuple):
675 x = pickle.loads(pickle.dumps(Point.x))
676 y = pickle.loads(pickle.dumps(Point.y))
677
678 np = NewPoint([1, 2])
679
680 self.assertEqual(np.x, 1)
681 self.assertEqual(np.y, 2)
682
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700683
Raymond Hettinger499e1932011-02-23 07:56:53 +0000684################################################################################
685### Abstract Base Classes
686################################################################################
687
Raymond Hettingerae650182009-01-28 23:33:59 +0000688class ABCTestCase(unittest.TestCase):
689
690 def validate_abstract_methods(self, abc, *names):
691 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
692
693 # everything should work will all required methods are present
694 C = type('C', (abc,), methodstubs)
695 C()
696
697 # instantiation should fail if a required method is missing
698 for name in names:
699 stubs = methodstubs.copy()
700 del stubs[name]
701 C = type('C', (abc,), stubs)
702 self.assertRaises(TypeError, C, name)
703
Florent Xiclunace153f62010-03-08 15:34:35 +0000704 def validate_isinstance(self, abc, name):
705 stub = lambda s, *args: 0
706
707 C = type('C', (object,), {'__hash__': None})
708 setattr(C, name, stub)
709 self.assertIsInstance(C(), abc)
710 self.assertTrue(issubclass(C, abc))
711
712 C = type('C', (object,), {'__hash__': None})
713 self.assertNotIsInstance(C(), abc)
714 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000715
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000716 def validate_comparison(self, instance):
717 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
718 operators = {}
719 for op in ops:
720 name = '__' + op + '__'
721 operators[name] = getattr(operator, name)
722
723 class Other:
724 def __init__(self):
725 self.right_side = False
726 def __eq__(self, other):
727 self.right_side = True
728 return True
729 __lt__ = __eq__
730 __gt__ = __eq__
731 __le__ = __eq__
732 __ge__ = __eq__
733 __ne__ = __eq__
734 __ror__ = __eq__
735 __rand__ = __eq__
736 __rxor__ = __eq__
737 __rsub__ = __eq__
738
739 for name, op in operators.items():
740 if not hasattr(instance, name):
741 continue
742 other = Other()
743 op(instance, other)
744 self.assertTrue(other.right_side,'Right side not called for %s.%s'
745 % (type(instance), name))
746
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700747def _test_gen():
748 yield
749
Raymond Hettingerae650182009-01-28 23:33:59 +0000750class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000751
Yury Selivanov75445082015-05-11 22:57:16 -0400752 def test_Awaitable(self):
753 def gen():
754 yield
755
756 @types.coroutine
757 def coro():
758 yield
759
760 async def new_coro():
761 pass
762
763 class Bar:
764 def __await__(self):
765 yield
766
767 class MinimalCoro(Coroutine):
768 def send(self, value):
769 return value
770 def throw(self, typ, val=None, tb=None):
771 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400772 def __await__(self):
773 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400774
775 non_samples = [None, int(), gen(), object()]
776 for x in non_samples:
777 self.assertNotIsInstance(x, Awaitable)
778 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
779
780 samples = [Bar(), MinimalCoro()]
781 for x in samples:
782 self.assertIsInstance(x, Awaitable)
783 self.assertTrue(issubclass(type(x), Awaitable))
784
785 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400786 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
787 # flag don't have '__await__' method, hence can't be instances
788 # of Awaitable. Use inspect.isawaitable to detect them.
789 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400790
791 c = new_coro()
792 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300793 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400794
Yury Selivanov56fc6142015-05-29 09:01:29 -0400795 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400796 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400797 self.assertTrue(isinstance(CoroLike(), Awaitable))
798 self.assertTrue(issubclass(CoroLike, Awaitable))
799 CoroLike = None
800 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400801
Yury Selivanov75445082015-05-11 22:57:16 -0400802 def test_Coroutine(self):
803 def gen():
804 yield
805
806 @types.coroutine
807 def coro():
808 yield
809
810 async def new_coro():
811 pass
812
813 class Bar:
814 def __await__(self):
815 yield
816
817 class MinimalCoro(Coroutine):
818 def send(self, value):
819 return value
820 def throw(self, typ, val=None, tb=None):
821 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400822 def __await__(self):
823 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400824
825 non_samples = [None, int(), gen(), object(), Bar()]
826 for x in non_samples:
827 self.assertNotIsInstance(x, Coroutine)
828 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
829
830 samples = [MinimalCoro()]
831 for x in samples:
832 self.assertIsInstance(x, Awaitable)
833 self.assertTrue(issubclass(type(x), Awaitable))
834
835 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400836 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
837 # flag don't have '__await__' method, hence can't be instances
838 # of Coroutine. Use inspect.isawaitable to detect them.
839 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400840
841 c = new_coro()
842 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300843 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400844
Yury Selivanov56fc6142015-05-29 09:01:29 -0400845 class CoroLike:
846 def send(self, value):
847 pass
848 def throw(self, typ, val=None, tb=None):
849 pass
850 def close(self):
851 pass
852 def __await__(self):
853 pass
854 self.assertTrue(isinstance(CoroLike(), Coroutine))
855 self.assertTrue(issubclass(CoroLike, Coroutine))
856
857 class CoroLike:
858 def send(self, value):
859 pass
860 def close(self):
861 pass
862 def __await__(self):
863 pass
864 self.assertFalse(isinstance(CoroLike(), Coroutine))
865 self.assertFalse(issubclass(CoroLike, Coroutine))
866
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000867 def test_Hashable(self):
868 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000869 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000870 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000871 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000872 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000873 # Check some hashables
874 samples = [None,
875 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000876 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000877 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000878 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000879 ]
880 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000881 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000882 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000883 self.assertRaises(TypeError, Hashable)
884 # Check direct subclassing
885 class H(Hashable):
886 def __hash__(self):
887 return super().__hash__()
888 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000889 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000890 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000891 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000892
Yury Selivanove0104ae2015-05-14 12:19:16 -0400893 def test_AsyncIterable(self):
894 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400895 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400896 return self
897 self.assertTrue(isinstance(AI(), AsyncIterable))
898 self.assertTrue(issubclass(AI, AsyncIterable))
899 # Check some non-iterables
900 non_samples = [None, object, []]
901 for x in non_samples:
902 self.assertNotIsInstance(x, AsyncIterable)
903 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
904 self.validate_abstract_methods(AsyncIterable, '__aiter__')
905 self.validate_isinstance(AsyncIterable, '__aiter__')
906
907 def test_AsyncIterator(self):
908 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400909 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400910 return self
911 async def __anext__(self):
912 raise StopAsyncIteration
913 self.assertTrue(isinstance(AI(), AsyncIterator))
914 self.assertTrue(issubclass(AI, AsyncIterator))
915 non_samples = [None, object, []]
916 # Check some non-iterables
917 for x in non_samples:
918 self.assertNotIsInstance(x, AsyncIterator)
919 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
920 # Similarly to regular iterators (see issue 10565)
921 class AnextOnly:
922 async def __anext__(self):
923 raise StopAsyncIteration
924 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
925 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
926
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000927 def test_Iterable(self):
928 # Check some non-iterables
929 non_samples = [None, 42, 3.14, 1j]
930 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000931 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000932 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000933 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000934 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000935 tuple(), list(), set(), frozenset(), dict(),
936 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700937 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000938 (x for x in []),
939 ]
940 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000941 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000942 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000943 # Check direct subclassing
944 class I(Iterable):
945 def __iter__(self):
946 return super().__iter__()
947 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000948 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000949 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000950 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700951 # Check None blocking
952 class It:
953 def __iter__(self): return iter([])
954 class ItBlocked(It):
955 __iter__ = None
956 self.assertTrue(issubclass(It, Iterable))
957 self.assertTrue(isinstance(It(), Iterable))
958 self.assertFalse(issubclass(ItBlocked, Iterable))
959 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000960
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700961 def test_Reversible(self):
962 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100963 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700964 for x in non_samples:
965 self.assertNotIsInstance(x, Reversible)
966 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700967 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100968 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700969 for x in non_reversibles:
970 self.assertNotIsInstance(x, Reversible)
971 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
972 # Check some reversible iterables
973 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
974 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100975 OrderedDict().values(), Counter(), Counter().keys(),
976 Counter().items(), Counter().values(), dict(),
977 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700978 for x in samples:
979 self.assertIsInstance(x, Reversible)
980 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
981 # Check also Mapping, MutableMapping, and Sequence
982 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
983 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
984 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
985 # Check direct subclassing
986 class R(Reversible):
987 def __iter__(self):
988 return iter(list())
989 def __reversed__(self):
990 return iter(list())
991 self.assertEqual(list(reversed(R())), [])
992 self.assertFalse(issubclass(float, R))
993 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700994 # Check reversible non-iterable (which is not Reversible)
995 class RevNoIter:
996 def __reversed__(self): return reversed([])
997 class RevPlusIter(RevNoIter):
998 def __iter__(self): return iter([])
999 self.assertFalse(issubclass(RevNoIter, Reversible))
1000 self.assertFalse(isinstance(RevNoIter(), Reversible))
1001 self.assertTrue(issubclass(RevPlusIter, Reversible))
1002 self.assertTrue(isinstance(RevPlusIter(), Reversible))
1003 # Check None blocking
1004 class Rev:
1005 def __iter__(self): return iter([])
1006 def __reversed__(self): return reversed([])
1007 class RevItBlocked(Rev):
1008 __iter__ = None
1009 class RevRevBlocked(Rev):
1010 __reversed__ = None
1011 self.assertTrue(issubclass(Rev, Reversible))
1012 self.assertTrue(isinstance(Rev(), Reversible))
1013 self.assertFalse(issubclass(RevItBlocked, Reversible))
1014 self.assertFalse(isinstance(RevItBlocked(), Reversible))
1015 self.assertFalse(issubclass(RevRevBlocked, Reversible))
1016 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001017
Guido van Rossumf0666942016-08-23 10:47:07 -07001018 def test_Collection(self):
1019 # Check some non-collections
1020 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
1021 for x in non_collections:
1022 self.assertNotIsInstance(x, Collection)
1023 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1024 # Check some non-collection iterables
1025 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001026 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -07001027 for x in non_col_iterables:
1028 self.assertNotIsInstance(x, Collection)
1029 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1030 # Check some collections
1031 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001032 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001033 for x in samples:
1034 self.assertIsInstance(x, Collection)
1035 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1036 # Check also Mapping, MutableMapping, etc.
1037 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1038 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1039 self.assertTrue(issubclass(MutableMapping, Collection),
1040 repr(MutableMapping))
1041 self.assertTrue(issubclass(Set, Collection), repr(Set))
1042 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1043 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1044 # Check direct subclassing
1045 class Col(Collection):
1046 def __iter__(self):
1047 return iter(list())
1048 def __len__(self):
1049 return 0
1050 def __contains__(self, item):
1051 return False
1052 class DerCol(Col): pass
1053 self.assertEqual(list(iter(Col())), [])
1054 self.assertFalse(issubclass(list, Col))
1055 self.assertFalse(issubclass(set, Col))
1056 self.assertFalse(issubclass(float, Col))
1057 self.assertEqual(list(iter(DerCol())), [])
1058 self.assertFalse(issubclass(list, DerCol))
1059 self.assertFalse(issubclass(set, DerCol))
1060 self.assertFalse(issubclass(float, DerCol))
1061 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1062 '__contains__')
1063 # Check sized container non-iterable (which is not Collection) etc.
1064 class ColNoIter:
1065 def __len__(self): return 0
1066 def __contains__(self, item): return False
1067 class ColNoSize:
1068 def __iter__(self): return iter([])
1069 def __contains__(self, item): return False
1070 class ColNoCont:
1071 def __iter__(self): return iter([])
1072 def __len__(self): return 0
1073 self.assertFalse(issubclass(ColNoIter, Collection))
1074 self.assertFalse(isinstance(ColNoIter(), Collection))
1075 self.assertFalse(issubclass(ColNoSize, Collection))
1076 self.assertFalse(isinstance(ColNoSize(), Collection))
1077 self.assertFalse(issubclass(ColNoCont, Collection))
1078 self.assertFalse(isinstance(ColNoCont(), Collection))
1079 # Check None blocking
1080 class SizeBlock:
1081 def __iter__(self): return iter([])
1082 def __contains__(self): return False
1083 __len__ = None
1084 class IterBlock:
1085 def __len__(self): return 0
1086 def __contains__(self): return True
1087 __iter__ = None
1088 self.assertFalse(issubclass(SizeBlock, Collection))
1089 self.assertFalse(isinstance(SizeBlock(), Collection))
1090 self.assertFalse(issubclass(IterBlock, Collection))
1091 self.assertFalse(isinstance(IterBlock(), Collection))
1092 # Check None blocking in subclass
1093 class ColImpl:
1094 def __iter__(self):
1095 return iter(list())
1096 def __len__(self):
1097 return 0
1098 def __contains__(self, item):
1099 return False
1100 class NonCol(ColImpl):
1101 __contains__ = None
1102 self.assertFalse(issubclass(NonCol, Collection))
1103 self.assertFalse(isinstance(NonCol(), Collection))
1104
1105
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001106 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001107 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001108 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001109 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001110 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001111 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001112 iter(tuple()), iter(list()), iter(dict()),
1113 iter(set()), iter(frozenset()),
1114 iter(dict().keys()), iter(dict().items()),
1115 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001116 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001117 (x for x in []),
1118 ]
1119 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001120 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001121 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001122 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1123
1124 # Issue 10565
1125 class NextOnly:
1126 def __next__(self):
1127 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001128 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001129 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001130
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001131 def test_Generator(self):
1132 class NonGen1:
1133 def __iter__(self): return self
1134 def __next__(self): return None
1135 def close(self): pass
1136 def throw(self, typ, val=None, tb=None): pass
1137
1138 class NonGen2:
1139 def __iter__(self): return self
1140 def __next__(self): return None
1141 def close(self): pass
1142 def send(self, value): return value
1143
1144 class NonGen3:
1145 def close(self): pass
1146 def send(self, value): return value
1147 def throw(self, typ, val=None, tb=None): pass
1148
1149 non_samples = [
1150 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1151 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1152 for x in non_samples:
1153 self.assertNotIsInstance(x, Generator)
1154 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1155
1156 class Gen:
1157 def __iter__(self): return self
1158 def __next__(self): return None
1159 def close(self): pass
1160 def send(self, value): return value
1161 def throw(self, typ, val=None, tb=None): pass
1162
1163 class MinimalGen(Generator):
1164 def send(self, value):
1165 return value
1166 def throw(self, typ, val=None, tb=None):
1167 super().throw(typ, val, tb)
1168
1169 def gen():
1170 yield 1
1171
1172 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1173 for x in samples:
1174 self.assertIsInstance(x, Iterator)
1175 self.assertIsInstance(x, Generator)
1176 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1177 self.validate_abstract_methods(Generator, 'send', 'throw')
1178
1179 # mixin tests
1180 mgen = MinimalGen()
1181 self.assertIs(mgen, iter(mgen))
1182 self.assertIs(mgen.send(None), next(mgen))
1183 self.assertEqual(2, mgen.send(2))
1184 self.assertIsNone(mgen.close())
1185 self.assertRaises(ValueError, mgen.throw, ValueError)
1186 self.assertRaisesRegex(ValueError, "^huhu$",
1187 mgen.throw, ValueError, ValueError("huhu"))
1188 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1189
1190 class FailOnClose(Generator):
1191 def send(self, value): return value
1192 def throw(self, *args): raise ValueError
1193
1194 self.assertRaises(ValueError, FailOnClose().close)
1195
1196 class IgnoreGeneratorExit(Generator):
1197 def send(self, value): return value
1198 def throw(self, *args): pass
1199
1200 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1201
Yury Selivanov22214ab2016-11-16 18:25:04 -05001202 def test_AsyncGenerator(self):
1203 class NonAGen1:
1204 def __aiter__(self): return self
1205 def __anext__(self): return None
1206 def aclose(self): pass
1207 def athrow(self, typ, val=None, tb=None): pass
1208
1209 class NonAGen2:
1210 def __aiter__(self): return self
1211 def __anext__(self): return None
1212 def aclose(self): pass
1213 def asend(self, value): return value
1214
1215 class NonAGen3:
1216 def aclose(self): pass
1217 def asend(self, value): return value
1218 def athrow(self, typ, val=None, tb=None): pass
1219
1220 non_samples = [
1221 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1222 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1223 for x in non_samples:
1224 self.assertNotIsInstance(x, AsyncGenerator)
1225 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1226
1227 class Gen:
1228 def __aiter__(self): return self
1229 async def __anext__(self): return None
1230 async def aclose(self): pass
1231 async def asend(self, value): return value
1232 async def athrow(self, typ, val=None, tb=None): pass
1233
1234 class MinimalAGen(AsyncGenerator):
1235 async def asend(self, value):
1236 return value
1237 async def athrow(self, typ, val=None, tb=None):
1238 await super().athrow(typ, val, tb)
1239
1240 async def gen():
1241 yield 1
1242
1243 samples = [gen(), Gen(), MinimalAGen()]
1244 for x in samples:
1245 self.assertIsInstance(x, AsyncIterator)
1246 self.assertIsInstance(x, AsyncGenerator)
1247 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1248 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1249
1250 def run_async(coro):
1251 result = None
1252 while True:
1253 try:
1254 coro.send(None)
1255 except StopIteration as ex:
1256 result = ex.args[0] if ex.args else None
1257 break
1258 return result
1259
1260 # mixin tests
1261 mgen = MinimalAGen()
1262 self.assertIs(mgen, mgen.__aiter__())
1263 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1264 self.assertEqual(2, run_async(mgen.asend(2)))
1265 self.assertIsNone(run_async(mgen.aclose()))
1266 with self.assertRaises(ValueError):
1267 run_async(mgen.athrow(ValueError))
1268
1269 class FailOnClose(AsyncGenerator):
1270 async def asend(self, value): return value
1271 async def athrow(self, *args): raise ValueError
1272
1273 with self.assertRaises(ValueError):
1274 run_async(FailOnClose().aclose())
1275
1276 class IgnoreGeneratorExit(AsyncGenerator):
1277 async def asend(self, value): return value
1278 async def athrow(self, *args): pass
1279
1280 with self.assertRaises(RuntimeError):
1281 run_async(IgnoreGeneratorExit().aclose())
1282
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001283 def test_Sized(self):
1284 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001285 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001286 (x for x in []),
1287 ]
1288 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001289 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001290 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001291 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001292 tuple(), list(), set(), frozenset(), dict(),
1293 dict().keys(), dict().items(), dict().values(),
1294 ]
1295 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001296 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001297 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001298 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001299 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001300
1301 def test_Container(self):
1302 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001303 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001304 (x for x in []),
1305 ]
1306 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001307 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001308 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001309 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001310 tuple(), list(), set(), frozenset(), dict(),
1311 dict().keys(), dict().items(),
1312 ]
1313 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001314 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001315 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001316 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001317 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001318
1319 def test_Callable(self):
1320 non_samples = [None, 42, 3.14, 1j,
1321 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001322 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001323 (x for x in []),
1324 ]
1325 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001326 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001327 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001328 samples = [lambda: None,
1329 type, int, object,
1330 len,
1331 list.append, [].append,
1332 ]
1333 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001334 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001335 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001336 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001337 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001338
1339 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001340 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001341 class C(B):
1342 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001343 self.assertTrue(issubclass(C, B))
1344 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001345
1346 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001347 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001348 class C:
1349 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001350 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001351 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001352 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001353
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001354class WithSet(MutableSet):
1355
1356 def __init__(self, it=()):
1357 self.data = set(it)
1358
1359 def __len__(self):
1360 return len(self.data)
1361
1362 def __iter__(self):
1363 return iter(self.data)
1364
1365 def __contains__(self, item):
1366 return item in self.data
1367
1368 def add(self, item):
1369 self.data.add(item)
1370
1371 def discard(self, item):
1372 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001373
Raymond Hettingerae650182009-01-28 23:33:59 +00001374class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001375
1376 # XXX For now, we only test some virtual inheritance properties.
1377 # We should also test the proper behavior of the collection ABCs
1378 # as real base classes or mix-in classes.
1379
1380 def test_Set(self):
1381 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001382 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001383 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001384 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001385 class MySet(Set):
1386 def __contains__(self, x):
1387 return False
1388 def __len__(self):
1389 return 0
1390 def __iter__(self):
1391 return iter([])
1392 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001393
Benjamin Peterson41181742008-07-02 20:22:54 +00001394 def test_hash_Set(self):
1395 class OneTwoThreeSet(Set):
1396 def __init__(self):
1397 self.contents = [1, 2, 3]
1398 def __contains__(self, x):
1399 return x in self.contents
1400 def __len__(self):
1401 return len(self.contents)
1402 def __iter__(self):
1403 return iter(self.contents)
1404 def __hash__(self):
1405 return self._hash()
1406 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001407 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001408
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001409 def test_isdisjoint_Set(self):
1410 class MySet(Set):
1411 def __init__(self, itr):
1412 self.contents = itr
1413 def __contains__(self, x):
1414 return x in self.contents
1415 def __iter__(self):
1416 return iter(self.contents)
1417 def __len__(self):
1418 return len([x for x in self.contents])
1419 s1 = MySet((1, 2, 3))
1420 s2 = MySet((4, 5, 6))
1421 s3 = MySet((1, 5, 6))
1422 self.assertTrue(s1.isdisjoint(s2))
1423 self.assertFalse(s1.isdisjoint(s3))
1424
1425 def test_equality_Set(self):
1426 class MySet(Set):
1427 def __init__(self, itr):
1428 self.contents = itr
1429 def __contains__(self, x):
1430 return x in self.contents
1431 def __iter__(self):
1432 return iter(self.contents)
1433 def __len__(self):
1434 return len([x for x in self.contents])
1435 s1 = MySet((1,))
1436 s2 = MySet((1, 2))
1437 s3 = MySet((3, 4))
1438 s4 = MySet((3, 4))
1439 self.assertTrue(s2 > s1)
1440 self.assertTrue(s1 < s2)
1441 self.assertFalse(s2 <= s1)
1442 self.assertFalse(s2 <= s3)
1443 self.assertFalse(s1 >= s2)
1444 self.assertEqual(s3, s4)
1445 self.assertNotEqual(s2, s3)
1446
1447 def test_arithmetic_Set(self):
1448 class MySet(Set):
1449 def __init__(self, itr):
1450 self.contents = itr
1451 def __contains__(self, x):
1452 return x in self.contents
1453 def __iter__(self):
1454 return iter(self.contents)
1455 def __len__(self):
1456 return len([x for x in self.contents])
1457 s1 = MySet((1, 2, 3))
1458 s2 = MySet((3, 4, 5))
1459 s3 = s1 & s2
1460 self.assertEqual(s3, MySet((3,)))
1461
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001462 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001463 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001464 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001465 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001466 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001467 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1468 'add', 'discard')
1469
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001470 def test_issue_5647(self):
1471 # MutableSet.__iand__ mutated the set during iteration
1472 s = WithSet('abcd')
1473 s &= WithSet('cdef') # This used to fail
1474 self.assertEqual(set(s), set('cd'))
1475
Raymond Hettingerae650182009-01-28 23:33:59 +00001476 def test_issue_4920(self):
1477 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001478 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001479 __slots__=['__s']
1480 def __init__(self,items=None):
1481 if items is None:
1482 items=[]
1483 self.__s=set(items)
1484 def __contains__(self,v):
1485 return v in self.__s
1486 def __iter__(self):
1487 return iter(self.__s)
1488 def __len__(self):
1489 return len(self.__s)
1490 def add(self,v):
1491 result=v not in self.__s
1492 self.__s.add(v)
1493 return result
1494 def discard(self,v):
1495 result=v in self.__s
1496 self.__s.discard(v)
1497 return result
1498 def __repr__(self):
1499 return "MySet(%s)" % repr(list(self))
1500 s = MySet([5,43,2,1])
1501 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001502
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001503 def test_issue8750(self):
1504 empty = WithSet()
1505 full = WithSet(range(10))
1506 s = WithSet(full)
1507 s -= s
1508 self.assertEqual(s, empty)
1509 s = WithSet(full)
1510 s ^= s
1511 self.assertEqual(s, empty)
1512 s = WithSet(full)
1513 s &= s
1514 self.assertEqual(s, full)
1515 s |= s
1516 self.assertEqual(s, full)
1517
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001518 def test_issue16373(self):
1519 # Recursion error comparing comparable and noncomparable
1520 # Set instances
1521 class MyComparableSet(Set):
1522 def __contains__(self, x):
1523 return False
1524 def __len__(self):
1525 return 0
1526 def __iter__(self):
1527 return iter([])
1528 class MyNonComparableSet(Set):
1529 def __contains__(self, x):
1530 return False
1531 def __len__(self):
1532 return 0
1533 def __iter__(self):
1534 return iter([])
1535 def __le__(self, x):
1536 return NotImplemented
1537 def __lt__(self, x):
1538 return NotImplemented
1539
1540 cs = MyComparableSet()
1541 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001542 self.assertFalse(ncs < cs)
1543 self.assertTrue(ncs <= cs)
1544 self.assertFalse(ncs > cs)
1545 self.assertTrue(ncs >= cs)
1546
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001547 def test_issue26915(self):
1548 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001549 class CustomSequence(Sequence):
1550 def __init__(self, seq):
1551 self._seq = seq
1552 def __getitem__(self, index):
1553 return self._seq[index]
1554 def __len__(self):
1555 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001556
1557 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001558 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001559 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001560 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001561 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001562 ItemsView({1: nan, 2: obj}),
1563 ValuesView({1: nan, 2: obj})
1564 ]
1565 for container in containers:
1566 for elem in container:
1567 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001568 self.assertEqual(seq.index(nan), 0)
1569 self.assertEqual(seq.index(obj), 1)
1570 self.assertEqual(seq.count(nan), 2)
1571 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001572
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001573 def assertSameSet(self, s1, s2):
1574 # coerce both to a real set then check equality
1575 self.assertSetEqual(set(s1), set(s2))
1576
Miss Islington (bot)89d74d02020-11-21 12:20:26 -08001577 def test_Set_from_iterable(self):
1578 """Verify _from_iterable overriden to an instance method works."""
1579 class SetUsingInstanceFromIterable(MutableSet):
1580 def __init__(self, values, created_by):
1581 if not created_by:
1582 raise ValueError(f'created_by must be specified')
1583 self.created_by = created_by
1584 self._values = set(values)
1585
1586 def _from_iterable(self, values):
1587 return type(self)(values, 'from_iterable')
1588
1589 def __contains__(self, value):
1590 return value in self._values
1591
1592 def __iter__(self):
1593 yield from self._values
1594
1595 def __len__(self):
1596 return len(self._values)
1597
1598 def add(self, value):
1599 self._values.add(value)
1600
1601 def discard(self, value):
1602 self._values.discard(value)
1603
1604 impl = SetUsingInstanceFromIterable([1, 2, 3], 'test')
1605
1606 actual = impl - {1}
1607 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1608 self.assertEqual('from_iterable', actual.created_by)
1609 self.assertEqual({2, 3}, actual)
1610
1611 actual = impl | {4}
1612 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1613 self.assertEqual('from_iterable', actual.created_by)
1614 self.assertEqual({1, 2, 3, 4}, actual)
1615
1616 actual = impl & {2}
1617 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1618 self.assertEqual('from_iterable', actual.created_by)
1619 self.assertEqual({2}, actual)
1620
1621 actual = impl ^ {3, 4}
1622 self.assertIsInstance(actual, SetUsingInstanceFromIterable)
1623 self.assertEqual('from_iterable', actual.created_by)
1624 self.assertEqual({1, 2, 4}, actual)
1625
1626 # NOTE: ixor'ing with a list is important here: internally, __ixor__
1627 # only calls _from_iterable if the other value isn't already a Set.
1628 impl ^= [3, 4]
1629 self.assertIsInstance(impl, SetUsingInstanceFromIterable)
1630 self.assertEqual('test', impl.created_by)
1631 self.assertEqual({1, 2, 4}, impl)
1632
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001633 def test_Set_interoperability_with_real_sets(self):
1634 # Issue: 8743
1635 class ListSet(Set):
1636 def __init__(self, elements=()):
1637 self.data = []
1638 for elem in elements:
1639 if elem not in self.data:
1640 self.data.append(elem)
1641 def __contains__(self, elem):
1642 return elem in self.data
1643 def __iter__(self):
1644 return iter(self.data)
1645 def __len__(self):
1646 return len(self.data)
1647 def __repr__(self):
1648 return 'Set({!r})'.format(self.data)
1649
1650 r1 = set('abc')
1651 r2 = set('bcd')
1652 r3 = set('abcde')
1653 f1 = ListSet('abc')
1654 f2 = ListSet('bcd')
1655 f3 = ListSet('abcde')
1656 l1 = list('abccba')
1657 l2 = list('bcddcb')
1658 l3 = list('abcdeedcba')
1659
1660 target = r1 & r2
1661 self.assertSameSet(f1 & f2, target)
1662 self.assertSameSet(f1 & r2, target)
1663 self.assertSameSet(r2 & f1, target)
1664 self.assertSameSet(f1 & l2, target)
1665
1666 target = r1 | r2
1667 self.assertSameSet(f1 | f2, target)
1668 self.assertSameSet(f1 | r2, target)
1669 self.assertSameSet(r2 | f1, target)
1670 self.assertSameSet(f1 | l2, target)
1671
1672 fwd_target = r1 - r2
1673 rev_target = r2 - r1
1674 self.assertSameSet(f1 - f2, fwd_target)
1675 self.assertSameSet(f2 - f1, rev_target)
1676 self.assertSameSet(f1 - r2, fwd_target)
1677 self.assertSameSet(f2 - r1, rev_target)
1678 self.assertSameSet(r1 - f2, fwd_target)
1679 self.assertSameSet(r2 - f1, rev_target)
1680 self.assertSameSet(f1 - l2, fwd_target)
1681 self.assertSameSet(f2 - l1, rev_target)
1682
1683 target = r1 ^ r2
1684 self.assertSameSet(f1 ^ f2, target)
1685 self.assertSameSet(f1 ^ r2, target)
1686 self.assertSameSet(r2 ^ f1, target)
1687 self.assertSameSet(f1 ^ l2, target)
1688
1689 # Don't change the following to use assertLess or other
1690 # "more specific" unittest assertions. The current
1691 # assertTrue/assertFalse style makes the pattern of test
1692 # case combinations clear and allows us to know for sure
1693 # the exact operator being invoked.
1694
1695 # proper subset
1696 self.assertTrue(f1 < f3)
1697 self.assertFalse(f1 < f1)
1698 self.assertFalse(f1 < f2)
1699 self.assertTrue(r1 < f3)
1700 self.assertFalse(r1 < f1)
1701 self.assertFalse(r1 < f2)
1702 self.assertTrue(r1 < r3)
1703 self.assertFalse(r1 < r1)
1704 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001705 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001706 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001707 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001708 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001709 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001710 f1 < l2
1711
1712 # any subset
1713 self.assertTrue(f1 <= f3)
1714 self.assertTrue(f1 <= f1)
1715 self.assertFalse(f1 <= f2)
1716 self.assertTrue(r1 <= f3)
1717 self.assertTrue(r1 <= f1)
1718 self.assertFalse(r1 <= f2)
1719 self.assertTrue(r1 <= r3)
1720 self.assertTrue(r1 <= r1)
1721 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001722 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001723 f1 <= l3
1724 with self.assertRaises(TypeError):
1725 f1 <= l1
1726 with self.assertRaises(TypeError):
1727 f1 <= l2
1728
1729 # proper superset
1730 self.assertTrue(f3 > f1)
1731 self.assertFalse(f1 > f1)
1732 self.assertFalse(f2 > f1)
1733 self.assertTrue(r3 > r1)
1734 self.assertFalse(f1 > r1)
1735 self.assertFalse(f2 > r1)
1736 self.assertTrue(r3 > r1)
1737 self.assertFalse(r1 > r1)
1738 self.assertFalse(r2 > r1)
1739 with self.assertRaises(TypeError):
1740 f1 > l3
1741 with self.assertRaises(TypeError):
1742 f1 > l1
1743 with self.assertRaises(TypeError):
1744 f1 > l2
1745
1746 # any superset
1747 self.assertTrue(f3 >= f1)
1748 self.assertTrue(f1 >= f1)
1749 self.assertFalse(f2 >= f1)
1750 self.assertTrue(r3 >= r1)
1751 self.assertTrue(f1 >= r1)
1752 self.assertFalse(f2 >= r1)
1753 self.assertTrue(r3 >= r1)
1754 self.assertTrue(r1 >= r1)
1755 self.assertFalse(r2 >= r1)
1756 with self.assertRaises(TypeError):
1757 f1 >= l3
1758 with self.assertRaises(TypeError):
1759 f1 >=l1
1760 with self.assertRaises(TypeError):
1761 f1 >= l2
1762
1763 # equality
1764 self.assertTrue(f1 == f1)
1765 self.assertTrue(r1 == f1)
1766 self.assertTrue(f1 == r1)
1767 self.assertFalse(f1 == f3)
1768 self.assertFalse(r1 == f3)
1769 self.assertFalse(f1 == r3)
1770 self.assertFalse(f1 == l3)
1771 self.assertFalse(f1 == l1)
1772 self.assertFalse(f1 == l2)
1773
1774 # inequality
1775 self.assertFalse(f1 != f1)
1776 self.assertFalse(r1 != f1)
1777 self.assertFalse(f1 != r1)
1778 self.assertTrue(f1 != f3)
1779 self.assertTrue(r1 != f3)
1780 self.assertTrue(f1 != r3)
1781 self.assertTrue(f1 != l3)
1782 self.assertTrue(f1 != l1)
1783 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001784
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001785 def test_Mapping(self):
1786 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001787 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001788 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001789 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1790 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001791 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001792 def __len__(self):
1793 return 0
1794 def __getitem__(self, i):
1795 raise IndexError
1796 def __iter__(self):
1797 return iter(())
1798 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001799 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001800
1801 def test_MutableMapping(self):
1802 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001803 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001804 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001805 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1806 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001807
Raymond Hettinger9117c752010-08-22 07:44:24 +00001808 def test_MutableMapping_subclass(self):
1809 # Test issue 9214
1810 mymap = UserDict()
1811 mymap['red'] = 5
1812 self.assertIsInstance(mymap.keys(), Set)
1813 self.assertIsInstance(mymap.keys(), KeysView)
1814 self.assertIsInstance(mymap.items(), Set)
1815 self.assertIsInstance(mymap.items(), ItemsView)
1816
1817 mymap = UserDict()
1818 mymap['red'] = 5
1819 z = mymap.keys() | {'orange'}
1820 self.assertIsInstance(z, set)
1821 list(z)
1822 mymap['blue'] = 7 # Shouldn't affect 'z'
1823 self.assertEqual(sorted(z), ['orange', 'red'])
1824
1825 mymap = UserDict()
1826 mymap['red'] = 5
1827 z = mymap.items() | {('orange', 3)}
1828 self.assertIsInstance(z, set)
1829 list(z)
1830 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001831 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001832
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001833 def test_Sequence(self):
1834 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001835 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001836 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001837 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001838 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001839 self.assertIsInstance(memoryview(b""), Sequence)
1840 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001841 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001842 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1843 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001844
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001845 def test_Sequence_mixins(self):
1846 class SequenceSubclass(Sequence):
1847 def __init__(self, seq=()):
1848 self.seq = seq
1849
1850 def __getitem__(self, index):
1851 return self.seq[index]
1852
1853 def __len__(self):
1854 return len(self.seq)
1855
1856 # Compare Sequence.index() behavior to (list|str).index() behavior
1857 def assert_index_same(seq1, seq2, index_args):
1858 try:
1859 expected = seq1.index(*index_args)
1860 except ValueError:
1861 with self.assertRaises(ValueError):
1862 seq2.index(*index_args)
1863 else:
1864 actual = seq2.index(*index_args)
1865 self.assertEqual(
1866 actual, expected, '%r.index%s' % (seq1, index_args))
1867
1868 for ty in list, str:
1869 nativeseq = ty('abracadabra')
1870 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1871 seqseq = SequenceSubclass(nativeseq)
1872 for letter in set(nativeseq) | {'z'}:
1873 assert_index_same(nativeseq, seqseq, (letter,))
1874 for start in range(-3, len(nativeseq) + 3):
1875 assert_index_same(nativeseq, seqseq, (letter, start))
1876 for stop in range(-3, len(nativeseq) + 3):
1877 assert_index_same(
1878 nativeseq, seqseq, (letter, start, stop))
1879
Guido van Rossumd05eb002007-11-21 22:26:24 +00001880 def test_ByteString(self):
1881 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001882 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001883 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001884 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001885 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001886 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001887 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001888 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001889
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001890 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001891 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001892 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001893 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001894 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001895 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001896 self.assertTrue(issubclass(sample, MutableSequence))
1897 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001898 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1899 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001900
Eli Bendersky0716a572011-03-04 10:38:14 +00001901 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001902 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001903 # class inherited from it.
1904 class MutableSequenceSubclass(MutableSequence):
1905 def __init__(self):
1906 self.lst = []
1907
1908 def __setitem__(self, index, value):
1909 self.lst[index] = value
1910
1911 def __getitem__(self, index):
1912 return self.lst[index]
1913
1914 def __len__(self):
1915 return len(self.lst)
1916
1917 def __delitem__(self, index):
1918 del self.lst[index]
1919
1920 def insert(self, index, value):
1921 self.lst.insert(index, value)
1922
1923 mss = MutableSequenceSubclass()
1924 mss.append(0)
1925 mss.extend((1, 2, 3, 4))
1926 self.assertEqual(len(mss), 5)
1927 self.assertEqual(mss[3], 3)
1928 mss.reverse()
1929 self.assertEqual(mss[3], 1)
1930 mss.pop()
1931 self.assertEqual(len(mss), 4)
1932 mss.remove(3)
1933 self.assertEqual(len(mss), 3)
1934 mss += (10, 20, 30)
1935 self.assertEqual(len(mss), 6)
1936 self.assertEqual(mss[-1], 30)
1937 mss.clear()
1938 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001939
Naris R1b5f9c92018-08-31 02:56:14 +10001940 # issue 34427
1941 # extending self should not cause infinite loop
1942 items = 'ABCD'
1943 mss2 = MutableSequenceSubclass()
1944 mss2.extend(items + items)
1945 mss.clear()
1946 mss.extend(items)
1947 mss.extend(mss)
1948 self.assertEqual(len(mss), len(mss2))
1949 self.assertEqual(list(mss), list(mss2))
1950
1951
Raymond Hettinger499e1932011-02-23 07:56:53 +00001952################################################################################
1953### Counter
1954################################################################################
1955
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001956class CounterSubclassWithSetItem(Counter):
1957 # Test a counter subclass that overrides __setitem__
1958 def __init__(self, *args, **kwds):
1959 self.called = False
1960 Counter.__init__(self, *args, **kwds)
1961 def __setitem__(self, key, value):
1962 self.called = True
1963 Counter.__setitem__(self, key, value)
1964
1965class CounterSubclassWithGet(Counter):
1966 # Test a counter subclass that overrides get()
1967 def __init__(self, *args, **kwds):
1968 self.called = False
1969 Counter.__init__(self, *args, **kwds)
1970 def get(self, key, default):
1971 self.called = True
1972 return Counter.get(self, key, default)
1973
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001974class TestCounter(unittest.TestCase):
1975
1976 def test_basics(self):
1977 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001978 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1979 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001980 self.assertIsInstance(c, dict)
1981 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001982 self.assertTrue(issubclass(Counter, dict))
1983 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001984 self.assertEqual(len(c), 3)
1985 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001986 self.assertEqual(list(c.values()), [3, 2, 1])
1987 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1988 self.assertEqual(list(c), ['a', 'b', 'c'])
1989 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001990 [('a', 3), ('b', 2), ('c', 1)])
1991 self.assertEqual(c['b'], 2)
1992 self.assertEqual(c['z'], 0)
1993 self.assertEqual(c.__contains__('c'), True)
1994 self.assertEqual(c.__contains__('z'), False)
1995 self.assertEqual(c.get('b', 10), 2)
1996 self.assertEqual(c.get('z', 10), 10)
1997 self.assertEqual(c, dict(a=3, b=2, c=1))
1998 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1999 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
2000 for i in range(5):
2001 self.assertEqual(c.most_common(i),
2002 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002003 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002004 c['a'] += 1 # increment an existing value
2005 c['b'] -= 2 # sub existing value to zero
2006 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002007 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002008 c['d'] -= 2 # sub from a missing value
2009 c['e'] = -5 # directly assign a missing value
2010 c['f'] += 4 # add to a missing value
2011 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01002012 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002013 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002014 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002015 for i in range(3):
2016 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00002017 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002018 c.clear()
2019 self.assertEqual(c, {})
2020 self.assertEqual(repr(c), 'Counter()')
2021 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
2022 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002023 c.update(dict(a=5, b=3))
2024 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002025 c.update(Counter('a' * 50 + 'b' * 30))
2026 c.update() # test case with no args
2027 c.__init__('a' * 500 + 'b' * 300)
2028 c.__init__('cdc')
2029 c.__init__()
2030 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
2031 self.assertEqual(c.setdefault('d', 5), 1)
2032 self.assertEqual(c['d'], 1)
2033 self.assertEqual(c.setdefault('e', 5), 5)
2034 self.assertEqual(c['e'], 5)
2035
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002036 def test_init(self):
2037 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
2038 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
2039 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
2040 self.assertRaises(TypeError, Counter, 42)
2041 self.assertRaises(TypeError, Counter, (), ())
2042 self.assertRaises(TypeError, Counter.__init__)
2043
Raymond Hettinger407c7342019-02-21 09:19:00 -08002044 def test_order_preservation(self):
2045 # Input order dictates items() order
2046 self.assertEqual(list(Counter('abracadabra').items()),
2047 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
2048 # letters with same count: ^----------^ ^---------^
2049
2050 # Verify retention of order even when all counts are equal
2051 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
2052 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
2053
2054 # Input order dictates elements() order
2055 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
2056 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
2057 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
2058
2059 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10002060 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08002061 ps = 'aaabbcdddeefggghhijjjkkl'
2062 qs = 'abbcccdeefffhkkllllmmnno'
2063 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
2064 def correctly_ordered(seq):
2065 'Return true if the letters occur in the expected order'
2066 positions = [order[letter] for letter in seq]
2067 return positions == sorted(positions)
2068
2069 p, q = Counter(ps), Counter(qs)
2070 self.assertTrue(correctly_ordered(+p))
2071 self.assertTrue(correctly_ordered(-p))
2072 self.assertTrue(correctly_ordered(p + q))
2073 self.assertTrue(correctly_ordered(p - q))
2074 self.assertTrue(correctly_ordered(p | q))
2075 self.assertTrue(correctly_ordered(p & q))
2076
2077 p, q = Counter(ps), Counter(qs)
2078 p += q
2079 self.assertTrue(correctly_ordered(p))
2080
2081 p, q = Counter(ps), Counter(qs)
2082 p -= q
2083 self.assertTrue(correctly_ordered(p))
2084
2085 p, q = Counter(ps), Counter(qs)
2086 p |= q
2087 self.assertTrue(correctly_ordered(p))
2088
2089 p, q = Counter(ps), Counter(qs)
2090 p &= q
2091 self.assertTrue(correctly_ordered(p))
2092
2093 p, q = Counter(ps), Counter(qs)
2094 p.update(q)
2095 self.assertTrue(correctly_ordered(p))
2096
2097 p, q = Counter(ps), Counter(qs)
2098 p.subtract(q)
2099 self.assertTrue(correctly_ordered(p))
2100
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002101 def test_update(self):
2102 c = Counter()
2103 c.update(self=42)
2104 self.assertEqual(list(c.items()), [('self', 42)])
2105 c = Counter()
2106 c.update(iterable=42)
2107 self.assertEqual(list(c.items()), [('iterable', 42)])
2108 c = Counter()
2109 c.update(iterable=None)
2110 self.assertEqual(list(c.items()), [('iterable', None)])
2111 self.assertRaises(TypeError, Counter().update, 42)
2112 self.assertRaises(TypeError, Counter().update, {}, {})
2113 self.assertRaises(TypeError, Counter.update)
2114
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002115 def test_copying(self):
2116 # Check that counters are copyable, deepcopyable, picklable, and
2117 #have a repr/eval round-trip
2118 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002119 def check(dup):
2120 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2121 self.assertIsNot(dup, words, msg)
2122 self.assertEqual(dup, words)
2123 check(words.copy())
2124 check(copy.copy(words))
2125 check(copy.deepcopy(words))
2126 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2127 with self.subTest(proto=proto):
2128 check(pickle.loads(pickle.dumps(words, proto)))
2129 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002130 update_test = Counter()
2131 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002132 check(update_test)
2133 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002134
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002135 def test_copy_subclass(self):
2136 class MyCounter(Counter):
2137 pass
2138 c = MyCounter('slartibartfast')
2139 d = c.copy()
2140 self.assertEqual(d, c)
2141 self.assertEqual(len(d), len(c))
2142 self.assertEqual(type(d), type(c))
2143
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002144 def test_conversions(self):
2145 # Convert to: set, list, dict
2146 s = 'she sells sea shells by the sea shore'
2147 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2148 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2149 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2150 self.assertEqual(set(Counter(s)), set(s))
2151
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002152 def test_invariant_for_the_in_operator(self):
2153 c = Counter(a=10, b=-2, c=0)
2154 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002155 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002156 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002157
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002158 def test_multiset_operations(self):
2159 # Verify that adding a zero counter will strip zeros and negatives
2160 c = Counter(a=10, b=-2, c=0) + Counter()
2161 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002162
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002163 elements = 'abcd'
2164 for i in range(1000):
2165 # test random pairs of multisets
2166 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002167 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002168 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002169 q.update(h=1, i=-1, j=0)
2170 for counterop, numberop in [
2171 (Counter.__add__, lambda x, y: max(0, x+y)),
2172 (Counter.__sub__, lambda x, y: max(0, x-y)),
2173 (Counter.__or__, lambda x, y: max(0,x,y)),
2174 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002175 ]:
2176 result = counterop(p, q)
2177 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002178 self.assertEqual(numberop(p[x], q[x]), result[x],
2179 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002180 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002181 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002182
2183 elements = 'abcdef'
2184 for i in range(100):
2185 # verify that random multisets with no repeats are exactly like sets
2186 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2187 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2188 for counterop, setop in [
2189 (Counter.__sub__, set.__sub__),
2190 (Counter.__or__, set.__or__),
2191 (Counter.__and__, set.__and__),
2192 ]:
2193 counter_result = counterop(p, q)
2194 set_result = setop(set(p.elements()), set(q.elements()))
2195 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002196
Raymond Hettinger1ca8fb12019-12-16 01:54:14 -08002197 def test_subset_superset_not_implemented(self):
2198 # Verify that multiset comparison operations are not implemented.
2199
2200 # These operations were intentionally omitted because multiset
2201 # comparison semantics conflict with existing dict equality semantics.
2202
2203 # For multisets, we would expect that if p<=q and p>=q are both true,
2204 # then p==q. However, dict equality semantics require that p!=q when
2205 # one of sets contains an element with a zero count and the other
2206 # doesn't.
2207
2208 p = Counter(a=1, b=0)
2209 q = Counter(a=1, c=0)
2210 self.assertNotEqual(p, q)
2211 with self.assertRaises(TypeError):
2212 p < q
2213 with self.assertRaises(TypeError):
2214 p <= q
2215 with self.assertRaises(TypeError):
2216 p > q
2217 with self.assertRaises(TypeError):
2218 p >= q
2219
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002220 def test_inplace_operations(self):
2221 elements = 'abcd'
2222 for i in range(1000):
2223 # test random pairs of multisets
2224 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2225 p.update(e=1, f=-1, g=0)
2226 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2227 q.update(h=1, i=-1, j=0)
2228 for inplace_op, regular_op in [
2229 (Counter.__iadd__, Counter.__add__),
2230 (Counter.__isub__, Counter.__sub__),
2231 (Counter.__ior__, Counter.__or__),
2232 (Counter.__iand__, Counter.__and__),
2233 ]:
2234 c = p.copy()
2235 c_id = id(c)
2236 regular_result = regular_op(c, q)
2237 inplace_result = inplace_op(c, q)
2238 self.assertEqual(inplace_result, regular_result)
2239 self.assertEqual(id(inplace_result), c_id)
2240
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002241 def test_subtract(self):
2242 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2243 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2244 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2245 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2246 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2247 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2248 c = Counter('aaabbcd')
2249 c.subtract('aaaabbcce')
2250 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002251
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002252 c = Counter()
2253 c.subtract(self=42)
2254 self.assertEqual(list(c.items()), [('self', -42)])
2255 c = Counter()
2256 c.subtract(iterable=42)
2257 self.assertEqual(list(c.items()), [('iterable', -42)])
2258 self.assertRaises(TypeError, Counter().subtract, 42)
2259 self.assertRaises(TypeError, Counter().subtract, {}, {})
2260 self.assertRaises(TypeError, Counter.subtract)
2261
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002262 def test_unary(self):
2263 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2264 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2265 self.assertEqual(dict(-c), dict(a=5))
2266
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002267 def test_repr_nonsortable(self):
2268 c = Counter(a=2, b=None)
2269 r = repr(c)
2270 self.assertIn("'a': 2", r)
2271 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002272
Raymond Hettinger426e0522011-01-03 02:12:02 +00002273 def test_helper_function(self):
2274 # two paths, one for real dicts and one for other mappings
2275 elems = list('abracadabra')
2276
2277 d = dict()
2278 _count_elements(d, elems)
2279 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2280
2281 m = OrderedDict()
2282 _count_elements(m, elems)
2283 self.assertEqual(m,
2284 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2285
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002286 # test fidelity to the pure python version
2287 c = CounterSubclassWithSetItem('abracadabra')
2288 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002289 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002290 c = CounterSubclassWithGet('abracadabra')
2291 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002292 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002293
Raymond Hettinger499e1932011-02-23 07:56:53 +00002294
2295################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002296### Run tests
2297################################################################################
2298
Guido van Rossumd8faa362007-04-27 19:54:29 +00002299def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002300 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002301 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002302 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002303 TestUserObjects,
2304 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002305 support.run_unittest(*test_classes)
2306 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002307
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002308
Guido van Rossumd8faa362007-04-27 19:54:29 +00002309if __name__ == "__main__":
2310 test_main(verbose=True)