blob: 79e64e6d13b9fa52e0ff01274d0f48829064d7c2 [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +00001"""Unit tests for collections.py."""
2
Christian Heimes25bb7832008-01-11 16:17:00 +00003import unittest, doctest
Benjamin Petersonee8712c2008-05-20 21:35:26 +00004from test import support
Raymond Hettingerb8baf632009-01-14 02:20:07 +00005from collections import namedtuple, Counter, Mapping
Georg Brandlc28e1fa2008-06-10 19:20:26 +00006import pickle, copy
Raymond Hettinger4d2073a2009-01-20 03:41:22 +00007from random import randrange
8import operator
Guido van Rossumcd16bf62007-06-13 18:07:49 +00009from collections import Hashable, Iterable, Iterator
10from collections import Sized, Container, Callable
11from collections import Set, MutableSet
12from collections import Mapping, MutableMapping
13from collections import Sequence, MutableSequence
Guido van Rossumd05eb002007-11-21 22:26:24 +000014from collections import ByteString
Guido van Rossumcd16bf62007-06-13 18:07:49 +000015
Georg Brandlc28e1fa2008-06-10 19:20:26 +000016TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Guido van Rossumd8faa362007-04-27 19:54:29 +000017
18class TestNamedTuple(unittest.TestCase):
19
20 def test_factory(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000021 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000022 self.assertEqual(Point.__name__, 'Point')
23 self.assertEqual(Point.__doc__, 'Point(x, y)')
24 self.assertEqual(Point.__slots__, ())
25 self.assertEqual(Point.__module__, __name__)
26 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Christian Heimesfaf2f632008-01-06 16:59:19 +000027 self.assertEqual(Point._fields, ('x', 'y'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +000028
29 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
30 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
31 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
32
33 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
34 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
35 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Christian Heimes0449f632007-12-15 01:27:15 +000036 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Guido van Rossum8ce8a782007-11-01 19:42:39 +000037 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
38
39 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Christian Heimes0449f632007-12-15 01:27:15 +000040 namedtuple('_', 'a b c') # Test leading underscores in a typename
Guido van Rossumd8faa362007-04-27 19:54:29 +000041
Benjamin Petersone9bbc8b2008-09-28 02:06:32 +000042 nt = namedtuple('nt', 'the quick brown fox') # check unicode input
43 self.assert_("u'" not in repr(nt._fields))
44 nt = namedtuple('nt', ('the', 'quick')) # check unicode input
45 self.assert_("u'" not in repr(nt._fields))
46
Christian Heimesfaf2f632008-01-06 16:59:19 +000047 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
48 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
49
Guido van Rossumd8faa362007-04-27 19:54:29 +000050 def test_instance(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000051 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000052 p = Point(11, 22)
53 self.assertEqual(p, Point(x=11, y=22))
54 self.assertEqual(p, Point(11, y=22))
55 self.assertEqual(p, Point(y=22, x=11))
56 self.assertEqual(p, Point(*(11, 22)))
57 self.assertEqual(p, Point(**dict(x=11, y=22)))
58 self.assertRaises(TypeError, Point, 1) # too few args
59 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
60 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
61 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
62 self.assertEqual(repr(p), 'Point(x=11, y=22)')
63 self.assert_('__dict__' not in dir(p)) # verify instance has no dict
64 self.assert_('__weakref__' not in dir(p))
Christian Heimesfaf2f632008-01-06 16:59:19 +000065 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Christian Heimes0449f632007-12-15 01:27:15 +000066 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
67 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
68 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Thomas Wouters1b7f8912007-09-19 03:06:30 +000069
Guido van Rossum3d392eb2007-11-16 00:35:22 +000070 try:
Christian Heimesfaf2f632008-01-06 16:59:19 +000071 p._replace(x=1, error=2)
72 except ValueError:
Guido van Rossum3d392eb2007-11-16 00:35:22 +000073 pass
74 else:
Christian Heimesfaf2f632008-01-06 16:59:19 +000075 self._fail('Did not detect an incorrect fieldname')
Guido van Rossum3d392eb2007-11-16 00:35:22 +000076
Thomas Wouters1b7f8912007-09-19 03:06:30 +000077 # verify that field string can have commas
Guido van Rossum8ce8a782007-11-01 19:42:39 +000078 Point = namedtuple('Point', 'x, y')
79 p = Point(x=11, y=22)
80 self.assertEqual(repr(p), 'Point(x=11, y=22)')
81
82 # verify that fieldspec can be a non-string sequence
83 Point = namedtuple('Point', ('x', 'y'))
Thomas Wouters1b7f8912007-09-19 03:06:30 +000084 p = Point(x=11, y=22)
85 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Guido van Rossumd8faa362007-04-27 19:54:29 +000086
87 def test_tupleness(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +000088 Point = namedtuple('Point', 'x y')
Guido van Rossumd8faa362007-04-27 19:54:29 +000089 p = Point(11, 22)
90
91 self.assert_(isinstance(p, tuple))
92 self.assertEqual(p, (11, 22)) # matches a real tuple
93 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
94 self.assertEqual(list(p), [11, 22]) # coercable to a list
95 self.assertEqual(max(p), 22) # iterable
96 self.assertEqual(max(*p), 22) # star-able
97 x, y = p
98 self.assertEqual(p, (x, y)) # unpacks like a tuple
99 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
100 self.assertRaises(IndexError, p.__getitem__, 3)
101
102 self.assertEqual(p.x, x)
103 self.assertEqual(p.y, y)
104 self.assertRaises(AttributeError, eval, 'p.z', locals())
105
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000106 def test_odd_sizes(self):
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000107 Zero = namedtuple('Zero', '')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 self.assertEqual(Zero(), ())
Christian Heimesfaf2f632008-01-06 16:59:19 +0000109 self.assertEqual(Zero._make([]), ())
Christian Heimes99170a52007-12-19 02:07:34 +0000110 self.assertEqual(repr(Zero()), 'Zero()')
111 self.assertEqual(Zero()._asdict(), {})
112 self.assertEqual(Zero()._fields, ())
113
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000114 Dot = namedtuple('Dot', 'd')
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 self.assertEqual(Dot(1), (1,))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000116 self.assertEqual(Dot._make([1]), (1,))
Christian Heimes99170a52007-12-19 02:07:34 +0000117 self.assertEqual(Dot(1).d, 1)
118 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
119 self.assertEqual(Dot(1)._asdict(), {'d':1})
120 self.assertEqual(Dot(1)._replace(d=999), (999,))
121 self.assertEqual(Dot(1)._fields, ('d',))
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000122
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000123 # n = 5000
Christian Heimes99170a52007-12-19 02:07:34 +0000124 n = 254 # SyntaxError: more than 255 arguments:
125 import string, random
Georg Brandlb533e262008-05-25 18:19:30 +0000126 names = list(set(''.join([random.choice(string.ascii_letters)
127 for j in range(10)]) for i in range(n)))
128 n = len(names)
Christian Heimes99170a52007-12-19 02:07:34 +0000129 Big = namedtuple('Big', names)
130 b = Big(*range(n))
131 self.assertEqual(b, tuple(range(n)))
Christian Heimesfaf2f632008-01-06 16:59:19 +0000132 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Christian Heimes99170a52007-12-19 02:07:34 +0000133 for pos, name in enumerate(names):
134 self.assertEqual(getattr(b, name), pos)
135 repr(b) # make sure repr() doesn't blow-up
136 d = b._asdict()
137 d_expected = dict(zip(names, range(n)))
138 self.assertEqual(d, d_expected)
139 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
140 b2_expected = list(range(n))
141 b2_expected[1] = 999
142 b2_expected[-5] = 42
143 self.assertEqual(b2, tuple(b2_expected))
144 self.assertEqual(b._fields, tuple(names))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000145
Georg Brandlc28e1fa2008-06-10 19:20:26 +0000146 def test_pickle(self):
147 p = TestNT(x=10, y=20, z=30)
148 for module in (pickle,):
149 loads = getattr(module, 'loads')
150 dumps = getattr(module, 'dumps')
151 for protocol in -1, 0, 1, 2:
152 q = loads(dumps(p, protocol))
153 self.assertEqual(p, q)
154 self.assertEqual(p._fields, q._fields)
155
156 def test_copy(self):
157 p = TestNT(x=10, y=20, z=30)
158 for copier in copy.copy, copy.deepcopy:
159 q = copier(p)
160 self.assertEqual(p, q)
161 self.assertEqual(p._fields, q._fields)
162
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000163class TestOneTrickPonyABCs(unittest.TestCase):
164
165 def test_Hashable(self):
166 # Check some non-hashables
Guido van Rossum254348e2007-11-21 19:29:53 +0000167 non_samples = [bytearray(), list(), set(), dict()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000168 for x in non_samples:
169 self.failIf(isinstance(x, Hashable), repr(x))
170 self.failIf(issubclass(type(x), Hashable), repr(type(x)))
171 # Check some hashables
172 samples = [None,
173 int(), float(), complex(),
Guido van Rossum07d4e782007-07-03 16:59:47 +0000174 str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000175 tuple(), frozenset(),
Guido van Rossum98297ee2007-11-06 21:34:58 +0000176 int, list, object, type, bytes()
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000177 ]
178 for x in samples:
179 self.failUnless(isinstance(x, Hashable), repr(x))
180 self.failUnless(issubclass(type(x), Hashable), repr(type(x)))
181 self.assertRaises(TypeError, Hashable)
182 # Check direct subclassing
183 class H(Hashable):
184 def __hash__(self):
185 return super().__hash__()
186 self.assertEqual(hash(H()), 0)
187 self.failIf(issubclass(int, H))
188
189 def test_Iterable(self):
190 # Check some non-iterables
191 non_samples = [None, 42, 3.14, 1j]
192 for x in non_samples:
193 self.failIf(isinstance(x, Iterable), repr(x))
194 self.failIf(issubclass(type(x), Iterable), repr(type(x)))
195 # Check some iterables
Guido van Rossum07d4e782007-07-03 16:59:47 +0000196 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000197 tuple(), list(), set(), frozenset(), dict(),
198 dict().keys(), dict().items(), dict().values(),
199 (lambda: (yield))(),
200 (x for x in []),
201 ]
202 for x in samples:
203 self.failUnless(isinstance(x, Iterable), repr(x))
204 self.failUnless(issubclass(type(x), Iterable), repr(type(x)))
205 # Check direct subclassing
206 class I(Iterable):
207 def __iter__(self):
208 return super().__iter__()
209 self.assertEqual(list(I()), [])
210 self.failIf(issubclass(str, I))
211
212 def test_Iterator(self):
Guido van Rossum07d4e782007-07-03 16:59:47 +0000213 non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000214 for x in non_samples:
215 self.failIf(isinstance(x, Iterator), repr(x))
216 self.failIf(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000217 samples = [iter(bytes()), iter(str()),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000218 iter(tuple()), iter(list()), iter(dict()),
219 iter(set()), iter(frozenset()),
220 iter(dict().keys()), iter(dict().items()),
221 iter(dict().values()),
222 (lambda: (yield))(),
223 (x for x in []),
224 ]
225 for x in samples:
226 self.failUnless(isinstance(x, Iterator), repr(x))
227 self.failUnless(issubclass(type(x), Iterator), repr(type(x)))
228
229 def test_Sized(self):
230 non_samples = [None, 42, 3.14, 1j,
231 (lambda: (yield))(),
232 (x for x in []),
233 ]
234 for x in non_samples:
235 self.failIf(isinstance(x, Sized), repr(x))
236 self.failIf(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000237 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000238 tuple(), list(), set(), frozenset(), dict(),
239 dict().keys(), dict().items(), dict().values(),
240 ]
241 for x in samples:
242 self.failUnless(isinstance(x, Sized), repr(x))
243 self.failUnless(issubclass(type(x), Sized), repr(type(x)))
244
245 def test_Container(self):
246 non_samples = [None, 42, 3.14, 1j,
247 (lambda: (yield))(),
248 (x for x in []),
249 ]
250 for x in non_samples:
251 self.failIf(isinstance(x, Container), repr(x))
252 self.failIf(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum07d4e782007-07-03 16:59:47 +0000253 samples = [bytes(), str(),
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000254 tuple(), list(), set(), frozenset(), dict(),
255 dict().keys(), dict().items(),
256 ]
257 for x in samples:
258 self.failUnless(isinstance(x, Container), repr(x))
259 self.failUnless(issubclass(type(x), Container), repr(type(x)))
260
261 def test_Callable(self):
262 non_samples = [None, 42, 3.14, 1j,
263 "", b"", (), [], {}, set(),
264 (lambda: (yield))(),
265 (x for x in []),
266 ]
267 for x in non_samples:
268 self.failIf(isinstance(x, Callable), repr(x))
269 self.failIf(issubclass(type(x), Callable), repr(type(x)))
270 samples = [lambda: None,
271 type, int, object,
272 len,
273 list.append, [].append,
274 ]
275 for x in samples:
276 self.failUnless(isinstance(x, Callable), repr(x))
277 self.failUnless(issubclass(type(x), Callable), repr(type(x)))
278
279 def test_direct_subclassing(self):
280 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
281 class C(B):
282 pass
283 self.failUnless(issubclass(C, B))
284 self.failIf(issubclass(int, C))
285
286 def test_registration(self):
287 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
288 class C:
289 __hash__ = None # Make sure it isn't hashable by default
290 self.failIf(issubclass(C, B), B.__name__)
291 B.register(C)
292 self.failUnless(issubclass(C, B))
293
294
295class TestCollectionABCs(unittest.TestCase):
296
297 # XXX For now, we only test some virtual inheritance properties.
298 # We should also test the proper behavior of the collection ABCs
299 # as real base classes or mix-in classes.
300
301 def test_Set(self):
302 for sample in [set, frozenset]:
303 self.failUnless(isinstance(sample(), Set))
304 self.failUnless(issubclass(sample, Set))
305
Benjamin Peterson41181742008-07-02 20:22:54 +0000306 def test_hash_Set(self):
307 class OneTwoThreeSet(Set):
308 def __init__(self):
309 self.contents = [1, 2, 3]
310 def __contains__(self, x):
311 return x in self.contents
312 def __len__(self):
313 return len(self.contents)
314 def __iter__(self):
315 return iter(self.contents)
316 def __hash__(self):
317 return self._hash()
318 a, b = OneTwoThreeSet(), OneTwoThreeSet()
319 self.failUnless(hash(a) == hash(b))
320
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000321 def test_MutableSet(self):
322 self.failUnless(isinstance(set(), MutableSet))
323 self.failUnless(issubclass(set, MutableSet))
324 self.failIf(isinstance(frozenset(), MutableSet))
325 self.failIf(issubclass(frozenset, MutableSet))
326
327 def test_Mapping(self):
328 for sample in [dict]:
329 self.failUnless(isinstance(sample(), Mapping))
330 self.failUnless(issubclass(sample, Mapping))
331
332 def test_MutableMapping(self):
333 for sample in [dict]:
334 self.failUnless(isinstance(sample(), MutableMapping))
335 self.failUnless(issubclass(sample, MutableMapping))
336
337 def test_Sequence(self):
338 for sample in [tuple, list, bytes, str]:
339 self.failUnless(isinstance(sample(), Sequence))
340 self.failUnless(issubclass(sample, Sequence))
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000341 self.failUnless(issubclass(str, Sequence))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000342
Guido van Rossumd05eb002007-11-21 22:26:24 +0000343 def test_ByteString(self):
344 for sample in [bytes, bytearray]:
345 self.failUnless(isinstance(sample(), ByteString))
346 self.failUnless(issubclass(sample, ByteString))
347 for sample in [str, list, tuple]:
348 self.failIf(isinstance(sample(), ByteString))
349 self.failIf(issubclass(sample, ByteString))
350 self.failIf(isinstance(memoryview(b""), ByteString))
351 self.failIf(issubclass(memoryview, ByteString))
352
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000353 def test_MutableSequence(self):
Guido van Rossumd05eb002007-11-21 22:26:24 +0000354 for sample in [tuple, str, bytes]:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000355 self.failIf(isinstance(sample(), MutableSequence))
356 self.failIf(issubclass(sample, MutableSequence))
Guido van Rossumd05eb002007-11-21 22:26:24 +0000357 for sample in [list, bytearray]:
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000358 self.failUnless(isinstance(sample(), MutableSequence))
359 self.failUnless(issubclass(sample, MutableSequence))
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000360 self.failIf(issubclass(str, MutableSequence))
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000361
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000362class TestCounter(unittest.TestCase):
363
364 def test_basics(self):
365 c = Counter('abcaba')
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000366 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
367 self.assertEqual(c, Counter(a=3, b=2, c=1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000368 self.assert_(isinstance(c, dict))
369 self.assert_(isinstance(c, Mapping))
370 self.assert_(issubclass(Counter, dict))
371 self.assert_(issubclass(Counter, Mapping))
372 self.assertEqual(len(c), 3)
373 self.assertEqual(sum(c.values()), 6)
374 self.assertEqual(sorted(c.values()), [1, 2, 3])
375 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
376 self.assertEqual(sorted(c), ['a', 'b', 'c'])
377 self.assertEqual(sorted(c.items()),
378 [('a', 3), ('b', 2), ('c', 1)])
379 self.assertEqual(c['b'], 2)
380 self.assertEqual(c['z'], 0)
381 self.assertEqual(c.__contains__('c'), True)
382 self.assertEqual(c.__contains__('z'), False)
383 self.assertEqual(c.get('b', 10), 2)
384 self.assertEqual(c.get('z', 10), 10)
385 self.assertEqual(c, dict(a=3, b=2, c=1))
386 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
387 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
388 for i in range(5):
389 self.assertEqual(c.most_common(i),
390 [('a', 3), ('b', 2), ('c', 1)][:i])
391 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
392 c['a'] += 1 # increment an existing value
393 c['b'] -= 2 # sub existing value to zero
394 del c['c'] # remove an entry
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000395 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000396 c['d'] -= 2 # sub from a missing value
397 c['e'] = -5 # directly assign a missing value
398 c['f'] += 4 # add to a missing value
399 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
400 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
401 self.assertEqual(c.pop('f'), 4)
402 self.assertEqual('f' in c, False)
403 for i in range(3):
404 elem, cnt = c.popitem()
405 self.assertEqual(elem in c, False)
406 c.clear()
407 self.assertEqual(c, {})
408 self.assertEqual(repr(c), 'Counter()')
409 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
410 self.assertRaises(TypeError, hash, c)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000411 c.update(dict(a=5, b=3))
412 c.update(c=1)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000413 c.update(Counter('a' * 50 + 'b' * 30))
414 c.update() # test case with no args
415 c.__init__('a' * 500 + 'b' * 300)
416 c.__init__('cdc')
417 c.__init__()
418 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
419 self.assertEqual(c.setdefault('d', 5), 1)
420 self.assertEqual(c['d'], 1)
421 self.assertEqual(c.setdefault('e', 5), 5)
422 self.assertEqual(c['e'], 5)
423
424 def test_copying(self):
425 # Check that counters are copyable, deepcopyable, picklable, and
426 #have a repr/eval round-trip
427 words = Counter('which witch had which witches wrist watch'.split())
428 update_test = Counter()
429 update_test.update(words)
430 for i, dup in enumerate([
431 words.copy(),
432 copy.copy(words),
433 copy.deepcopy(words),
434 pickle.loads(pickle.dumps(words, 0)),
435 pickle.loads(pickle.dumps(words, 1)),
436 pickle.loads(pickle.dumps(words, 2)),
437 pickle.loads(pickle.dumps(words, -1)),
438 eval(repr(words)),
439 update_test,
440 Counter(words),
441 ]):
442 msg = (i, dup, words)
443 self.assert_(dup is not words)
444 self.assertEquals(dup, words)
445 self.assertEquals(len(dup), len(words))
446 self.assertEquals(type(dup), type(words))
447
448 def test_conversions(self):
449 # Convert to: set, list, dict
450 s = 'she sells sea shells by the sea shore'
451 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
452 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
453 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
454 self.assertEqual(set(Counter(s)), set(s))
455
Raymond Hettinger670eaec2009-01-21 23:14:07 +0000456 def test_invariant_for_the_in_operator(self):
457 c = Counter(a=10, b=-2, c=0)
458 for elem in c:
459 self.assert_(elem in c)
460
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000461 def test_multiset_operations(self):
462 # Verify that adding a zero counter will strip zeros and negatives
463 c = Counter(a=10, b=-2, c=0) + Counter()
464 self.assertEqual(dict(c), dict(a=10))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000465
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000466 elements = 'abcd'
467 for i in range(1000):
468 # test random pairs of multisets
469 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000470 p.update(e=1, f=-1, g=0)
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000471 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000472 q.update(h=1, i=-1, j=0)
473 for counterop, numberop in [
474 (Counter.__add__, lambda x, y: max(0, x+y)),
475 (Counter.__sub__, lambda x, y: max(0, x-y)),
476 (Counter.__or__, lambda x, y: max(0,x,y)),
477 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000478 ]:
479 result = counterop(p, q)
480 for x in elements:
Raymond Hettingere0d1b9f2009-01-21 20:36:27 +0000481 self.assertEqual(numberop(p[x], q[x]), result[x],
482 (counterop, x, p, q))
Raymond Hettinger4d2073a2009-01-20 03:41:22 +0000483 # verify that results exclude non-positive counts
484 self.assert_(x>0 for x in result.values())
485
486 elements = 'abcdef'
487 for i in range(100):
488 # verify that random multisets with no repeats are exactly like sets
489 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
490 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
491 for counterop, setop in [
492 (Counter.__sub__, set.__sub__),
493 (Counter.__or__, set.__or__),
494 (Counter.__and__, set.__and__),
495 ]:
496 counter_result = counterop(p, q)
497 set_result = setop(set(p.elements()), set(q.elements()))
498 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000499
Christian Heimes25bb7832008-01-11 16:17:00 +0000500import doctest, collections
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000501
Guido van Rossumd8faa362007-04-27 19:54:29 +0000502def test_main(verbose=None):
Benjamin Petersonad9d48d2008-04-02 21:49:44 +0000503 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerb8baf632009-01-14 02:20:07 +0000504 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
505 TestCollectionABCs, TestCounter]
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000506 support.run_unittest(*test_classes)
507 support.run_doctest(collections, verbose)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000508
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000509
Guido van Rossumd8faa362007-04-27 19:54:29 +0000510if __name__ == "__main__":
511 test_main(verbose=True)