blob: ddf83985e0ea265472fa2789bdc1143a9d4f9722 [file] [log] [blame]
Raymond Hettingerd1ef8542008-01-11 00:23:13 +00001import unittest, doctest
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00002from test import test_support
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +00003from collections import namedtuple, Counter, Mapping
Raymond Hettingere98839a2008-06-09 01:28:30 +00004import pickle, cPickle, copy
Raymond Hettingerbad1eb22009-01-20 01:19:26 +00005from random import randrange
6import operator
Guido van Rossum64c06e32007-11-22 00:55:51 +00007from collections import Hashable, Iterable, Iterator
8from collections import Sized, Container, Callable
9from collections import Set, MutableSet
10from collections import Mapping, MutableMapping
11from collections import Sequence, MutableSequence
12
Raymond Hettingere98839a2008-06-09 01:28:30 +000013TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000014
15class TestNamedTuple(unittest.TestCase):
16
17 def test_factory(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +000018 Point = namedtuple('Point', 'x y')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000019 self.assertEqual(Point.__name__, 'Point')
20 self.assertEqual(Point.__doc__, 'Point(x, y)')
21 self.assertEqual(Point.__slots__, ())
22 self.assertEqual(Point.__module__, __name__)
23 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Raymond Hettingere0734e72008-01-04 03:22:53 +000024 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettingerabfd8df2007-10-16 21:28:32 +000025
Raymond Hettinger01a09572007-10-23 20:37:41 +000026 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
27 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
28 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
Raymond Hettingerabfd8df2007-10-16 21:28:32 +000029
Raymond Hettinger01a09572007-10-23 20:37:41 +000030 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
31 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
32 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Raymond Hettinger42da8742007-12-14 02:49:47 +000033 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Raymond Hettinger01a09572007-10-23 20:37:41 +000034 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
Raymond Hettingerabfd8df2007-10-16 21:28:32 +000035
Raymond Hettinger01a09572007-10-23 20:37:41 +000036 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Raymond Hettinger42da8742007-12-14 02:49:47 +000037 namedtuple('_', 'a b c') # Test leading underscores in a typename
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000038
Raymond Hettinger6ee7bc02008-09-25 23:31:52 +000039 nt = namedtuple('nt', u'the quick brown fox') # check unicode input
40 self.assert_("u'" not in repr(nt._fields))
41 nt = namedtuple('nt', (u'the', u'quick')) # check unicode input
42 self.assert_("u'" not in repr(nt._fields))
43
Raymond Hettinger02740f72008-01-05 01:35:43 +000044 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
45 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
46
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000047 def test_instance(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +000048 Point = namedtuple('Point', 'x y')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000049 p = Point(11, 22)
50 self.assertEqual(p, Point(x=11, y=22))
51 self.assertEqual(p, Point(11, y=22))
52 self.assertEqual(p, Point(y=22, x=11))
53 self.assertEqual(p, Point(*(11, 22)))
54 self.assertEqual(p, Point(**dict(x=11, y=22)))
55 self.assertRaises(TypeError, Point, 1) # too few args
56 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
57 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
58 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
59 self.assertEqual(repr(p), 'Point(x=11, y=22)')
60 self.assert_('__dict__' not in dir(p)) # verify instance has no dict
61 self.assert_('__weakref__' not in dir(p))
Raymond Hettinger02740f72008-01-05 01:35:43 +000062 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Raymond Hettinger42da8742007-12-14 02:49:47 +000063 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
64 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
65 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Raymond Hettingerd36a60e2007-09-17 00:55:00 +000066
Raymond Hettinger1b50fd72008-01-05 02:17:24 +000067 try:
68 p._replace(x=1, error=2)
69 except ValueError:
70 pass
71 else:
72 self._fail('Did not detect an incorrect fieldname')
73
Raymond Hettingerd36a60e2007-09-17 00:55:00 +000074 # verify that field string can have commas
Raymond Hettinger01a09572007-10-23 20:37:41 +000075 Point = namedtuple('Point', 'x, y')
Raymond Hettingerd36a60e2007-09-17 00:55:00 +000076 p = Point(x=11, y=22)
77 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000078
Raymond Hettinger2115bbc2007-10-08 09:14:28 +000079 # verify that fieldspec can be a non-string sequence
Raymond Hettinger01a09572007-10-23 20:37:41 +000080 Point = namedtuple('Point', ('x', 'y'))
Raymond Hettinger2115bbc2007-10-08 09:14:28 +000081 p = Point(x=11, y=22)
82 self.assertEqual(repr(p), 'Point(x=11, y=22)')
83
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000084 def test_tupleness(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +000085 Point = namedtuple('Point', 'x y')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000086 p = Point(11, 22)
87
88 self.assert_(isinstance(p, tuple))
89 self.assertEqual(p, (11, 22)) # matches a real tuple
90 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
91 self.assertEqual(list(p), [11, 22]) # coercable to a list
92 self.assertEqual(max(p), 22) # iterable
93 self.assertEqual(max(*p), 22) # star-able
94 x, y = p
95 self.assertEqual(p, (x, y)) # unpacks like a tuple
96 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
97 self.assertRaises(IndexError, p.__getitem__, 3)
98
99 self.assertEqual(p.x, x)
100 self.assertEqual(p.y, y)
101 self.assertRaises(AttributeError, eval, 'p.z', locals())
102
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000103 def test_odd_sizes(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +0000104 Zero = namedtuple('Zero', '')
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000105 self.assertEqual(Zero(), ())
Raymond Hettinger02740f72008-01-05 01:35:43 +0000106 self.assertEqual(Zero._make([]), ())
Raymond Hettinger88880b22007-12-18 00:13:45 +0000107 self.assertEqual(repr(Zero()), 'Zero()')
108 self.assertEqual(Zero()._asdict(), {})
109 self.assertEqual(Zero()._fields, ())
110
Raymond Hettinger01a09572007-10-23 20:37:41 +0000111 Dot = namedtuple('Dot', 'd')
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000112 self.assertEqual(Dot(1), (1,))
Raymond Hettinger02740f72008-01-05 01:35:43 +0000113 self.assertEqual(Dot._make([1]), (1,))
Raymond Hettinger88880b22007-12-18 00:13:45 +0000114 self.assertEqual(Dot(1).d, 1)
115 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
116 self.assertEqual(Dot(1)._asdict(), {'d':1})
117 self.assertEqual(Dot(1)._replace(d=999), (999,))
118 self.assertEqual(Dot(1)._fields, ('d',))
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000119
Raymond Hettingere98839a2008-06-09 01:28:30 +0000120 n = 5000
Raymond Hettinger88880b22007-12-18 00:13:45 +0000121 import string, random
Georg Brandl0bb02992008-05-18 10:39:26 +0000122 names = list(set(''.join([random.choice(string.ascii_letters)
123 for j in range(10)]) for i in range(n)))
124 n = len(names)
Raymond Hettinger88880b22007-12-18 00:13:45 +0000125 Big = namedtuple('Big', names)
126 b = Big(*range(n))
127 self.assertEqual(b, tuple(range(n)))
Raymond Hettinger02740f72008-01-05 01:35:43 +0000128 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Raymond Hettinger88880b22007-12-18 00:13:45 +0000129 for pos, name in enumerate(names):
130 self.assertEqual(getattr(b, name), pos)
131 repr(b) # make sure repr() doesn't blow-up
132 d = b._asdict()
133 d_expected = dict(zip(names, range(n)))
134 self.assertEqual(d, d_expected)
135 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
136 b2_expected = range(n)
137 b2_expected[1] = 999
138 b2_expected[-5] = 42
139 self.assertEqual(b2, tuple(b2_expected))
140 self.assertEqual(b._fields, tuple(names))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000141
Raymond Hettingere98839a2008-06-09 01:28:30 +0000142 def test_pickle(self):
143 p = TestNT(x=10, y=20, z=30)
144 for module in pickle, cPickle:
145 loads = getattr(module, 'loads')
146 dumps = getattr(module, 'dumps')
147 for protocol in -1, 0, 1, 2:
148 q = loads(dumps(p, protocol))
149 self.assertEqual(p, q)
150 self.assertEqual(p._fields, q._fields)
151
152 def test_copy(self):
153 p = TestNT(x=10, y=20, z=30)
154 for copier in copy.copy, copy.deepcopy:
155 q = copier(p)
156 self.assertEqual(p, q)
157 self.assertEqual(p._fields, q._fields)
158
Guido van Rossum64c06e32007-11-22 00:55:51 +0000159class TestOneTrickPonyABCs(unittest.TestCase):
160
161 def test_Hashable(self):
162 # Check some non-hashables
163 non_samples = [list(), set(), dict()]
164 for x in non_samples:
165 self.failIf(isinstance(x, Hashable), repr(x))
166 self.failIf(issubclass(type(x), Hashable), repr(type(x)))
167 # Check some hashables
168 samples = [None,
169 int(), float(), complex(),
170 str(),
171 tuple(), frozenset(),
172 int, list, object, type,
173 ]
174 for x in samples:
175 self.failUnless(isinstance(x, Hashable), repr(x))
176 self.failUnless(issubclass(type(x), Hashable), repr(type(x)))
177 self.assertRaises(TypeError, Hashable)
178 # Check direct subclassing
179 class H(Hashable):
180 def __hash__(self):
181 return super(H, self).__hash__()
Nick Coghlan48361f52008-08-11 15:45:58 +0000182 __eq__ = Hashable.__eq__ # Silence Py3k warning
Guido van Rossum64c06e32007-11-22 00:55:51 +0000183 self.assertEqual(hash(H()), 0)
184 self.failIf(issubclass(int, H))
185
186 def test_Iterable(self):
187 # Check some non-iterables
188 non_samples = [None, 42, 3.14, 1j]
189 for x in non_samples:
190 self.failIf(isinstance(x, Iterable), repr(x))
191 self.failIf(issubclass(type(x), Iterable), repr(type(x)))
192 # Check some iterables
193 samples = [str(),
194 tuple(), list(), set(), frozenset(), dict(),
195 dict().keys(), dict().items(), dict().values(),
196 (lambda: (yield))(),
197 (x for x in []),
198 ]
199 for x in samples:
200 self.failUnless(isinstance(x, Iterable), repr(x))
201 self.failUnless(issubclass(type(x), Iterable), repr(type(x)))
202 # Check direct subclassing
203 class I(Iterable):
204 def __iter__(self):
205 return super(I, self).__iter__()
206 self.assertEqual(list(I()), [])
207 self.failIf(issubclass(str, I))
208
209 def test_Iterator(self):
210 non_samples = [None, 42, 3.14, 1j, "".encode('ascii'), "", (), [],
211 {}, set()]
212 for x in non_samples:
213 self.failIf(isinstance(x, Iterator), repr(x))
214 self.failIf(issubclass(type(x), Iterator), repr(type(x)))
215 samples = [iter(str()),
216 iter(tuple()), iter(list()), iter(dict()),
217 iter(set()), iter(frozenset()),
218 iter(dict().keys()), iter(dict().items()),
219 iter(dict().values()),
220 (lambda: (yield))(),
221 (x for x in []),
222 ]
223 for x in samples:
224 self.failUnless(isinstance(x, Iterator), repr(x))
225 self.failUnless(issubclass(type(x), Iterator), repr(type(x)))
226
227 def test_Sized(self):
228 non_samples = [None, 42, 3.14, 1j,
229 (lambda: (yield))(),
230 (x for x in []),
231 ]
232 for x in non_samples:
233 self.failIf(isinstance(x, Sized), repr(x))
234 self.failIf(issubclass(type(x), Sized), repr(type(x)))
235 samples = [str(),
236 tuple(), list(), set(), frozenset(), dict(),
237 dict().keys(), dict().items(), dict().values(),
238 ]
239 for x in samples:
240 self.failUnless(isinstance(x, Sized), repr(x))
241 self.failUnless(issubclass(type(x), Sized), repr(type(x)))
242
243 def test_Container(self):
244 non_samples = [None, 42, 3.14, 1j,
245 (lambda: (yield))(),
246 (x for x in []),
247 ]
248 for x in non_samples:
249 self.failIf(isinstance(x, Container), repr(x))
250 self.failIf(issubclass(type(x), Container), repr(type(x)))
251 samples = [str(),
252 tuple(), list(), set(), frozenset(), dict(),
253 dict().keys(), dict().items(),
254 ]
255 for x in samples:
256 self.failUnless(isinstance(x, Container), repr(x))
257 self.failUnless(issubclass(type(x), Container), repr(type(x)))
258
259 def test_Callable(self):
260 non_samples = [None, 42, 3.14, 1j,
261 "", "".encode('ascii'), (), [], {}, set(),
262 (lambda: (yield))(),
263 (x for x in []),
264 ]
265 for x in non_samples:
266 self.failIf(isinstance(x, Callable), repr(x))
267 self.failIf(issubclass(type(x), Callable), repr(type(x)))
268 samples = [lambda: None,
269 type, int, object,
270 len,
271 list.append, [].append,
272 ]
273 for x in samples:
274 self.failUnless(isinstance(x, Callable), repr(x))
275 self.failUnless(issubclass(type(x), Callable), repr(type(x)))
276
277 def test_direct_subclassing(self):
278 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
279 class C(B):
280 pass
281 self.failUnless(issubclass(C, B))
282 self.failIf(issubclass(int, C))
283
284 def test_registration(self):
285 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
286 class C:
287 __metaclass__ = type
288 __hash__ = None # Make sure it isn't hashable by default
289 self.failIf(issubclass(C, B), B.__name__)
290 B.register(C)
291 self.failUnless(issubclass(C, B))
292
293
294class TestCollectionABCs(unittest.TestCase):
295
296 # XXX For now, we only test some virtual inheritance properties.
297 # We should also test the proper behavior of the collection ABCs
298 # as real base classes or mix-in classes.
299
300 def test_Set(self):
301 for sample in [set, frozenset]:
302 self.failUnless(isinstance(sample(), Set))
303 self.failUnless(issubclass(sample, Set))
304
Raymond Hettinger4c52f522008-06-23 03:29:28 +0000305 def test_hash_Set(self):
306 class OneTwoThreeSet(Set):
307 def __init__(self):
308 self.contents = [1, 2, 3]
309 def __contains__(self, x):
310 return x in self.contents
311 def __len__(self):
312 return len(self.contents)
313 def __iter__(self):
314 return iter(self.contents)
315 def __hash__(self):
316 return self._hash()
317 a, b = OneTwoThreeSet(), OneTwoThreeSet()
318 self.failUnless(hash(a) == hash(b))
319
Guido van Rossum64c06e32007-11-22 00:55:51 +0000320 def test_MutableSet(self):
321 self.failUnless(isinstance(set(), MutableSet))
322 self.failUnless(issubclass(set, MutableSet))
323 self.failIf(isinstance(frozenset(), MutableSet))
324 self.failIf(issubclass(frozenset, MutableSet))
325
326 def test_Mapping(self):
327 for sample in [dict]:
328 self.failUnless(isinstance(sample(), Mapping))
329 self.failUnless(issubclass(sample, Mapping))
330
331 def test_MutableMapping(self):
332 for sample in [dict]:
333 self.failUnless(isinstance(sample(), MutableMapping))
334 self.failUnless(issubclass(sample, MutableMapping))
335
336 def test_Sequence(self):
337 for sample in [tuple, list, str]:
338 self.failUnless(isinstance(sample(), Sequence))
339 self.failUnless(issubclass(sample, Sequence))
340 self.failUnless(issubclass(basestring, Sequence))
341
342 def test_MutableSequence(self):
343 for sample in [tuple, str]:
344 self.failIf(isinstance(sample(), MutableSequence))
345 self.failIf(issubclass(sample, MutableSequence))
346 for sample in [list]:
347 self.failUnless(isinstance(sample(), MutableSequence))
348 self.failUnless(issubclass(sample, MutableSequence))
349 self.failIf(issubclass(basestring, MutableSequence))
350
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000351class TestCounter(unittest.TestCase):
352
353 def test_basics(self):
354 c = Counter('abcaba')
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000355 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
356 self.assertEqual(c, Counter(a=3, b=2, c=1))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000357 self.assert_(isinstance(c, dict))
358 self.assert_(isinstance(c, Mapping))
359 self.assert_(issubclass(Counter, dict))
360 self.assert_(issubclass(Counter, Mapping))
361 self.assertEqual(len(c), 3)
362 self.assertEqual(sum(c.values()), 6)
363 self.assertEqual(sorted(c.values()), [1, 2, 3])
364 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
365 self.assertEqual(sorted(c), ['a', 'b', 'c'])
366 self.assertEqual(sorted(c.items()),
367 [('a', 3), ('b', 2), ('c', 1)])
368 self.assertEqual(c['b'], 2)
369 self.assertEqual(c['z'], 0)
370 self.assertEqual(c.has_key('c'), True)
371 self.assertEqual(c.has_key('z'), False)
372 self.assertEqual(c.__contains__('c'), True)
373 self.assertEqual(c.__contains__('z'), False)
374 self.assertEqual(c.get('b', 10), 2)
375 self.assertEqual(c.get('z', 10), 10)
376 self.assertEqual(c, dict(a=3, b=2, c=1))
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000377 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000378 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
379 for i in range(5):
380 self.assertEqual(c.most_common(i),
381 [('a', 3), ('b', 2), ('c', 1)][:i])
382 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
383 c['a'] += 1 # increment an existing value
384 c['b'] -= 2 # sub existing value to zero
385 del c['c'] # remove an entry
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000386 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000387 c['d'] -= 2 # sub from a missing value
388 c['e'] = -5 # directly assign a missing value
389 c['f'] += 4 # add to a missing value
390 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
391 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
392 self.assertEqual(c.pop('f'), 4)
393 self.assertEqual('f' in c, False)
394 for i in range(3):
395 elem, cnt = c.popitem()
396 self.assertEqual(elem in c, False)
397 c.clear()
398 self.assertEqual(c, {})
399 self.assertEqual(repr(c), 'Counter()')
400 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
401 self.assertRaises(TypeError, hash, c)
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000402 c.update(dict(a=5, b=3))
403 c.update(c=1)
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000404 c.update(Counter('a' * 50 + 'b' * 30))
Raymond Hettingerafd112b2009-01-14 01:15:06 +0000405 c.update() # test case with no args
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000406 c.__init__('a' * 500 + 'b' * 300)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000407 c.__init__('cdc')
Raymond Hettingerafd112b2009-01-14 01:15:06 +0000408 c.__init__()
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000409 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
410 self.assertEqual(c.setdefault('d', 5), 1)
411 self.assertEqual(c['d'], 1)
412 self.assertEqual(c.setdefault('e', 5), 5)
413 self.assertEqual(c['e'], 5)
414
415 def test_copying(self):
416 # Check that counters are copyable, deepcopyable, picklable, and
417 #have a repr/eval round-trip
418 words = Counter('which witch had which witches wrist watch'.split())
419 update_test = Counter()
420 update_test.update(words)
421 for i, dup in enumerate([
422 words.copy(),
423 copy.copy(words),
424 copy.deepcopy(words),
425 pickle.loads(pickle.dumps(words, 0)),
426 pickle.loads(pickle.dumps(words, 1)),
427 pickle.loads(pickle.dumps(words, 2)),
428 pickle.loads(pickle.dumps(words, -1)),
429 cPickle.loads(cPickle.dumps(words, 0)),
430 cPickle.loads(cPickle.dumps(words, 1)),
431 cPickle.loads(cPickle.dumps(words, 2)),
432 cPickle.loads(cPickle.dumps(words, -1)),
433 eval(repr(words)),
434 update_test,
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000435 Counter(words),
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000436 ]):
437 msg = (i, dup, words)
438 self.assert_(dup is not words)
439 self.assertEquals(dup, words)
440 self.assertEquals(len(dup), len(words))
441 self.assertEquals(type(dup), type(words))
442
443 def test_conversions(self):
444 # Convert to: set, list, dict
445 s = 'she sells sea shells by the sea shore'
446 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
447 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
448 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
449 self.assertEqual(set(Counter(s)), set(s))
450
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000451 def test_multiset_operations(self):
452 # Verify that adding a zero counter will strip zeros and negatives
453 c = Counter(a=10, b=-2, c=0) + Counter()
454 self.assertEqual(dict(c), dict(a=10))
455
456 elements = 'abcd'
457 for i in range(1000):
458 # test random pairs of multisets
459 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
460 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
461 for counterop, numberop, defneg in [
462 (Counter.__add__, lambda x, y: x+y if x+y>0 else 0, True),
463 (Counter.__sub__, lambda x, y: x-y if x-y>0 else 0, False),
464 (Counter.__or__, max, False),
465 (Counter.__and__, min, False),
466 ]:
467 result = counterop(p, q)
468 for x in elements:
469 # all except __add__ are undefined for negative inputs
470 if defneg or (p[x] >= 0 and q[x] >= 0):
471 self.assertEqual(numberop(p[x], q[x]), result[x])
472 # verify that results exclude non-positive counts
473 self.assert_(x>0 for x in result.values())
474
475 elements = 'abcdef'
476 for i in range(100):
477 # verify that random multisets with no repeats are exactly like sets
478 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
479 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
480 for counterop, setop in [
481 (Counter.__sub__, set.__sub__),
482 (Counter.__or__, set.__or__),
483 (Counter.__and__, set.__and__),
484 ]:
485 counter_result = counterop(p, q)
486 set_result = setop(set(p.elements()), set(q.elements()))
487 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000488
Raymond Hettingerd1ef8542008-01-11 00:23:13 +0000489import doctest, collections
Guido van Rossum64c06e32007-11-22 00:55:51 +0000490
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000491def test_main(verbose=None):
Amaury Forgeot d'Arccb0f2ad2008-04-02 00:55:04 +0000492 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000493 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
494 TestCollectionABCs, TestCounter]
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000495 test_support.run_unittest(*test_classes)
Amaury Forgeot d'Arccb0f2ad2008-04-02 00:55:04 +0000496 test_support.run_doctest(collections, verbose)
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000497
498if __name__ == "__main__":
499 test_main(verbose=True)