blob: 47c500bcdd002505f527fdfcc363a1f752eee4f3 [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
Raymond Hettinger499e1932011-02-23 07:56:53 +0000198 def test_dict_coercion(self):
199 d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
200 self.assertEqual(dict(d), dict(a=1, b=2, c=30))
201 self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
202
Vinay Sajip1ba81ee2013-01-11 23:39:53 +0000203 def test_new_child(self):
204 'Tests for changes for issue #16613.'
205 c = ChainMap()
206 c['a'] = 1
207 c['b'] = 2
208 m = {'b':20, 'c': 30}
209 d = c.new_child(m)
210 self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
211 self.assertIs(m, d.maps[0])
212
213 # Use a different map than a dict
214 class lowerdict(dict):
215 def __getitem__(self, key):
216 if isinstance(key, str):
217 key = key.lower()
218 return dict.__getitem__(self, key)
219 def __contains__(self, key):
220 if isinstance(key, str):
221 key = key.lower()
222 return dict.__contains__(self, key)
223
224 c = ChainMap()
225 c['a'] = 1
226 c['b'] = 2
227 m = lowerdict(b=20, c=30)
228 d = c.new_child(m)
229 self.assertIs(m, d.maps[0])
230 for key in 'abc': # check contains
231 self.assertIn(key, d)
232 for k, v in dict(a=1, B=20, C=30, z=100).items(): # check get
233 self.assertEqual(d.get(k, 100), v)
234
Curtis Bucherf393b2c2020-03-23 12:02:05 -0700235 def test_union_operators(self):
236 cm1 = ChainMap(dict(a=1, b=2), dict(c=3, d=4))
237 cm2 = ChainMap(dict(a=10, e=5), dict(b=20, d=4))
238 cm3 = cm1.copy()
239 d = dict(a=10, c=30)
240 pairs = [('c', 3), ('p',0)]
241
242 tmp = cm1 | cm2 # testing between chainmaps
243 self.assertEqual(tmp.maps, [cm1.maps[0] | dict(cm2), *cm1.maps[1:]])
244 cm1 |= cm2
245 self.assertEqual(tmp, cm1)
246
247 tmp = cm2 | d # testing between chainmap and mapping
248 self.assertEqual(tmp.maps, [cm2.maps[0] | d, *cm2.maps[1:]])
249 self.assertEqual((d | cm2).maps, [d | dict(cm2)])
250 cm2 |= d
251 self.assertEqual(tmp, cm2)
252
253 # testing behavior between chainmap and iterable key-value pairs
254 with self.assertRaises(TypeError):
255 cm3 | pairs
256 cm3 |= pairs
257 self.assertEqual(cm3.maps, [cm3.maps[0] | dict(pairs), *cm3.maps[1:]])
258
259 # testing proper return types for ChainMap and it's subclasses
260 class Subclass(ChainMap):
261 pass
262
263 class SubclassRor(ChainMap):
264 def __ror__(self, other):
265 return super().__ror__(other)
266
267 tmp = ChainMap() | ChainMap()
268 self.assertIs(type(tmp), ChainMap)
269 self.assertIs(type(tmp.maps[0]), dict)
270 tmp = ChainMap() | Subclass()
271 self.assertIs(type(tmp), ChainMap)
272 self.assertIs(type(tmp.maps[0]), dict)
273 tmp = Subclass() | ChainMap()
274 self.assertIs(type(tmp), Subclass)
275 self.assertIs(type(tmp.maps[0]), dict)
276 tmp = ChainMap() | SubclassRor()
277 self.assertIs(type(tmp), SubclassRor)
278 self.assertIs(type(tmp.maps[0]), dict)
279
Raymond Hettinger499e1932011-02-23 07:56:53 +0000280
281################################################################################
282### Named Tuples
283################################################################################
284
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000285TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +0000286
287class TestNamedTuple(unittest.TestCase):
288
289 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000290 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000291 self.assertEqual(Point.__name__, 'Point')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000292 self.assertEqual(Point.__slots__, ())
293 self.assertEqual(Point.__module__, __name__)
294 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +0000295 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000296
297 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
298 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
299 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
300
301 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
302 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
303 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +0000304 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000305 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
306
307 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +0000308 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +0000309
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000310 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000311 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000312 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
Benjamin Peterson577473f2010-01-19 00:09:57 +0000313 self.assertNotIn("u'", repr(nt._fields))
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +0000314
Christian Heimesfaf2f632008-01-06 16:59:19 +0000315 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
316 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
317
Raymond Hettinger39482072018-01-10 21:45:19 -0800318 def test_defaults(self):
319 Point = namedtuple('Point', 'x y', defaults=(10, 20)) # 2 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700320 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800321 self.assertEqual(Point(1, 2), (1, 2))
322 self.assertEqual(Point(1), (1, 20))
323 self.assertEqual(Point(), (10, 20))
324
325 Point = namedtuple('Point', 'x y', defaults=(20,)) # 1 default
Raymond Hettinger23581c02019-03-18 00:27:39 -0700326 self.assertEqual(Point._field_defaults, {'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800327 self.assertEqual(Point(1, 2), (1, 2))
328 self.assertEqual(Point(1), (1, 20))
329
330 Point = namedtuple('Point', 'x y', defaults=()) # 0 defaults
Raymond Hettinger23581c02019-03-18 00:27:39 -0700331 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800332 self.assertEqual(Point(1, 2), (1, 2))
333 with self.assertRaises(TypeError):
334 Point(1)
335
336 with self.assertRaises(TypeError): # catch too few args
337 Point()
338 with self.assertRaises(TypeError): # catch too many args
339 Point(1, 2, 3)
340 with self.assertRaises(TypeError): # too many defaults
341 Point = namedtuple('Point', 'x y', defaults=(10, 20, 30))
342 with self.assertRaises(TypeError): # non-iterable defaults
343 Point = namedtuple('Point', 'x y', defaults=10)
344 with self.assertRaises(TypeError): # another non-iterable default
345 Point = namedtuple('Point', 'x y', defaults=False)
346
347 Point = namedtuple('Point', 'x y', defaults=None) # default is None
Raymond Hettinger23581c02019-03-18 00:27:39 -0700348 self.assertEqual(Point._field_defaults, {})
Raymond Hettinger39482072018-01-10 21:45:19 -0800349 self.assertIsNone(Point.__new__.__defaults__, None)
350 self.assertEqual(Point(10, 20), (10, 20))
351 with self.assertRaises(TypeError): # catch too few args
352 Point(10)
353
354 Point = namedtuple('Point', 'x y', defaults=[10, 20]) # allow non-tuple iterable
Raymond Hettinger23581c02019-03-18 00:27:39 -0700355 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800356 self.assertEqual(Point.__new__.__defaults__, (10, 20))
357 self.assertEqual(Point(1, 2), (1, 2))
358 self.assertEqual(Point(1), (1, 20))
359 self.assertEqual(Point(), (10, 20))
360
361 Point = namedtuple('Point', 'x y', defaults=iter([10, 20])) # allow plain iterator
Raymond Hettinger23581c02019-03-18 00:27:39 -0700362 self.assertEqual(Point._field_defaults, {'x': 10, 'y': 20})
Raymond Hettinger39482072018-01-10 21:45:19 -0800363 self.assertEqual(Point.__new__.__defaults__, (10, 20))
364 self.assertEqual(Point(1, 2), (1, 2))
365 self.assertEqual(Point(1), (1, 20))
366 self.assertEqual(Point(), (10, 20))
367
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200368 def test_readonly(self):
369 Point = namedtuple('Point', 'x y')
370 p = Point(11, 22)
371 with self.assertRaises(AttributeError):
372 p.x = 33
373 with self.assertRaises(AttributeError):
374 del p.x
375 with self.assertRaises(TypeError):
376 p[0] = 33
377 with self.assertRaises(TypeError):
378 del p[0]
379 self.assertEqual(p.x, 11)
380 self.assertEqual(p[0], 11)
Raymond Hettinger39482072018-01-10 21:45:19 -0800381
R. David Murray378c0cf2010-02-24 01:46:21 +0000382 @unittest.skipIf(sys.flags.optimize >= 2,
383 "Docstrings are omitted with -O2 and above")
384 def test_factory_doc_attr(self):
385 Point = namedtuple('Point', 'x y')
386 self.assertEqual(Point.__doc__, 'Point(x, y)')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200387 Point.__doc__ = '2D point'
388 self.assertEqual(Point.__doc__, '2D point')
R. David Murray378c0cf2010-02-24 01:46:21 +0000389
Raymond Hettingereac503a2015-05-13 01:09:59 -0700390 @unittest.skipIf(sys.flags.optimize >= 2,
391 "Docstrings are omitted with -O2 and above")
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200392 def test_field_doc(self):
Raymond Hettingereac503a2015-05-13 01:09:59 -0700393 Point = namedtuple('Point', 'x y')
394 self.assertEqual(Point.x.__doc__, 'Alias for field number 0')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200395 self.assertEqual(Point.y.__doc__, 'Alias for field number 1')
Raymond Hettingereac503a2015-05-13 01:09:59 -0700396 Point.x.__doc__ = 'docstring for Point.x'
397 self.assertEqual(Point.x.__doc__, 'docstring for Point.x')
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200398 # namedtuple can mutate doc of descriptors independently
399 Vector = namedtuple('Vector', 'x y')
400 self.assertEqual(Vector.x.__doc__, 'Alias for field number 0')
401 Vector.x.__doc__ = 'docstring for Vector.x'
402 self.assertEqual(Vector.x.__doc__, 'docstring for Vector.x')
403
404 @support.cpython_only
405 @unittest.skipIf(sys.flags.optimize >= 2,
406 "Docstrings are omitted with -O2 and above")
407 def test_field_doc_reuse(self):
408 P = namedtuple('P', ['m', 'n'])
409 Q = namedtuple('Q', ['o', 'p'])
410 self.assertIs(P.m.__doc__, Q.o.__doc__)
411 self.assertIs(P.n.__doc__, Q.p.__doc__)
Raymond Hettingereac503a2015-05-13 01:09:59 -0700412
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000413 def test_name_fixer(self):
414 for spec, renamed in [
Raymond Hettinger56145242009-04-02 22:31:59 +0000415 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
416 [('abc', 'class'), ('abc', '_1')], # field has keyword
417 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
418 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
419 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
420 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Benjamin Petersona86f2c02009-02-10 02:41:10 +0000421 ]:
422 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
423
Raymond Hettinger0d5048c2016-09-12 00:18:31 -0700424 def test_module_parameter(self):
425 NT = namedtuple('NT', ['x', 'y'], module=collections)
426 self.assertEqual(NT.__module__, collections)
427
Guido van Rossumd8faa362007-04-27 19:54:29 +0000428 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000429 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000430 p = Point(11, 22)
431 self.assertEqual(p, Point(x=11, y=22))
432 self.assertEqual(p, Point(11, y=22))
433 self.assertEqual(p, Point(y=22, x=11))
434 self.assertEqual(p, Point(*(11, 22)))
435 self.assertEqual(p, Point(**dict(x=11, y=22)))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200436 self.assertRaises(TypeError, Point, 1) # too few args
437 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
438 with self.assertRaises(TypeError): # wrong keyword argument
439 Point(XXX=1, y=2)
440 with self.assertRaises(TypeError): # missing keyword argument
441 Point(x=1)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000442 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Benjamin Peterson577473f2010-01-19 00:09:57 +0000443 self.assertNotIn('__weakref__', dir(p))
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200444 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
445 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
446 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
447 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000448
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000449 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000450 p._replace(x=1, error=2)
451 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000452 pass
453 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +0000454 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +0000455
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000456 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000457 Point = namedtuple('Point', 'x, y')
458 p = Point(x=11, y=22)
459 self.assertEqual(repr(p), 'Point(x=11, y=22)')
460
461 # verify that fieldspec can be a non-string sequence
462 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000463 p = Point(x=11, y=22)
464 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000465
466 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000467 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +0000468 p = Point(11, 22)
469
Ezio Melottie9615932010-01-24 19:26:24 +0000470 self.assertIsInstance(p, tuple)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000471 self.assertEqual(p, (11, 22)) # matches a real tuple
Min ho Kimc4cacc82019-07-31 08:16:13 +1000472 self.assertEqual(tuple(p), (11, 22)) # coercible to a real tuple
473 self.assertEqual(list(p), [11, 22]) # coercible to a list
Guido van Rossumd8faa362007-04-27 19:54:29 +0000474 self.assertEqual(max(p), 22) # iterable
475 self.assertEqual(max(*p), 22) # star-able
476 x, y = p
477 self.assertEqual(p, (x, y)) # unpacks like a tuple
478 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200479 with self.assertRaises(IndexError):
480 p[3]
481 self.assertEqual(p[-1], 22)
482 self.assertEqual(hash(p), hash((11, 22)))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000483
484 self.assertEqual(p.x, x)
485 self.assertEqual(p.y, y)
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200486 with self.assertRaises(AttributeError):
487 p.z
Guido van Rossumd8faa362007-04-27 19:54:29 +0000488
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000489 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000490 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000491 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000492 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000493 self.assertEqual(repr(Zero()), 'Zero()')
494 self.assertEqual(Zero()._asdict(), {})
495 self.assertEqual(Zero()._fields, ())
496
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000497 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000498 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000499 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000500 self.assertEqual(Dot(1).d, 1)
501 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
502 self.assertEqual(Dot(1)._asdict(), {'d':1})
503 self.assertEqual(Dot(1)._replace(d=999), (999,))
504 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000505
Serhiy Storchaka5bb8b912016-12-16 19:19:02 +0200506 n = 5000
Serhiy Storchaka33e7ea52015-11-25 17:09:01 +0200507 names = list(set(''.join([choice(string.ascii_letters)
Georg Brandlb533e262008-05-25 18:19:30 +0000508 for j in range(10)]) for i in range(n)))
509 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000510 Big = namedtuple('Big', names)
511 b = Big(*range(n))
512 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000513 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000514 for pos, name in enumerate(names):
515 self.assertEqual(getattr(b, name), pos)
516 repr(b) # make sure repr() doesn't blow-up
517 d = b._asdict()
518 d_expected = dict(zip(names, range(n)))
519 self.assertEqual(d, d_expected)
520 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
521 b2_expected = list(range(n))
522 b2_expected[1] = 999
523 b2_expected[-5] = 42
524 self.assertEqual(b2, tuple(b2_expected))
525 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000526
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000527 def test_pickle(self):
528 p = TestNT(x=10, y=20, z=30)
529 for module in (pickle,):
530 loads = getattr(module, 'loads')
531 dumps = getattr(module, 'dumps')
Eric V. Smith4d5d69d2014-02-05 10:33:14 -0500532 for protocol in range(-1, module.HIGHEST_PROTOCOL + 1):
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000533 q = loads(dumps(p, protocol))
534 self.assertEqual(p, q)
535 self.assertEqual(p._fields, q._fields)
Raymond Hettingerb98dcc12013-05-03 02:24:15 -0700536 self.assertNotIn(b'OrderedDict', dumps(p, protocol))
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000537
538 def test_copy(self):
539 p = TestNT(x=10, y=20, z=30)
540 for copier in copy.copy, copy.deepcopy:
541 q = copier(p)
542 self.assertEqual(p, q)
543 self.assertEqual(p._fields, q._fields)
544
Raymond Hettinger089ba7f2009-05-27 00:38:24 +0000545 def test_name_conflicts(self):
546 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
547 # failed when used as field names. Test to make sure these now work.
548 T = namedtuple('T', 'itemgetter property self cls tuple')
549 t = T(1, 2, 3, 4, 5)
550 self.assertEqual(t, (1,2,3,4,5))
551 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
552 self.assertEqual(newt, (10,20,30,40,50))
553
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700554 # Broader test of all interesting names taken from the code, old
555 # template, and an example
556 words = {'Alias', 'At', 'AttributeError', 'Build', 'Bypass', 'Create',
557 'Encountered', 'Expected', 'Field', 'For', 'Got', 'Helper',
558 'IronPython', 'Jython', 'KeyError', 'Make', 'Modify', 'Note',
559 'OrderedDict', 'Point', 'Return', 'Returns', 'Type', 'TypeError',
560 'Used', 'Validate', 'ValueError', 'Variables', 'a', 'accessible', 'add',
561 'added', 'all', 'also', 'an', 'arg_list', 'args', 'arguments',
562 'automatically', 'be', 'build', 'builtins', 'but', 'by', 'cannot',
563 'class_namespace', 'classmethod', 'cls', 'collections', 'convert',
564 'copy', 'created', 'creation', 'd', 'debugging', 'defined', 'dict',
565 'dictionary', 'doc', 'docstring', 'docstrings', 'duplicate', 'effect',
566 'either', 'enumerate', 'environments', 'error', 'example', 'exec', 'f',
567 'f_globals', 'field', 'field_names', 'fields', 'formatted', 'frame',
568 'function', 'functions', 'generate', 'get', 'getter', 'got', 'greater',
569 'has', 'help', 'identifiers', 'index', 'indexable', 'instance',
570 'instantiate', 'interning', 'introspection', 'isidentifier',
571 'isinstance', 'itemgetter', 'iterable', 'join', 'keyword', 'keywords',
572 'kwds', 'len', 'like', 'list', 'map', 'maps', 'message', 'metadata',
573 'method', 'methods', 'module', 'module_name', 'must', 'name', 'named',
574 'namedtuple', 'namedtuple_', 'names', 'namespace', 'needs', 'new',
575 'nicely', 'num_fields', 'number', 'object', 'of', 'operator', 'option',
576 'p', 'particular', 'pickle', 'pickling', 'plain', 'pop', 'positional',
577 'property', 'r', 'regular', 'rename', 'replace', 'replacing', 'repr',
578 'repr_fmt', 'representation', 'result', 'reuse_itemgetter', 's', 'seen',
579 'self', 'sequence', 'set', 'side', 'specified', 'split', 'start',
580 'startswith', 'step', 'str', 'string', 'strings', 'subclass', 'sys',
581 'targets', 'than', 'the', 'their', 'this', 'to', 'tuple', 'tuple_new',
582 'type', 'typename', 'underscore', 'unexpected', 'unpack', 'up', 'use',
583 'used', 'user', 'valid', 'values', 'variable', 'verbose', 'where',
584 'which', 'work', 'x', 'y', 'z', 'zip'}
Raymond Hettinger499b2ee2009-05-27 01:53:46 +0000585 T = namedtuple('T', words)
586 # test __new__
587 values = tuple(range(len(words)))
588 t = T(*values)
589 self.assertEqual(t, values)
590 t = T(**dict(zip(T._fields, values)))
591 self.assertEqual(t, values)
592 # test _make
593 t = T._make(values)
594 self.assertEqual(t, values)
595 # exercise __repr__
596 repr(t)
597 # test _asdict
598 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
599 # test _replace
600 t = T._make(values)
601 newvalues = tuple(v*10 for v in values)
602 newt = t._replace(**dict(zip(T._fields, newvalues)))
603 self.assertEqual(newt, newvalues)
604 # test _fields
605 self.assertEqual(T._fields, tuple(words))
606 # test __getnewargs__
607 self.assertEqual(t.__getnewargs__(), values)
608
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000609 def test_repr(self):
Raymond Hettinger8b57d732017-09-10 10:23:36 -0700610 A = namedtuple('A', 'x')
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000611 self.assertEqual(repr(A(1)), 'A(x=1)')
612 # repr should show the name of the subclass
613 class B(A):
614 pass
615 self.assertEqual(repr(B(1)), 'B(x=1)')
616
Raymond Hettinger6538b432016-08-16 10:55:43 -0700617 def test_keyword_only_arguments(self):
618 # See issue 25628
Raymond Hettinger6538b432016-08-16 10:55:43 -0700619 with self.assertRaises(TypeError):
620 NT = namedtuple('NT', ['x', 'y'], True)
621
622 NT = namedtuple('NT', ['abc', 'def'], rename=True)
623 self.assertEqual(NT._fields, ('abc', '_1'))
624 with self.assertRaises(TypeError):
625 NT = namedtuple('NT', ['abc', 'def'], False, True)
Raymond Hettingerd331ce92010-08-08 01:13:42 +0000626
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700627 def test_namedtuple_subclass_issue_24931(self):
628 class Point(namedtuple('_Point', ['x', 'y'])):
629 pass
630
631 a = Point(3, 4)
632 self.assertEqual(a._asdict(), OrderedDict([('x', 3), ('y', 4)]))
633
634 a.w = 5
635 self.assertEqual(a.__dict__, {'w': 5})
636
Serhiy Storchaka052b2df2018-12-31 14:15:16 +0200637 def test_field_descriptor(self):
638 Point = namedtuple('Point', 'x y')
639 p = Point(11, 22)
640 self.assertTrue(inspect.isdatadescriptor(Point.x))
641 self.assertEqual(Point.x.__get__(p), 11)
642 self.assertRaises(AttributeError, Point.x.__set__, p, 33)
643 self.assertRaises(AttributeError, Point.x.__delete__, p)
Pablo Galindo3f5fc702018-12-30 09:24:03 +0000644
Joe Jevnikf36f8922019-02-21 16:00:40 -0500645 class NewPoint(tuple):
646 x = pickle.loads(pickle.dumps(Point.x))
647 y = pickle.loads(pickle.dumps(Point.y))
648
649 np = NewPoint([1, 2])
650
651 self.assertEqual(np.x, 1)
652 self.assertEqual(np.y, 2)
653
Raymond Hettinger7a3602e2015-08-30 09:13:48 -0700654
Raymond Hettinger499e1932011-02-23 07:56:53 +0000655################################################################################
656### Abstract Base Classes
657################################################################################
658
Raymond Hettingerae650182009-01-28 23:33:59 +0000659class ABCTestCase(unittest.TestCase):
660
661 def validate_abstract_methods(self, abc, *names):
662 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
663
664 # everything should work will all required methods are present
665 C = type('C', (abc,), methodstubs)
666 C()
667
668 # instantiation should fail if a required method is missing
669 for name in names:
670 stubs = methodstubs.copy()
671 del stubs[name]
672 C = type('C', (abc,), stubs)
673 self.assertRaises(TypeError, C, name)
674
Florent Xiclunace153f62010-03-08 15:34:35 +0000675 def validate_isinstance(self, abc, name):
676 stub = lambda s, *args: 0
677
678 C = type('C', (object,), {'__hash__': None})
679 setattr(C, name, stub)
680 self.assertIsInstance(C(), abc)
681 self.assertTrue(issubclass(C, abc))
682
683 C = type('C', (object,), {'__hash__': None})
684 self.assertNotIsInstance(C(), abc)
685 self.assertFalse(issubclass(C, abc))
Raymond Hettingerae650182009-01-28 23:33:59 +0000686
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +0000687 def validate_comparison(self, instance):
688 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
689 operators = {}
690 for op in ops:
691 name = '__' + op + '__'
692 operators[name] = getattr(operator, name)
693
694 class Other:
695 def __init__(self):
696 self.right_side = False
697 def __eq__(self, other):
698 self.right_side = True
699 return True
700 __lt__ = __eq__
701 __gt__ = __eq__
702 __le__ = __eq__
703 __ge__ = __eq__
704 __ne__ = __eq__
705 __ror__ = __eq__
706 __rand__ = __eq__
707 __rxor__ = __eq__
708 __rsub__ = __eq__
709
710 for name, op in operators.items():
711 if not hasattr(instance, name):
712 continue
713 other = Other()
714 op(instance, other)
715 self.assertTrue(other.right_side,'Right side not called for %s.%s'
716 % (type(instance), name))
717
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700718def _test_gen():
719 yield
720
Raymond Hettingerae650182009-01-28 23:33:59 +0000721class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000722
Yury Selivanov75445082015-05-11 22:57:16 -0400723 def test_Awaitable(self):
724 def gen():
725 yield
726
727 @types.coroutine
728 def coro():
729 yield
730
731 async def new_coro():
732 pass
733
734 class Bar:
735 def __await__(self):
736 yield
737
738 class MinimalCoro(Coroutine):
739 def send(self, value):
740 return value
741 def throw(self, typ, val=None, tb=None):
742 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400743 def __await__(self):
744 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400745
746 non_samples = [None, int(), gen(), object()]
747 for x in non_samples:
748 self.assertNotIsInstance(x, Awaitable)
749 self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
750
751 samples = [Bar(), MinimalCoro()]
752 for x in samples:
753 self.assertIsInstance(x, Awaitable)
754 self.assertTrue(issubclass(type(x), Awaitable))
755
756 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400757 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
758 # flag don't have '__await__' method, hence can't be instances
759 # of Awaitable. Use inspect.isawaitable to detect them.
760 self.assertNotIsInstance(c, Awaitable)
Yury Selivanov75445082015-05-11 22:57:16 -0400761
762 c = new_coro()
763 self.assertIsInstance(c, Awaitable)
Mike53f7a7c2017-12-14 14:04:53 +0300764 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400765
Yury Selivanov56fc6142015-05-29 09:01:29 -0400766 class CoroLike: pass
Yury Selivanovaded55c2015-05-13 23:41:55 -0400767 Coroutine.register(CoroLike)
Yury Selivanov08e53002015-05-13 23:57:59 -0400768 self.assertTrue(isinstance(CoroLike(), Awaitable))
769 self.assertTrue(issubclass(CoroLike, Awaitable))
770 CoroLike = None
771 support.gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Yury Selivanovaded55c2015-05-13 23:41:55 -0400772
Yury Selivanov75445082015-05-11 22:57:16 -0400773 def test_Coroutine(self):
774 def gen():
775 yield
776
777 @types.coroutine
778 def coro():
779 yield
780
781 async def new_coro():
782 pass
783
784 class Bar:
785 def __await__(self):
786 yield
787
788 class MinimalCoro(Coroutine):
789 def send(self, value):
790 return value
791 def throw(self, typ, val=None, tb=None):
792 super().throw(typ, val, tb)
Yury Selivanov56fc6142015-05-29 09:01:29 -0400793 def __await__(self):
794 yield
Yury Selivanov75445082015-05-11 22:57:16 -0400795
796 non_samples = [None, int(), gen(), object(), Bar()]
797 for x in non_samples:
798 self.assertNotIsInstance(x, Coroutine)
799 self.assertFalse(issubclass(type(x), Coroutine), repr(type(x)))
800
801 samples = [MinimalCoro()]
802 for x in samples:
803 self.assertIsInstance(x, Awaitable)
804 self.assertTrue(issubclass(type(x), Awaitable))
805
806 c = coro()
Yury Selivanovfdbeb2b2015-07-03 13:11:35 -0400807 # Iterable coroutines (generators with CO_ITERABLE_COROUTINE
808 # flag don't have '__await__' method, hence can't be instances
809 # of Coroutine. Use inspect.isawaitable to detect them.
810 self.assertNotIsInstance(c, Coroutine)
Yury Selivanov75445082015-05-11 22:57:16 -0400811
812 c = new_coro()
813 self.assertIsInstance(c, Coroutine)
Mike53f7a7c2017-12-14 14:04:53 +0300814 c.close() # avoid RuntimeWarning that coro() was not awaited
Yury Selivanov75445082015-05-11 22:57:16 -0400815
Yury Selivanov56fc6142015-05-29 09:01:29 -0400816 class CoroLike:
817 def send(self, value):
818 pass
819 def throw(self, typ, val=None, tb=None):
820 pass
821 def close(self):
822 pass
823 def __await__(self):
824 pass
825 self.assertTrue(isinstance(CoroLike(), Coroutine))
826 self.assertTrue(issubclass(CoroLike, Coroutine))
827
828 class CoroLike:
829 def send(self, value):
830 pass
831 def close(self):
832 pass
833 def __await__(self):
834 pass
835 self.assertFalse(isinstance(CoroLike(), Coroutine))
836 self.assertFalse(issubclass(CoroLike, Coroutine))
837
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000838 def test_Hashable(self):
839 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000840 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000841 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000842 self.assertNotIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000843 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000844 # Check some hashables
845 samples = [None,
846 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000847 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000848 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000849 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000850 ]
851 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000852 self.assertIsInstance(x, Hashable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000853 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000854 self.assertRaises(TypeError, Hashable)
855 # Check direct subclassing
856 class H(Hashable):
857 def __hash__(self):
858 return super().__hash__()
859 self.assertEqual(hash(H()), 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000860 self.assertFalse(issubclass(int, H))
Raymond Hettingerae650182009-01-28 23:33:59 +0000861 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000862 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000863
Yury Selivanove0104ae2015-05-14 12:19:16 -0400864 def test_AsyncIterable(self):
865 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400866 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400867 return self
868 self.assertTrue(isinstance(AI(), AsyncIterable))
869 self.assertTrue(issubclass(AI, AsyncIterable))
870 # Check some non-iterables
871 non_samples = [None, object, []]
872 for x in non_samples:
873 self.assertNotIsInstance(x, AsyncIterable)
874 self.assertFalse(issubclass(type(x), AsyncIterable), repr(type(x)))
875 self.validate_abstract_methods(AsyncIterable, '__aiter__')
876 self.validate_isinstance(AsyncIterable, '__aiter__')
877
878 def test_AsyncIterator(self):
879 class AI:
Yury Selivanovfaa135a2017-10-06 02:08:57 -0400880 def __aiter__(self):
Yury Selivanove0104ae2015-05-14 12:19:16 -0400881 return self
882 async def __anext__(self):
883 raise StopAsyncIteration
884 self.assertTrue(isinstance(AI(), AsyncIterator))
885 self.assertTrue(issubclass(AI, AsyncIterator))
886 non_samples = [None, object, []]
887 # Check some non-iterables
888 for x in non_samples:
889 self.assertNotIsInstance(x, AsyncIterator)
890 self.assertFalse(issubclass(type(x), AsyncIterator), repr(type(x)))
891 # Similarly to regular iterators (see issue 10565)
892 class AnextOnly:
893 async def __anext__(self):
894 raise StopAsyncIteration
895 self.assertNotIsInstance(AnextOnly(), AsyncIterator)
896 self.validate_abstract_methods(AsyncIterator, '__anext__', '__aiter__')
897
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000898 def test_Iterable(self):
899 # Check some non-iterables
900 non_samples = [None, 42, 3.14, 1j]
901 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000902 self.assertNotIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000903 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000904 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000905 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000906 tuple(), list(), set(), frozenset(), dict(),
907 dict().keys(), dict().items(), dict().values(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700908 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000909 (x for x in []),
910 ]
911 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +0000912 self.assertIsInstance(x, Iterable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000913 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000914 # Check direct subclassing
915 class I(Iterable):
916 def __iter__(self):
917 return super().__iter__()
918 self.assertEqual(list(I()), [])
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000919 self.assertFalse(issubclass(str, I))
Raymond Hettingerae650182009-01-28 23:33:59 +0000920 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xiclunace153f62010-03-08 15:34:35 +0000921 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700922 # Check None blocking
923 class It:
924 def __iter__(self): return iter([])
925 class ItBlocked(It):
926 __iter__ = None
927 self.assertTrue(issubclass(It, Iterable))
928 self.assertTrue(isinstance(It(), Iterable))
929 self.assertFalse(issubclass(ItBlocked, Iterable))
930 self.assertFalse(isinstance(ItBlocked(), Iterable))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000931
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700932 def test_Reversible(self):
933 # Check some non-reversibles
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100934 non_samples = [None, 42, 3.14, 1j, set(), frozenset()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700935 for x in non_samples:
936 self.assertNotIsInstance(x, Reversible)
937 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700938 # Check some non-reversible iterables
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100939 non_reversibles = [_test_gen(), (x for x in []), iter([]), reversed([])]
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700940 for x in non_reversibles:
941 self.assertNotIsInstance(x, Reversible)
942 self.assertFalse(issubclass(type(x), Reversible), repr(type(x)))
943 # Check some reversible iterables
944 samples = [bytes(), str(), tuple(), list(), OrderedDict(),
945 OrderedDict().keys(), OrderedDict().items(),
Rémi Lapeyre6531bf62018-11-06 01:38:54 +0100946 OrderedDict().values(), Counter(), Counter().keys(),
947 Counter().items(), Counter().values(), dict(),
948 dict().keys(), dict().items(), dict().values()]
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700949 for x in samples:
950 self.assertIsInstance(x, Reversible)
951 self.assertTrue(issubclass(type(x), Reversible), repr(type(x)))
952 # Check also Mapping, MutableMapping, and Sequence
953 self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence))
954 self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping))
955 self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping))
956 # Check direct subclassing
957 class R(Reversible):
958 def __iter__(self):
959 return iter(list())
960 def __reversed__(self):
961 return iter(list())
962 self.assertEqual(list(reversed(R())), [])
963 self.assertFalse(issubclass(float, R))
964 self.validate_abstract_methods(Reversible, '__reversed__', '__iter__')
Guido van Rossum97c1adf2016-08-18 09:22:23 -0700965 # Check reversible non-iterable (which is not Reversible)
966 class RevNoIter:
967 def __reversed__(self): return reversed([])
968 class RevPlusIter(RevNoIter):
969 def __iter__(self): return iter([])
970 self.assertFalse(issubclass(RevNoIter, Reversible))
971 self.assertFalse(isinstance(RevNoIter(), Reversible))
972 self.assertTrue(issubclass(RevPlusIter, Reversible))
973 self.assertTrue(isinstance(RevPlusIter(), Reversible))
974 # Check None blocking
975 class Rev:
976 def __iter__(self): return iter([])
977 def __reversed__(self): return reversed([])
978 class RevItBlocked(Rev):
979 __iter__ = None
980 class RevRevBlocked(Rev):
981 __reversed__ = None
982 self.assertTrue(issubclass(Rev, Reversible))
983 self.assertTrue(isinstance(Rev(), Reversible))
984 self.assertFalse(issubclass(RevItBlocked, Reversible))
985 self.assertFalse(isinstance(RevItBlocked(), Reversible))
986 self.assertFalse(issubclass(RevRevBlocked, Reversible))
987 self.assertFalse(isinstance(RevRevBlocked(), Reversible))
Guido van Rossum16ca06b2016-04-04 10:59:29 -0700988
Guido van Rossumf0666942016-08-23 10:47:07 -0700989 def test_Collection(self):
990 # Check some non-collections
991 non_collections = [None, 42, 3.14, 1j, lambda x: 2*x]
992 for x in non_collections:
993 self.assertNotIsInstance(x, Collection)
994 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
995 # Check some non-collection iterables
996 non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),
Raymond Hettinger02556fb2018-01-11 21:53:49 -0800997 (x for x in [])]
Guido van Rossumf0666942016-08-23 10:47:07 -0700998 for x in non_col_iterables:
999 self.assertNotIsInstance(x, Collection)
1000 self.assertFalse(issubclass(type(x), Collection), repr(type(x)))
1001 # Check some collections
1002 samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),
Raymond Hettinger02556fb2018-01-11 21:53:49 -08001003 list(), dict().keys(), dict().items(), dict().values()]
Guido van Rossumf0666942016-08-23 10:47:07 -07001004 for x in samples:
1005 self.assertIsInstance(x, Collection)
1006 self.assertTrue(issubclass(type(x), Collection), repr(type(x)))
1007 # Check also Mapping, MutableMapping, etc.
1008 self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))
1009 self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))
1010 self.assertTrue(issubclass(MutableMapping, Collection),
1011 repr(MutableMapping))
1012 self.assertTrue(issubclass(Set, Collection), repr(Set))
1013 self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))
1014 self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))
1015 # Check direct subclassing
1016 class Col(Collection):
1017 def __iter__(self):
1018 return iter(list())
1019 def __len__(self):
1020 return 0
1021 def __contains__(self, item):
1022 return False
1023 class DerCol(Col): pass
1024 self.assertEqual(list(iter(Col())), [])
1025 self.assertFalse(issubclass(list, Col))
1026 self.assertFalse(issubclass(set, Col))
1027 self.assertFalse(issubclass(float, Col))
1028 self.assertEqual(list(iter(DerCol())), [])
1029 self.assertFalse(issubclass(list, DerCol))
1030 self.assertFalse(issubclass(set, DerCol))
1031 self.assertFalse(issubclass(float, DerCol))
1032 self.validate_abstract_methods(Collection, '__len__', '__iter__',
1033 '__contains__')
1034 # Check sized container non-iterable (which is not Collection) etc.
1035 class ColNoIter:
1036 def __len__(self): return 0
1037 def __contains__(self, item): return False
1038 class ColNoSize:
1039 def __iter__(self): return iter([])
1040 def __contains__(self, item): return False
1041 class ColNoCont:
1042 def __iter__(self): return iter([])
1043 def __len__(self): return 0
1044 self.assertFalse(issubclass(ColNoIter, Collection))
1045 self.assertFalse(isinstance(ColNoIter(), Collection))
1046 self.assertFalse(issubclass(ColNoSize, Collection))
1047 self.assertFalse(isinstance(ColNoSize(), Collection))
1048 self.assertFalse(issubclass(ColNoCont, Collection))
1049 self.assertFalse(isinstance(ColNoCont(), Collection))
1050 # Check None blocking
1051 class SizeBlock:
1052 def __iter__(self): return iter([])
1053 def __contains__(self): return False
1054 __len__ = None
1055 class IterBlock:
1056 def __len__(self): return 0
1057 def __contains__(self): return True
1058 __iter__ = None
1059 self.assertFalse(issubclass(SizeBlock, Collection))
1060 self.assertFalse(isinstance(SizeBlock(), Collection))
1061 self.assertFalse(issubclass(IterBlock, Collection))
1062 self.assertFalse(isinstance(IterBlock(), Collection))
1063 # Check None blocking in subclass
1064 class ColImpl:
1065 def __iter__(self):
1066 return iter(list())
1067 def __len__(self):
1068 return 0
1069 def __contains__(self, item):
1070 return False
1071 class NonCol(ColImpl):
1072 __contains__ = None
1073 self.assertFalse(issubclass(NonCol, Collection))
1074 self.assertFalse(isinstance(NonCol(), Collection))
1075
1076
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001077 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +00001078 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001079 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001080 self.assertNotIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001081 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001082 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001083 iter(tuple()), iter(list()), iter(dict()),
1084 iter(set()), iter(frozenset()),
1085 iter(dict().keys()), iter(dict().items()),
1086 iter(dict().values()),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001087 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001088 (x for x in []),
1089 ]
1090 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001091 self.assertIsInstance(x, Iterator)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001092 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Raymond Hettingeread22222010-11-29 03:56:12 +00001093 self.validate_abstract_methods(Iterator, '__next__', '__iter__')
1094
1095 # Issue 10565
1096 class NextOnly:
1097 def __next__(self):
1098 yield 1
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -08001099 return
Raymond Hettingeread22222010-11-29 03:56:12 +00001100 self.assertNotIsInstance(NextOnly(), Iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001101
Raymond Hettingerbd60e8d2015-05-09 01:07:23 -04001102 def test_Generator(self):
1103 class NonGen1:
1104 def __iter__(self): return self
1105 def __next__(self): return None
1106 def close(self): pass
1107 def throw(self, typ, val=None, tb=None): pass
1108
1109 class NonGen2:
1110 def __iter__(self): return self
1111 def __next__(self): return None
1112 def close(self): pass
1113 def send(self, value): return value
1114
1115 class NonGen3:
1116 def close(self): pass
1117 def send(self, value): return value
1118 def throw(self, typ, val=None, tb=None): pass
1119
1120 non_samples = [
1121 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1122 iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
1123 for x in non_samples:
1124 self.assertNotIsInstance(x, Generator)
1125 self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
1126
1127 class Gen:
1128 def __iter__(self): return self
1129 def __next__(self): return None
1130 def close(self): pass
1131 def send(self, value): return value
1132 def throw(self, typ, val=None, tb=None): pass
1133
1134 class MinimalGen(Generator):
1135 def send(self, value):
1136 return value
1137 def throw(self, typ, val=None, tb=None):
1138 super().throw(typ, val, tb)
1139
1140 def gen():
1141 yield 1
1142
1143 samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
1144 for x in samples:
1145 self.assertIsInstance(x, Iterator)
1146 self.assertIsInstance(x, Generator)
1147 self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
1148 self.validate_abstract_methods(Generator, 'send', 'throw')
1149
1150 # mixin tests
1151 mgen = MinimalGen()
1152 self.assertIs(mgen, iter(mgen))
1153 self.assertIs(mgen.send(None), next(mgen))
1154 self.assertEqual(2, mgen.send(2))
1155 self.assertIsNone(mgen.close())
1156 self.assertRaises(ValueError, mgen.throw, ValueError)
1157 self.assertRaisesRegex(ValueError, "^huhu$",
1158 mgen.throw, ValueError, ValueError("huhu"))
1159 self.assertRaises(StopIteration, mgen.throw, StopIteration())
1160
1161 class FailOnClose(Generator):
1162 def send(self, value): return value
1163 def throw(self, *args): raise ValueError
1164
1165 self.assertRaises(ValueError, FailOnClose().close)
1166
1167 class IgnoreGeneratorExit(Generator):
1168 def send(self, value): return value
1169 def throw(self, *args): pass
1170
1171 self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
1172
Yury Selivanov22214ab2016-11-16 18:25:04 -05001173 def test_AsyncGenerator(self):
1174 class NonAGen1:
1175 def __aiter__(self): return self
1176 def __anext__(self): return None
1177 def aclose(self): pass
1178 def athrow(self, typ, val=None, tb=None): pass
1179
1180 class NonAGen2:
1181 def __aiter__(self): return self
1182 def __anext__(self): return None
1183 def aclose(self): pass
1184 def asend(self, value): return value
1185
1186 class NonAGen3:
1187 def aclose(self): pass
1188 def asend(self, value): return value
1189 def athrow(self, typ, val=None, tb=None): pass
1190
1191 non_samples = [
1192 None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
1193 iter(()), iter([]), NonAGen1(), NonAGen2(), NonAGen3()]
1194 for x in non_samples:
1195 self.assertNotIsInstance(x, AsyncGenerator)
1196 self.assertFalse(issubclass(type(x), AsyncGenerator), repr(type(x)))
1197
1198 class Gen:
1199 def __aiter__(self): return self
1200 async def __anext__(self): return None
1201 async def aclose(self): pass
1202 async def asend(self, value): return value
1203 async def athrow(self, typ, val=None, tb=None): pass
1204
1205 class MinimalAGen(AsyncGenerator):
1206 async def asend(self, value):
1207 return value
1208 async def athrow(self, typ, val=None, tb=None):
1209 await super().athrow(typ, val, tb)
1210
1211 async def gen():
1212 yield 1
1213
1214 samples = [gen(), Gen(), MinimalAGen()]
1215 for x in samples:
1216 self.assertIsInstance(x, AsyncIterator)
1217 self.assertIsInstance(x, AsyncGenerator)
1218 self.assertTrue(issubclass(type(x), AsyncGenerator), repr(type(x)))
1219 self.validate_abstract_methods(AsyncGenerator, 'asend', 'athrow')
1220
1221 def run_async(coro):
1222 result = None
1223 while True:
1224 try:
1225 coro.send(None)
1226 except StopIteration as ex:
1227 result = ex.args[0] if ex.args else None
1228 break
1229 return result
1230
1231 # mixin tests
1232 mgen = MinimalAGen()
1233 self.assertIs(mgen, mgen.__aiter__())
1234 self.assertIs(run_async(mgen.asend(None)), run_async(mgen.__anext__()))
1235 self.assertEqual(2, run_async(mgen.asend(2)))
1236 self.assertIsNone(run_async(mgen.aclose()))
1237 with self.assertRaises(ValueError):
1238 run_async(mgen.athrow(ValueError))
1239
1240 class FailOnClose(AsyncGenerator):
1241 async def asend(self, value): return value
1242 async def athrow(self, *args): raise ValueError
1243
1244 with self.assertRaises(ValueError):
1245 run_async(FailOnClose().aclose())
1246
1247 class IgnoreGeneratorExit(AsyncGenerator):
1248 async def asend(self, value): return value
1249 async def athrow(self, *args): pass
1250
1251 with self.assertRaises(RuntimeError):
1252 run_async(IgnoreGeneratorExit().aclose())
1253
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001254 def test_Sized(self):
1255 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001256 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001257 (x for x in []),
1258 ]
1259 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001260 self.assertNotIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001261 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001262 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001263 tuple(), list(), set(), frozenset(), dict(),
1264 dict().keys(), dict().items(), dict().values(),
1265 ]
1266 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001267 self.assertIsInstance(x, Sized)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001268 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001269 self.validate_abstract_methods(Sized, '__len__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001270 self.validate_isinstance(Sized, '__len__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001271
1272 def test_Container(self):
1273 non_samples = [None, 42, 3.14, 1j,
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001274 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001275 (x for x in []),
1276 ]
1277 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001278 self.assertNotIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001279 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +00001280 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001281 tuple(), list(), set(), frozenset(), dict(),
1282 dict().keys(), dict().items(),
1283 ]
1284 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001285 self.assertIsInstance(x, Container)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001286 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001287 self.validate_abstract_methods(Container, '__contains__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001288 self.validate_isinstance(Container, '__contains__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001289
1290 def test_Callable(self):
1291 non_samples = [None, 42, 3.14, 1j,
1292 "", b"", (), [], {}, set(),
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001293 _test_gen(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001294 (x for x in []),
1295 ]
1296 for x in non_samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001297 self.assertNotIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001298 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001299 samples = [lambda: None,
1300 type, int, object,
1301 len,
1302 list.append, [].append,
1303 ]
1304 for x in samples:
Ezio Melottie9615932010-01-24 19:26:24 +00001305 self.assertIsInstance(x, Callable)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001306 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerae650182009-01-28 23:33:59 +00001307 self.validate_abstract_methods(Callable, '__call__')
Florent Xiclunace153f62010-03-08 15:34:35 +00001308 self.validate_isinstance(Callable, '__call__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001309
1310 def test_direct_subclassing(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001311 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001312 class C(B):
1313 pass
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001314 self.assertTrue(issubclass(C, B))
1315 self.assertFalse(issubclass(int, C))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001316
1317 def test_registration(self):
Guido van Rossum16ca06b2016-04-04 10:59:29 -07001318 for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable:
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001319 class C:
1320 __hash__ = None # Make sure it isn't hashable by default
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001321 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001322 B.register(C)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001323 self.assertTrue(issubclass(C, B))
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001324
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001325class WithSet(MutableSet):
1326
1327 def __init__(self, it=()):
1328 self.data = set(it)
1329
1330 def __len__(self):
1331 return len(self.data)
1332
1333 def __iter__(self):
1334 return iter(self.data)
1335
1336 def __contains__(self, item):
1337 return item in self.data
1338
1339 def add(self, item):
1340 self.data.add(item)
1341
1342 def discard(self, item):
1343 self.data.discard(item)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001344
Raymond Hettingerae650182009-01-28 23:33:59 +00001345class TestCollectionABCs(ABCTestCase):
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001346
1347 # XXX For now, we only test some virtual inheritance properties.
1348 # We should also test the proper behavior of the collection ABCs
1349 # as real base classes or mix-in classes.
1350
1351 def test_Set(self):
1352 for sample in [set, frozenset]:
Ezio Melottie9615932010-01-24 19:26:24 +00001353 self.assertIsInstance(sample(), Set)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001354 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerae650182009-01-28 23:33:59 +00001355 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001356 class MySet(Set):
1357 def __contains__(self, x):
1358 return False
1359 def __len__(self):
1360 return 0
1361 def __iter__(self):
1362 return iter([])
1363 self.validate_comparison(MySet())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001364
Benjamin Peterson41181742008-07-02 20:22:54 +00001365 def test_hash_Set(self):
1366 class OneTwoThreeSet(Set):
1367 def __init__(self):
1368 self.contents = [1, 2, 3]
1369 def __contains__(self, x):
1370 return x in self.contents
1371 def __len__(self):
1372 return len(self.contents)
1373 def __iter__(self):
1374 return iter(self.contents)
1375 def __hash__(self):
1376 return self._hash()
1377 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001378 self.assertTrue(hash(a) == hash(b))
Benjamin Peterson41181742008-07-02 20:22:54 +00001379
Raymond Hettinger2d452ee2014-05-25 18:28:39 -07001380 def test_isdisjoint_Set(self):
1381 class MySet(Set):
1382 def __init__(self, itr):
1383 self.contents = itr
1384 def __contains__(self, x):
1385 return x in self.contents
1386 def __iter__(self):
1387 return iter(self.contents)
1388 def __len__(self):
1389 return len([x for x in self.contents])
1390 s1 = MySet((1, 2, 3))
1391 s2 = MySet((4, 5, 6))
1392 s3 = MySet((1, 5, 6))
1393 self.assertTrue(s1.isdisjoint(s2))
1394 self.assertFalse(s1.isdisjoint(s3))
1395
1396 def test_equality_Set(self):
1397 class MySet(Set):
1398 def __init__(self, itr):
1399 self.contents = itr
1400 def __contains__(self, x):
1401 return x in self.contents
1402 def __iter__(self):
1403 return iter(self.contents)
1404 def __len__(self):
1405 return len([x for x in self.contents])
1406 s1 = MySet((1,))
1407 s2 = MySet((1, 2))
1408 s3 = MySet((3, 4))
1409 s4 = MySet((3, 4))
1410 self.assertTrue(s2 > s1)
1411 self.assertTrue(s1 < s2)
1412 self.assertFalse(s2 <= s1)
1413 self.assertFalse(s2 <= s3)
1414 self.assertFalse(s1 >= s2)
1415 self.assertEqual(s3, s4)
1416 self.assertNotEqual(s2, s3)
1417
1418 def test_arithmetic_Set(self):
1419 class MySet(Set):
1420 def __init__(self, itr):
1421 self.contents = itr
1422 def __contains__(self, x):
1423 return x in self.contents
1424 def __iter__(self):
1425 return iter(self.contents)
1426 def __len__(self):
1427 return len([x for x in self.contents])
1428 s1 = MySet((1, 2, 3))
1429 s2 = MySet((3, 4, 5))
1430 s3 = s1 & s2
1431 self.assertEqual(s3, MySet((3,)))
1432
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001433 def test_MutableSet(self):
Ezio Melottie9615932010-01-24 19:26:24 +00001434 self.assertIsInstance(set(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001435 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottie9615932010-01-24 19:26:24 +00001436 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001437 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerae650182009-01-28 23:33:59 +00001438 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
1439 'add', 'discard')
1440
Raymond Hettinger3f10a952009-04-01 19:05:50 +00001441 def test_issue_5647(self):
1442 # MutableSet.__iand__ mutated the set during iteration
1443 s = WithSet('abcd')
1444 s &= WithSet('cdef') # This used to fail
1445 self.assertEqual(set(s), set('cd'))
1446
Raymond Hettingerae650182009-01-28 23:33:59 +00001447 def test_issue_4920(self):
1448 # MutableSet.pop() method did not work
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001449 class MySet(MutableSet):
Raymond Hettingerae650182009-01-28 23:33:59 +00001450 __slots__=['__s']
1451 def __init__(self,items=None):
1452 if items is None:
1453 items=[]
1454 self.__s=set(items)
1455 def __contains__(self,v):
1456 return v in self.__s
1457 def __iter__(self):
1458 return iter(self.__s)
1459 def __len__(self):
1460 return len(self.__s)
1461 def add(self,v):
1462 result=v not in self.__s
1463 self.__s.add(v)
1464 return result
1465 def discard(self,v):
1466 result=v in self.__s
1467 self.__s.discard(v)
1468 return result
1469 def __repr__(self):
1470 return "MySet(%s)" % repr(list(self))
1471 s = MySet([5,43,2,1])
1472 self.assertEqual(s.pop(), 1)
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001473
Daniel Stutzbach31da5b22010-08-24 20:49:57 +00001474 def test_issue8750(self):
1475 empty = WithSet()
1476 full = WithSet(range(10))
1477 s = WithSet(full)
1478 s -= s
1479 self.assertEqual(s, empty)
1480 s = WithSet(full)
1481 s ^= s
1482 self.assertEqual(s, empty)
1483 s = WithSet(full)
1484 s &= s
1485 self.assertEqual(s, full)
1486 s |= s
1487 self.assertEqual(s, full)
1488
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001489 def test_issue16373(self):
1490 # Recursion error comparing comparable and noncomparable
1491 # Set instances
1492 class MyComparableSet(Set):
1493 def __contains__(self, x):
1494 return False
1495 def __len__(self):
1496 return 0
1497 def __iter__(self):
1498 return iter([])
1499 class MyNonComparableSet(Set):
1500 def __contains__(self, x):
1501 return False
1502 def __len__(self):
1503 return 0
1504 def __iter__(self):
1505 return iter([])
1506 def __le__(self, x):
1507 return NotImplemented
1508 def __lt__(self, x):
1509 return NotImplemented
1510
1511 cs = MyComparableSet()
1512 ncs = MyNonComparableSet()
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001513 self.assertFalse(ncs < cs)
1514 self.assertTrue(ncs <= cs)
1515 self.assertFalse(ncs > cs)
1516 self.assertTrue(ncs >= cs)
1517
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001518 def test_issue26915(self):
1519 # Container membership test should check identity first
Xiang Zhangd5d32492017-03-08 11:04:24 +08001520 class CustomSequence(Sequence):
1521 def __init__(self, seq):
1522 self._seq = seq
1523 def __getitem__(self, index):
1524 return self._seq[index]
1525 def __len__(self):
1526 return len(self._seq)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001527
1528 nan = float('nan')
Serhiy Storchaka7d44e7a2019-08-08 08:43:18 +03001529 obj = support.NEVER_EQ
Xiang Zhangd5d32492017-03-08 11:04:24 +08001530 seq = CustomSequence([nan, obj, nan])
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001531 containers = [
Xiang Zhangd5d32492017-03-08 11:04:24 +08001532 seq,
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001533 ItemsView({1: nan, 2: obj}),
1534 ValuesView({1: nan, 2: obj})
1535 ]
1536 for container in containers:
1537 for elem in container:
1538 self.assertIn(elem, container)
Xiang Zhangd5d32492017-03-08 11:04:24 +08001539 self.assertEqual(seq.index(nan), 0)
1540 self.assertEqual(seq.index(obj), 1)
1541 self.assertEqual(seq.count(nan), 2)
1542 self.assertEqual(seq.count(obj), 1)
Raymond Hettinger584e8ae2016-05-05 11:14:06 +03001543
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001544 def assertSameSet(self, s1, s2):
1545 # coerce both to a real set then check equality
1546 self.assertSetEqual(set(s1), set(s2))
1547
1548 def test_Set_interoperability_with_real_sets(self):
1549 # Issue: 8743
1550 class ListSet(Set):
1551 def __init__(self, elements=()):
1552 self.data = []
1553 for elem in elements:
1554 if elem not in self.data:
1555 self.data.append(elem)
1556 def __contains__(self, elem):
1557 return elem in self.data
1558 def __iter__(self):
1559 return iter(self.data)
1560 def __len__(self):
1561 return len(self.data)
1562 def __repr__(self):
1563 return 'Set({!r})'.format(self.data)
1564
1565 r1 = set('abc')
1566 r2 = set('bcd')
1567 r3 = set('abcde')
1568 f1 = ListSet('abc')
1569 f2 = ListSet('bcd')
1570 f3 = ListSet('abcde')
1571 l1 = list('abccba')
1572 l2 = list('bcddcb')
1573 l3 = list('abcdeedcba')
1574
1575 target = r1 & r2
1576 self.assertSameSet(f1 & f2, target)
1577 self.assertSameSet(f1 & r2, target)
1578 self.assertSameSet(r2 & f1, target)
1579 self.assertSameSet(f1 & l2, target)
1580
1581 target = r1 | r2
1582 self.assertSameSet(f1 | f2, target)
1583 self.assertSameSet(f1 | r2, target)
1584 self.assertSameSet(r2 | f1, target)
1585 self.assertSameSet(f1 | l2, target)
1586
1587 fwd_target = r1 - r2
1588 rev_target = r2 - r1
1589 self.assertSameSet(f1 - f2, fwd_target)
1590 self.assertSameSet(f2 - f1, rev_target)
1591 self.assertSameSet(f1 - r2, fwd_target)
1592 self.assertSameSet(f2 - r1, rev_target)
1593 self.assertSameSet(r1 - f2, fwd_target)
1594 self.assertSameSet(r2 - f1, rev_target)
1595 self.assertSameSet(f1 - l2, fwd_target)
1596 self.assertSameSet(f2 - l1, rev_target)
1597
1598 target = r1 ^ r2
1599 self.assertSameSet(f1 ^ f2, target)
1600 self.assertSameSet(f1 ^ r2, target)
1601 self.assertSameSet(r2 ^ f1, target)
1602 self.assertSameSet(f1 ^ l2, target)
1603
1604 # Don't change the following to use assertLess or other
1605 # "more specific" unittest assertions. The current
1606 # assertTrue/assertFalse style makes the pattern of test
1607 # case combinations clear and allows us to know for sure
1608 # the exact operator being invoked.
1609
1610 # proper subset
1611 self.assertTrue(f1 < f3)
1612 self.assertFalse(f1 < f1)
1613 self.assertFalse(f1 < f2)
1614 self.assertTrue(r1 < f3)
1615 self.assertFalse(r1 < f1)
1616 self.assertFalse(r1 < f2)
1617 self.assertTrue(r1 < r3)
1618 self.assertFalse(r1 < r1)
1619 self.assertFalse(r1 < r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001620 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001621 f1 < l3
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001622 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001623 f1 < l1
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001624 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001625 f1 < l2
1626
1627 # any subset
1628 self.assertTrue(f1 <= f3)
1629 self.assertTrue(f1 <= f1)
1630 self.assertFalse(f1 <= f2)
1631 self.assertTrue(r1 <= f3)
1632 self.assertTrue(r1 <= f1)
1633 self.assertFalse(r1 <= f2)
1634 self.assertTrue(r1 <= r3)
1635 self.assertTrue(r1 <= r1)
1636 self.assertFalse(r1 <= r2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001637 with self.assertRaises(TypeError):
Raymond Hettingerdd5e53a2014-05-26 00:09:04 -07001638 f1 <= l3
1639 with self.assertRaises(TypeError):
1640 f1 <= l1
1641 with self.assertRaises(TypeError):
1642 f1 <= l2
1643
1644 # proper superset
1645 self.assertTrue(f3 > f1)
1646 self.assertFalse(f1 > f1)
1647 self.assertFalse(f2 > f1)
1648 self.assertTrue(r3 > r1)
1649 self.assertFalse(f1 > r1)
1650 self.assertFalse(f2 > r1)
1651 self.assertTrue(r3 > r1)
1652 self.assertFalse(r1 > r1)
1653 self.assertFalse(r2 > r1)
1654 with self.assertRaises(TypeError):
1655 f1 > l3
1656 with self.assertRaises(TypeError):
1657 f1 > l1
1658 with self.assertRaises(TypeError):
1659 f1 > l2
1660
1661 # any superset
1662 self.assertTrue(f3 >= f1)
1663 self.assertTrue(f1 >= f1)
1664 self.assertFalse(f2 >= f1)
1665 self.assertTrue(r3 >= r1)
1666 self.assertTrue(f1 >= r1)
1667 self.assertFalse(f2 >= r1)
1668 self.assertTrue(r3 >= r1)
1669 self.assertTrue(r1 >= r1)
1670 self.assertFalse(r2 >= r1)
1671 with self.assertRaises(TypeError):
1672 f1 >= l3
1673 with self.assertRaises(TypeError):
1674 f1 >=l1
1675 with self.assertRaises(TypeError):
1676 f1 >= l2
1677
1678 # equality
1679 self.assertTrue(f1 == f1)
1680 self.assertTrue(r1 == f1)
1681 self.assertTrue(f1 == r1)
1682 self.assertFalse(f1 == f3)
1683 self.assertFalse(r1 == f3)
1684 self.assertFalse(f1 == r3)
1685 self.assertFalse(f1 == l3)
1686 self.assertFalse(f1 == l1)
1687 self.assertFalse(f1 == l2)
1688
1689 # inequality
1690 self.assertFalse(f1 != f1)
1691 self.assertFalse(r1 != f1)
1692 self.assertFalse(f1 != r1)
1693 self.assertTrue(f1 != f3)
1694 self.assertTrue(r1 != f3)
1695 self.assertTrue(f1 != r3)
1696 self.assertTrue(f1 != l3)
1697 self.assertTrue(f1 != l1)
1698 self.assertTrue(f1 != l2)
Andrew Svetlovbcac6ad2012-11-01 13:28:54 +02001699
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001700 def test_Mapping(self):
1701 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001702 self.assertIsInstance(sample(), Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001703 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001704 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
1705 '__getitem__')
Raymond Hettinger57d1a882011-02-23 00:46:28 +00001706 class MyMapping(Mapping):
Benjamin Peterson4ad6bd52010-05-21 20:55:22 +00001707 def __len__(self):
1708 return 0
1709 def __getitem__(self, i):
1710 raise IndexError
1711 def __iter__(self):
1712 return iter(())
1713 self.validate_comparison(MyMapping())
Guido van Rossum97c1adf2016-08-18 09:22:23 -07001714 self.assertRaises(TypeError, reversed, MyMapping())
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001715
1716 def test_MutableMapping(self):
1717 for sample in [dict]:
Ezio Melottie9615932010-01-24 19:26:24 +00001718 self.assertIsInstance(sample(), MutableMapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001719 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerae650182009-01-28 23:33:59 +00001720 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
1721 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001722
Raymond Hettinger9117c752010-08-22 07:44:24 +00001723 def test_MutableMapping_subclass(self):
1724 # Test issue 9214
1725 mymap = UserDict()
1726 mymap['red'] = 5
1727 self.assertIsInstance(mymap.keys(), Set)
1728 self.assertIsInstance(mymap.keys(), KeysView)
1729 self.assertIsInstance(mymap.items(), Set)
1730 self.assertIsInstance(mymap.items(), ItemsView)
1731
1732 mymap = UserDict()
1733 mymap['red'] = 5
1734 z = mymap.keys() | {'orange'}
1735 self.assertIsInstance(z, set)
1736 list(z)
1737 mymap['blue'] = 7 # Shouldn't affect 'z'
1738 self.assertEqual(sorted(z), ['orange', 'red'])
1739
1740 mymap = UserDict()
1741 mymap['red'] = 5
1742 z = mymap.items() | {('orange', 3)}
1743 self.assertIsInstance(z, set)
1744 list(z)
1745 mymap['blue'] = 7 # Shouldn't affect 'z'
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001746 self.assertEqual(z, {('orange', 3), ('red', 5)})
Raymond Hettinger9117c752010-08-22 07:44:24 +00001747
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001748 def test_Sequence(self):
1749 for sample in [tuple, list, bytes, str]:
Ezio Melottie9615932010-01-24 19:26:24 +00001750 self.assertIsInstance(sample(), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001751 self.assertTrue(issubclass(sample, Sequence))
Ezio Melottie9615932010-01-24 19:26:24 +00001752 self.assertIsInstance(range(10), Sequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001753 self.assertTrue(issubclass(range, Sequence))
Nick Coghlan45163cc2013-10-02 22:31:47 +10001754 self.assertIsInstance(memoryview(b""), Sequence)
1755 self.assertTrue(issubclass(memoryview, Sequence))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001756 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001757 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
1758 '__getitem__')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001759
Raymond Hettingerec219ba2015-05-22 19:29:22 -07001760 def test_Sequence_mixins(self):
1761 class SequenceSubclass(Sequence):
1762 def __init__(self, seq=()):
1763 self.seq = seq
1764
1765 def __getitem__(self, index):
1766 return self.seq[index]
1767
1768 def __len__(self):
1769 return len(self.seq)
1770
1771 # Compare Sequence.index() behavior to (list|str).index() behavior
1772 def assert_index_same(seq1, seq2, index_args):
1773 try:
1774 expected = seq1.index(*index_args)
1775 except ValueError:
1776 with self.assertRaises(ValueError):
1777 seq2.index(*index_args)
1778 else:
1779 actual = seq2.index(*index_args)
1780 self.assertEqual(
1781 actual, expected, '%r.index%s' % (seq1, index_args))
1782
1783 for ty in list, str:
1784 nativeseq = ty('abracadabra')
1785 indexes = [-10000, -9999] + list(range(-3, len(nativeseq) + 3))
1786 seqseq = SequenceSubclass(nativeseq)
1787 for letter in set(nativeseq) | {'z'}:
1788 assert_index_same(nativeseq, seqseq, (letter,))
1789 for start in range(-3, len(nativeseq) + 3):
1790 assert_index_same(nativeseq, seqseq, (letter, start))
1791 for stop in range(-3, len(nativeseq) + 3):
1792 assert_index_same(
1793 nativeseq, seqseq, (letter, start, stop))
1794
Guido van Rossumd05eb002007-11-21 22:26:24 +00001795 def test_ByteString(self):
1796 for sample in [bytes, bytearray]:
Ezio Melottie9615932010-01-24 19:26:24 +00001797 self.assertIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001798 self.assertTrue(issubclass(sample, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001799 for sample in [str, list, tuple]:
Ezio Melottie9615932010-01-24 19:26:24 +00001800 self.assertNotIsInstance(sample(), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001801 self.assertFalse(issubclass(sample, ByteString))
Ezio Melottie9615932010-01-24 19:26:24 +00001802 self.assertNotIsInstance(memoryview(b""), ByteString)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001803 self.assertFalse(issubclass(memoryview, ByteString))
Guido van Rossumd05eb002007-11-21 22:26:24 +00001804
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001805 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +00001806 for sample in [tuple, str, bytes]:
Ezio Melottie9615932010-01-24 19:26:24 +00001807 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001808 self.assertFalse(issubclass(sample, MutableSequence))
Raymond Hettinger32ea1652015-03-21 01:37:37 -07001809 for sample in [list, bytearray, deque]:
Ezio Melottie9615932010-01-24 19:26:24 +00001810 self.assertIsInstance(sample(), MutableSequence)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001811 self.assertTrue(issubclass(sample, MutableSequence))
1812 self.assertFalse(issubclass(str, MutableSequence))
Raymond Hettingerae650182009-01-28 23:33:59 +00001813 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
1814 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001815
Eli Bendersky0716a572011-03-04 10:38:14 +00001816 def test_MutableSequence_mixins(self):
Mike53f7a7c2017-12-14 14:04:53 +03001817 # Test the mixins of MutableSequence by creating a minimal concrete
Eli Bendersky0716a572011-03-04 10:38:14 +00001818 # class inherited from it.
1819 class MutableSequenceSubclass(MutableSequence):
1820 def __init__(self):
1821 self.lst = []
1822
1823 def __setitem__(self, index, value):
1824 self.lst[index] = value
1825
1826 def __getitem__(self, index):
1827 return self.lst[index]
1828
1829 def __len__(self):
1830 return len(self.lst)
1831
1832 def __delitem__(self, index):
1833 del self.lst[index]
1834
1835 def insert(self, index, value):
1836 self.lst.insert(index, value)
1837
1838 mss = MutableSequenceSubclass()
1839 mss.append(0)
1840 mss.extend((1, 2, 3, 4))
1841 self.assertEqual(len(mss), 5)
1842 self.assertEqual(mss[3], 3)
1843 mss.reverse()
1844 self.assertEqual(mss[3], 1)
1845 mss.pop()
1846 self.assertEqual(len(mss), 4)
1847 mss.remove(3)
1848 self.assertEqual(len(mss), 3)
1849 mss += (10, 20, 30)
1850 self.assertEqual(len(mss), 6)
1851 self.assertEqual(mss[-1], 30)
1852 mss.clear()
1853 self.assertEqual(len(mss), 0)
Raymond Hettinger499e1932011-02-23 07:56:53 +00001854
Naris R1b5f9c92018-08-31 02:56:14 +10001855 # issue 34427
1856 # extending self should not cause infinite loop
1857 items = 'ABCD'
1858 mss2 = MutableSequenceSubclass()
1859 mss2.extend(items + items)
1860 mss.clear()
1861 mss.extend(items)
1862 mss.extend(mss)
1863 self.assertEqual(len(mss), len(mss2))
1864 self.assertEqual(list(mss), list(mss2))
1865
1866
Raymond Hettinger499e1932011-02-23 07:56:53 +00001867################################################################################
1868### Counter
1869################################################################################
1870
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07001871class CounterSubclassWithSetItem(Counter):
1872 # Test a counter subclass that overrides __setitem__
1873 def __init__(self, *args, **kwds):
1874 self.called = False
1875 Counter.__init__(self, *args, **kwds)
1876 def __setitem__(self, key, value):
1877 self.called = True
1878 Counter.__setitem__(self, key, value)
1879
1880class CounterSubclassWithGet(Counter):
1881 # Test a counter subclass that overrides get()
1882 def __init__(self, *args, **kwds):
1883 self.called = False
1884 Counter.__init__(self, *args, **kwds)
1885 def get(self, key, default):
1886 self.called = True
1887 return Counter.get(self, key, default)
1888
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001889class TestCounter(unittest.TestCase):
1890
1891 def test_basics(self):
1892 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001893 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
1894 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottie9615932010-01-24 19:26:24 +00001895 self.assertIsInstance(c, dict)
1896 self.assertIsInstance(c, Mapping)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001897 self.assertTrue(issubclass(Counter, dict))
1898 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001899 self.assertEqual(len(c), 3)
1900 self.assertEqual(sum(c.values()), 6)
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001901 self.assertEqual(list(c.values()), [3, 2, 1])
1902 self.assertEqual(list(c.keys()), ['a', 'b', 'c'])
1903 self.assertEqual(list(c), ['a', 'b', 'c'])
1904 self.assertEqual(list(c.items()),
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001905 [('a', 3), ('b', 2), ('c', 1)])
1906 self.assertEqual(c['b'], 2)
1907 self.assertEqual(c['z'], 0)
1908 self.assertEqual(c.__contains__('c'), True)
1909 self.assertEqual(c.__contains__('z'), False)
1910 self.assertEqual(c.get('b', 10), 2)
1911 self.assertEqual(c.get('z', 10), 10)
1912 self.assertEqual(c, dict(a=3, b=2, c=1))
1913 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
1914 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
1915 for i in range(5):
1916 self.assertEqual(c.most_common(i),
1917 [('a', 3), ('b', 2), ('c', 1)][:i])
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001918 self.assertEqual(''.join(c.elements()), 'aaabbc')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001919 c['a'] += 1 # increment an existing value
1920 c['b'] -= 2 # sub existing value to zero
1921 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001922 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001923 c['d'] -= 2 # sub from a missing value
1924 c['e'] = -5 # directly assign a missing value
1925 c['f'] += 4 # add to a missing value
1926 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
Rémi Lapeyre6531bf62018-11-06 01:38:54 +01001927 self.assertEqual(''.join(c.elements()), 'aaaaffff')
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001928 self.assertEqual(c.pop('f'), 4)
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001929 self.assertNotIn('f', c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001930 for i in range(3):
1931 elem, cnt = c.popitem()
Ezio Melottib58e0bd2010-01-23 15:40:09 +00001932 self.assertNotIn(elem, c)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001933 c.clear()
1934 self.assertEqual(c, {})
1935 self.assertEqual(repr(c), 'Counter()')
1936 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
1937 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00001938 c.update(dict(a=5, b=3))
1939 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00001940 c.update(Counter('a' * 50 + 'b' * 30))
1941 c.update() # test case with no args
1942 c.__init__('a' * 500 + 'b' * 300)
1943 c.__init__('cdc')
1944 c.__init__()
1945 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
1946 self.assertEqual(c.setdefault('d', 5), 1)
1947 self.assertEqual(c['d'], 1)
1948 self.assertEqual(c.setdefault('e', 5), 5)
1949 self.assertEqual(c['e'], 5)
1950
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02001951 def test_init(self):
1952 self.assertEqual(list(Counter(self=42).items()), [('self', 42)])
1953 self.assertEqual(list(Counter(iterable=42).items()), [('iterable', 42)])
1954 self.assertEqual(list(Counter(iterable=None).items()), [('iterable', None)])
1955 self.assertRaises(TypeError, Counter, 42)
1956 self.assertRaises(TypeError, Counter, (), ())
1957 self.assertRaises(TypeError, Counter.__init__)
1958
Raymond Hettinger407c7342019-02-21 09:19:00 -08001959 def test_order_preservation(self):
1960 # Input order dictates items() order
1961 self.assertEqual(list(Counter('abracadabra').items()),
1962 [('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)])
1963 # letters with same count: ^----------^ ^---------^
1964
1965 # Verify retention of order even when all counts are equal
1966 self.assertEqual(list(Counter('xyzpdqqdpzyx').items()),
1967 [('x', 2), ('y', 2), ('z', 2), ('p', 2), ('d', 2), ('q', 2)])
1968
1969 # Input order dictates elements() order
1970 self.assertEqual(list(Counter('abracadabra simsalabim').elements()),
1971 ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b','r',
1972 'r', 'c', 'd', ' ', 's', 's', 'i', 'i', 'm', 'm', 'l'])
1973
1974 # Math operations order first by the order encountered in the left
Min ho Kim39d87b52019-08-31 06:21:19 +10001975 # operand and then by the order encountered in the right operand.
Raymond Hettinger407c7342019-02-21 09:19:00 -08001976 ps = 'aaabbcdddeefggghhijjjkkl'
1977 qs = 'abbcccdeefffhkkllllmmnno'
1978 order = {letter: i for i, letter in enumerate(dict.fromkeys(ps + qs))}
1979 def correctly_ordered(seq):
1980 'Return true if the letters occur in the expected order'
1981 positions = [order[letter] for letter in seq]
1982 return positions == sorted(positions)
1983
1984 p, q = Counter(ps), Counter(qs)
1985 self.assertTrue(correctly_ordered(+p))
1986 self.assertTrue(correctly_ordered(-p))
1987 self.assertTrue(correctly_ordered(p + q))
1988 self.assertTrue(correctly_ordered(p - q))
1989 self.assertTrue(correctly_ordered(p | q))
1990 self.assertTrue(correctly_ordered(p & q))
1991
1992 p, q = Counter(ps), Counter(qs)
1993 p += q
1994 self.assertTrue(correctly_ordered(p))
1995
1996 p, q = Counter(ps), Counter(qs)
1997 p -= q
1998 self.assertTrue(correctly_ordered(p))
1999
2000 p, q = Counter(ps), Counter(qs)
2001 p |= q
2002 self.assertTrue(correctly_ordered(p))
2003
2004 p, q = Counter(ps), Counter(qs)
2005 p &= q
2006 self.assertTrue(correctly_ordered(p))
2007
2008 p, q = Counter(ps), Counter(qs)
2009 p.update(q)
2010 self.assertTrue(correctly_ordered(p))
2011
2012 p, q = Counter(ps), Counter(qs)
2013 p.subtract(q)
2014 self.assertTrue(correctly_ordered(p))
2015
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002016 def test_update(self):
2017 c = Counter()
2018 c.update(self=42)
2019 self.assertEqual(list(c.items()), [('self', 42)])
2020 c = Counter()
2021 c.update(iterable=42)
2022 self.assertEqual(list(c.items()), [('iterable', 42)])
2023 c = Counter()
2024 c.update(iterable=None)
2025 self.assertEqual(list(c.items()), [('iterable', None)])
2026 self.assertRaises(TypeError, Counter().update, 42)
2027 self.assertRaises(TypeError, Counter().update, {}, {})
2028 self.assertRaises(TypeError, Counter.update)
2029
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002030 def test_copying(self):
2031 # Check that counters are copyable, deepcopyable, picklable, and
2032 #have a repr/eval round-trip
2033 words = Counter('which witch had which witches wrist watch'.split())
Serhiy Storchakabad12572014-12-15 14:03:42 +02002034 def check(dup):
2035 msg = "\ncopy: %s\nwords: %s" % (dup, words)
2036 self.assertIsNot(dup, words, msg)
2037 self.assertEqual(dup, words)
2038 check(words.copy())
2039 check(copy.copy(words))
2040 check(copy.deepcopy(words))
2041 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2042 with self.subTest(proto=proto):
2043 check(pickle.loads(pickle.dumps(words, proto)))
2044 check(eval(repr(words)))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002045 update_test = Counter()
2046 update_test.update(words)
Serhiy Storchakabad12572014-12-15 14:03:42 +02002047 check(update_test)
2048 check(Counter(words))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002049
Raymond Hettinger1c746c22011-04-15 13:16:46 -07002050 def test_copy_subclass(self):
2051 class MyCounter(Counter):
2052 pass
2053 c = MyCounter('slartibartfast')
2054 d = c.copy()
2055 self.assertEqual(d, c)
2056 self.assertEqual(len(d), len(c))
2057 self.assertEqual(type(d), type(c))
2058
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002059 def test_conversions(self):
2060 # Convert to: set, list, dict
2061 s = 'she sells sea shells by the sea shore'
2062 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
2063 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
2064 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
2065 self.assertEqual(set(Counter(s)), set(s))
2066
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002067 def test_invariant_for_the_in_operator(self):
2068 c = Counter(a=10, b=-2, c=0)
2069 for elem in c:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002070 self.assertTrue(elem in c)
Benjamin Peterson577473f2010-01-19 00:09:57 +00002071 self.assertIn(elem, c)
Raymond Hettinger670eaec2009-01-21 23:14:07 +00002072
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002073 def test_multiset_operations(self):
2074 # Verify that adding a zero counter will strip zeros and negatives
2075 c = Counter(a=10, b=-2, c=0) + Counter()
2076 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002077
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002078 elements = 'abcd'
2079 for i in range(1000):
2080 # test random pairs of multisets
2081 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002082 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002083 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002084 q.update(h=1, i=-1, j=0)
2085 for counterop, numberop in [
2086 (Counter.__add__, lambda x, y: max(0, x+y)),
2087 (Counter.__sub__, lambda x, y: max(0, x-y)),
2088 (Counter.__or__, lambda x, y: max(0,x,y)),
2089 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002090 ]:
2091 result = counterop(p, q)
2092 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +00002093 self.assertEqual(numberop(p[x], q[x]), result[x],
2094 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002095 # verify that results exclude non-positive counts
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002096 self.assertTrue(x>0 for x in result.values())
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00002097
2098 elements = 'abcdef'
2099 for i in range(100):
2100 # verify that random multisets with no repeats are exactly like sets
2101 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2102 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
2103 for counterop, setop in [
2104 (Counter.__sub__, set.__sub__),
2105 (Counter.__or__, set.__or__),
2106 (Counter.__and__, set.__and__),
2107 ]:
2108 counter_result = counterop(p, q)
2109 set_result = setop(set(p.elements()), set(q.elements()))
2110 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002111
Raymond Hettinger1ca8fb12019-12-16 01:54:14 -08002112 def test_subset_superset_not_implemented(self):
2113 # Verify that multiset comparison operations are not implemented.
2114
2115 # These operations were intentionally omitted because multiset
2116 # comparison semantics conflict with existing dict equality semantics.
2117
2118 # For multisets, we would expect that if p<=q and p>=q are both true,
2119 # then p==q. However, dict equality semantics require that p!=q when
2120 # one of sets contains an element with a zero count and the other
2121 # doesn't.
2122
2123 p = Counter(a=1, b=0)
2124 q = Counter(a=1, c=0)
2125 self.assertNotEqual(p, q)
2126 with self.assertRaises(TypeError):
2127 p < q
2128 with self.assertRaises(TypeError):
2129 p <= q
2130 with self.assertRaises(TypeError):
2131 p > q
2132 with self.assertRaises(TypeError):
2133 p >= q
2134
Raymond Hettingerbecd5682011-10-19 13:40:37 -07002135 def test_inplace_operations(self):
2136 elements = 'abcd'
2137 for i in range(1000):
2138 # test random pairs of multisets
2139 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2140 p.update(e=1, f=-1, g=0)
2141 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
2142 q.update(h=1, i=-1, j=0)
2143 for inplace_op, regular_op in [
2144 (Counter.__iadd__, Counter.__add__),
2145 (Counter.__isub__, Counter.__sub__),
2146 (Counter.__ior__, Counter.__or__),
2147 (Counter.__iand__, Counter.__and__),
2148 ]:
2149 c = p.copy()
2150 c_id = id(c)
2151 regular_result = regular_op(c, q)
2152 inplace_result = inplace_op(c, q)
2153 self.assertEqual(inplace_result, regular_result)
2154 self.assertEqual(id(inplace_result), c_id)
2155
Raymond Hettinger9c01e442010-04-03 10:32:58 +00002156 def test_subtract(self):
2157 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2158 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
2159 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2160 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2161 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
2162 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
2163 c = Counter('aaabbcd')
2164 c.subtract('aaaabbcce')
2165 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
Raymond Hettinger2d32f632009-03-02 21:24:57 +00002166
Serhiy Storchakaae5cb212014-11-27 16:25:51 +02002167 c = Counter()
2168 c.subtract(self=42)
2169 self.assertEqual(list(c.items()), [('self', -42)])
2170 c = Counter()
2171 c.subtract(iterable=42)
2172 self.assertEqual(list(c.items()), [('iterable', -42)])
2173 self.assertRaises(TypeError, Counter().subtract, 42)
2174 self.assertRaises(TypeError, Counter().subtract, {}, {})
2175 self.assertRaises(TypeError, Counter.subtract)
2176
Raymond Hettingerfcb393c2011-08-09 13:00:40 -07002177 def test_unary(self):
2178 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
2179 self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
2180 self.assertEqual(dict(-c), dict(a=5))
2181
Raymond Hettinger4e6bf412011-11-05 13:35:26 -07002182 def test_repr_nonsortable(self):
2183 c = Counter(a=2, b=None)
2184 r = repr(c)
2185 self.assertIn("'a': 2", r)
2186 self.assertIn("'b': None", r)
Raymond Hettinger68fb89f2011-11-05 13:43:01 -07002187
Raymond Hettinger426e0522011-01-03 02:12:02 +00002188 def test_helper_function(self):
2189 # two paths, one for real dicts and one for other mappings
2190 elems = list('abracadabra')
2191
2192 d = dict()
2193 _count_elements(d, elems)
2194 self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
2195
2196 m = OrderedDict()
2197 _count_elements(m, elems)
2198 self.assertEqual(m,
2199 OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
2200
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002201 # test fidelity to the pure python version
2202 c = CounterSubclassWithSetItem('abracadabra')
2203 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002204 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002205 c = CounterSubclassWithGet('abracadabra')
2206 self.assertTrue(c.called)
Raymond Hettingerfacd0a32013-10-05 17:14:51 -07002207 self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
Raymond Hettingercb1d96f2013-10-04 16:51:02 -07002208
Raymond Hettinger499e1932011-02-23 07:56:53 +00002209
2210################################################################################
Raymond Hettinger499e1932011-02-23 07:56:53 +00002211### Run tests
2212################################################################################
2213
Guido van Rossumd8faa362007-04-27 19:54:29 +00002214def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +00002215 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +00002216 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerd0321312011-02-26 06:53:58 +00002217 TestCollectionABCs, TestCounter, TestChainMap,
Eric Snow47db7172015-05-29 22:21:39 -06002218 TestUserObjects,
2219 ]
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002220 support.run_unittest(*test_classes)
2221 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +00002222
Guido van Rossumcd16bf62007-06-13 18:07:49 +00002223
Guido van Rossumd8faa362007-04-27 19:54:29 +00002224if __name__ == "__main__":
2225 test_main(verbose=True)