blob: 784a31880e3bf1709609abb91b6573d35256850c [file] [log] [blame]
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001
Benjamin Petersoneb318d32010-05-21 20:51:45 +00002import unittest, doctest, operator
Raymond Hettingerbc512d32009-03-03 04:45:34 +00003import inspect
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00004from test import test_support
Raymond Hettingerbc512d32009-03-03 04:45:34 +00005from collections import namedtuple, Counter, OrderedDict
6from test import mapping_tests
Raymond Hettingere98839a2008-06-09 01:28:30 +00007import pickle, cPickle, copy
Raymond Hettingerbc512d32009-03-03 04:45:34 +00008from random import randrange, shuffle
Raymond Hettingera68cad12009-05-27 02:24:45 +00009import keyword
10import re
R. David Murrayf28fd242010-02-23 00:24:49 +000011import sys
Guido van Rossum64c06e32007-11-22 00:55:51 +000012from collections import Hashable, Iterable, Iterator
13from collections import Sized, Container, Callable
14from collections import Set, MutableSet
15from collections import Mapping, MutableMapping
16from collections import Sequence, MutableSequence
17
Raymond Hettingere98839a2008-06-09 01:28:30 +000018TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000019
Raymond Hettinger7393c692013-05-27 10:58:55 -070020py273_named_tuple_pickle = '''\
21ccopy_reg
22_reconstructor
23p0
24(ctest.test_collections
25TestNT
26p1
27c__builtin__
28tuple
29p2
30(I10
31I20
32I30
33tp3
34tp4
35Rp5
36ccollections
37OrderedDict
38p6
39((lp7
40(lp8
41S'x'
42p9
43aI10
44aa(lp10
45S'y'
46p11
47aI20
48aa(lp12
49S'z'
50p13
51aI30
52aatp14
53Rp15
54b.
55'''
56
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000057class TestNamedTuple(unittest.TestCase):
58
59 def test_factory(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +000060 Point = namedtuple('Point', 'x y')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000061 self.assertEqual(Point.__name__, 'Point')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000062 self.assertEqual(Point.__slots__, ())
63 self.assertEqual(Point.__module__, __name__)
64 self.assertEqual(Point.__getitem__, tuple.__getitem__)
Raymond Hettingere0734e72008-01-04 03:22:53 +000065 self.assertEqual(Point._fields, ('x', 'y'))
Raymond Hettingerabfd8df2007-10-16 21:28:32 +000066
Raymond Hettinger01a09572007-10-23 20:37:41 +000067 self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi') # type has non-alpha char
68 self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi') # type has keyword
69 self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi') # type starts with digit
Raymond Hettingerabfd8df2007-10-16 21:28:32 +000070
Raymond Hettinger01a09572007-10-23 20:37:41 +000071 self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi') # field with non-alpha char
72 self.assertRaises(ValueError, namedtuple, 'abc', 'abc class') # field has keyword
73 self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi') # field starts with digit
Raymond Hettinger42da8742007-12-14 02:49:47 +000074 self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi') # field with leading underscore
Raymond Hettinger01a09572007-10-23 20:37:41 +000075 self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi') # duplicate field
Raymond Hettingerabfd8df2007-10-16 21:28:32 +000076
Raymond Hettinger01a09572007-10-23 20:37:41 +000077 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
Raymond Hettinger42da8742007-12-14 02:49:47 +000078 namedtuple('_', 'a b c') # Test leading underscores in a typename
Raymond Hettingerc37e5e02007-03-01 06:16:43 +000079
Raymond Hettinger6ee7bc02008-09-25 23:31:52 +000080 nt = namedtuple('nt', u'the quick brown fox') # check unicode input
Ezio Melottiaa980582010-01-23 23:04:36 +000081 self.assertNotIn("u'", repr(nt._fields))
Raymond Hettinger6ee7bc02008-09-25 23:31:52 +000082 nt = namedtuple('nt', (u'the', u'quick')) # check unicode input
Ezio Melottiaa980582010-01-23 23:04:36 +000083 self.assertNotIn("u'", repr(nt._fields))
Raymond Hettinger6ee7bc02008-09-25 23:31:52 +000084
Raymond Hettinger02740f72008-01-05 01:35:43 +000085 self.assertRaises(TypeError, Point._make, [11]) # catch too few args
86 self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
87
R. David Murrayf28fd242010-02-23 00:24:49 +000088 @unittest.skipIf(sys.flags.optimize >= 2,
89 "Docstrings are omitted with -O2 and above")
90 def test_factory_doc_attr(self):
91 Point = namedtuple('Point', 'x y')
92 self.assertEqual(Point.__doc__, 'Point(x, y)')
93
Raymond Hettinger322daea2009-02-10 01:24:05 +000094 def test_name_fixer(self):
95 for spec, renamed in [
Raymond Hettinger756ab672009-04-02 22:25:40 +000096 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
97 [('abc', 'class'), ('abc', '_1')], # field has keyword
98 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
99 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
100 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
101 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
Raymond Hettinger322daea2009-02-10 01:24:05 +0000102 ]:
103 self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
104
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000105 def test_instance(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +0000106 Point = namedtuple('Point', 'x y')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000107 p = Point(11, 22)
108 self.assertEqual(p, Point(x=11, y=22))
109 self.assertEqual(p, Point(11, y=22))
110 self.assertEqual(p, Point(y=22, x=11))
111 self.assertEqual(p, Point(*(11, 22)))
112 self.assertEqual(p, Point(**dict(x=11, y=22)))
113 self.assertRaises(TypeError, Point, 1) # too few args
114 self.assertRaises(TypeError, Point, 1, 2, 3) # too many args
115 self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
116 self.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
117 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Ezio Melottiaa980582010-01-23 23:04:36 +0000118 self.assertNotIn('__weakref__', dir(p))
Raymond Hettinger02740f72008-01-05 01:35:43 +0000119 self.assertEqual(p, Point._make([11, 22])) # test _make classmethod
Raymond Hettinger42da8742007-12-14 02:49:47 +0000120 self.assertEqual(p._fields, ('x', 'y')) # test _fields attribute
121 self.assertEqual(p._replace(x=1), (1, 22)) # test _replace method
122 self.assertEqual(p._asdict(), dict(x=11, y=22)) # test _asdict method
Raymond Hettinger7393c692013-05-27 10:58:55 -0700123 self.assertEqual(vars(p), p._asdict()) # verify that vars() works
Raymond Hettingerd36a60e2007-09-17 00:55:00 +0000124
Raymond Hettinger1b50fd72008-01-05 02:17:24 +0000125 try:
126 p._replace(x=1, error=2)
127 except ValueError:
128 pass
129 else:
130 self._fail('Did not detect an incorrect fieldname')
131
Raymond Hettingerd36a60e2007-09-17 00:55:00 +0000132 # verify that field string can have commas
Raymond Hettinger01a09572007-10-23 20:37:41 +0000133 Point = namedtuple('Point', 'x, y')
Raymond Hettingerd36a60e2007-09-17 00:55:00 +0000134 p = Point(x=11, y=22)
135 self.assertEqual(repr(p), 'Point(x=11, y=22)')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000136
Raymond Hettinger2115bbc2007-10-08 09:14:28 +0000137 # verify that fieldspec can be a non-string sequence
Raymond Hettinger01a09572007-10-23 20:37:41 +0000138 Point = namedtuple('Point', ('x', 'y'))
Raymond Hettinger2115bbc2007-10-08 09:14:28 +0000139 p = Point(x=11, y=22)
140 self.assertEqual(repr(p), 'Point(x=11, y=22)')
141
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000142 def test_tupleness(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +0000143 Point = namedtuple('Point', 'x y')
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000144 p = Point(11, 22)
145
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000146 self.assertIsInstance(p, tuple)
Raymond Hettingerc37e5e02007-03-01 06:16:43 +0000147 self.assertEqual(p, (11, 22)) # matches a real tuple
148 self.assertEqual(tuple(p), (11, 22)) # coercable to a real tuple
149 self.assertEqual(list(p), [11, 22]) # coercable to a list
150 self.assertEqual(max(p), 22) # iterable
151 self.assertEqual(max(*p), 22) # star-able
152 x, y = p
153 self.assertEqual(p, (x, y)) # unpacks like a tuple
154 self.assertEqual((p[0], p[1]), (11, 22)) # indexable like a tuple
155 self.assertRaises(IndexError, p.__getitem__, 3)
156
157 self.assertEqual(p.x, x)
158 self.assertEqual(p.y, y)
159 self.assertRaises(AttributeError, eval, 'p.z', locals())
160
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000161 def test_odd_sizes(self):
Raymond Hettinger01a09572007-10-23 20:37:41 +0000162 Zero = namedtuple('Zero', '')
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000163 self.assertEqual(Zero(), ())
Raymond Hettinger02740f72008-01-05 01:35:43 +0000164 self.assertEqual(Zero._make([]), ())
Raymond Hettinger88880b22007-12-18 00:13:45 +0000165 self.assertEqual(repr(Zero()), 'Zero()')
166 self.assertEqual(Zero()._asdict(), {})
167 self.assertEqual(Zero()._fields, ())
168
Raymond Hettinger01a09572007-10-23 20:37:41 +0000169 Dot = namedtuple('Dot', 'd')
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000170 self.assertEqual(Dot(1), (1,))
Raymond Hettinger02740f72008-01-05 01:35:43 +0000171 self.assertEqual(Dot._make([1]), (1,))
Raymond Hettinger88880b22007-12-18 00:13:45 +0000172 self.assertEqual(Dot(1).d, 1)
173 self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
174 self.assertEqual(Dot(1)._asdict(), {'d':1})
175 self.assertEqual(Dot(1)._replace(d=999), (999,))
176 self.assertEqual(Dot(1)._fields, ('d',))
Raymond Hettinger2b03d452007-09-18 03:33:19 +0000177
Raymond Hettingere98839a2008-06-09 01:28:30 +0000178 n = 5000
Raymond Hettinger88880b22007-12-18 00:13:45 +0000179 import string, random
Georg Brandl0bb02992008-05-18 10:39:26 +0000180 names = list(set(''.join([random.choice(string.ascii_letters)
181 for j in range(10)]) for i in range(n)))
182 n = len(names)
Raymond Hettinger88880b22007-12-18 00:13:45 +0000183 Big = namedtuple('Big', names)
184 b = Big(*range(n))
185 self.assertEqual(b, tuple(range(n)))
Raymond Hettinger02740f72008-01-05 01:35:43 +0000186 self.assertEqual(Big._make(range(n)), tuple(range(n)))
Raymond Hettinger88880b22007-12-18 00:13:45 +0000187 for pos, name in enumerate(names):
188 self.assertEqual(getattr(b, name), pos)
189 repr(b) # make sure repr() doesn't blow-up
190 d = b._asdict()
191 d_expected = dict(zip(names, range(n)))
192 self.assertEqual(d, d_expected)
193 b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
194 b2_expected = range(n)
195 b2_expected[1] = 999
196 b2_expected[-5] = 42
197 self.assertEqual(b2, tuple(b2_expected))
198 self.assertEqual(b._fields, tuple(names))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000199
Raymond Hettingere98839a2008-06-09 01:28:30 +0000200 def test_pickle(self):
201 p = TestNT(x=10, y=20, z=30)
202 for module in pickle, cPickle:
203 loads = getattr(module, 'loads')
204 dumps = getattr(module, 'dumps')
205 for protocol in -1, 0, 1, 2:
206 q = loads(dumps(p, protocol))
207 self.assertEqual(p, q)
208 self.assertEqual(p._fields, q._fields)
209
210 def test_copy(self):
211 p = TestNT(x=10, y=20, z=30)
212 for copier in copy.copy, copy.deepcopy:
213 q = copier(p)
214 self.assertEqual(p, q)
215 self.assertEqual(p._fields, q._fields)
216
Raymond Hettingera68cad12009-05-27 02:24:45 +0000217 def test_name_conflicts(self):
218 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
219 # failed when used as field names. Test to make sure these now work.
220 T = namedtuple('T', 'itemgetter property self cls tuple')
221 t = T(1, 2, 3, 4, 5)
222 self.assertEqual(t, (1,2,3,4,5))
223 newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
224 self.assertEqual(newt, (10,20,30,40,50))
225
226 # Broader test of all interesting names in a template
227 with test_support.captured_stdout() as template:
228 T = namedtuple('T', 'x', verbose=True)
229 words = set(re.findall('[A-Za-z]+', template.getvalue()))
230 words -= set(keyword.kwlist)
231 T = namedtuple('T', words)
232 # test __new__
233 values = tuple(range(len(words)))
234 t = T(*values)
235 self.assertEqual(t, values)
236 t = T(**dict(zip(T._fields, values)))
237 self.assertEqual(t, values)
238 # test _make
239 t = T._make(values)
240 self.assertEqual(t, values)
241 # exercise __repr__
242 repr(t)
243 # test _asdict
244 self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
245 # test _replace
246 t = T._make(values)
247 newvalues = tuple(v*10 for v in values)
248 newt = t._replace(**dict(zip(T._fields, newvalues)))
249 self.assertEqual(newt, newvalues)
250 # test _fields
251 self.assertEqual(T._fields, tuple(words))
252 # test __getnewargs__
253 self.assertEqual(t.__getnewargs__(), values)
254
Raymond Hettinger7393c692013-05-27 10:58:55 -0700255 def test_pickling_bug_18015(self):
256 # http://bugs.python.org/issue18015
257 pt = pickle.loads(py273_named_tuple_pickle)
258 self.assertEqual(pt.x, 10)
259
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000260class ABCTestCase(unittest.TestCase):
261
262 def validate_abstract_methods(self, abc, *names):
263 methodstubs = dict.fromkeys(names, lambda s, *args: 0)
264
265 # everything should work will all required methods are present
266 C = type('C', (abc,), methodstubs)
267 C()
268
269 # instantiation should fail if a required method is missing
270 for name in names:
271 stubs = methodstubs.copy()
272 del stubs[name]
273 C = type('C', (abc,), stubs)
274 self.assertRaises(TypeError, C, name)
275
Florent Xicluna47627d52010-03-08 15:20:28 +0000276 def validate_isinstance(self, abc, name):
277 stub = lambda s, *args: 0
278
279 # new-style class
280 C = type('C', (object,), {name: stub})
281 self.assertIsInstance(C(), abc)
282 self.assertTrue(issubclass(C, abc))
283 # old-style class
284 class C: pass
285 setattr(C, name, stub)
286 self.assertIsInstance(C(), abc)
287 self.assertTrue(issubclass(C, abc))
288
289 # new-style class
290 C = type('C', (object,), {'__hash__': None})
291 self.assertNotIsInstance(C(), abc)
292 self.assertFalse(issubclass(C, abc))
293 # old-style class
294 class C: pass
295 self.assertNotIsInstance(C(), abc)
296 self.assertFalse(issubclass(C, abc))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000297
Benjamin Petersoneb318d32010-05-21 20:51:45 +0000298 def validate_comparison(self, instance):
299 ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
300 operators = {}
301 for op in ops:
302 name = '__' + op + '__'
303 operators[name] = getattr(operator, name)
304
305 class Other:
306 def __init__(self):
307 self.right_side = False
308 def __eq__(self, other):
309 self.right_side = True
310 return True
311 __lt__ = __eq__
312 __gt__ = __eq__
313 __le__ = __eq__
314 __ge__ = __eq__
315 __ne__ = __eq__
316 __ror__ = __eq__
317 __rand__ = __eq__
318 __rxor__ = __eq__
319 __rsub__ = __eq__
320
321 for name, op in operators.items():
322 if not hasattr(instance, name):
323 continue
324 other = Other()
325 op(instance, other)
326 self.assertTrue(other.right_side,'Right side not called for %s.%s'
327 % (type(instance), name))
328
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000329class TestOneTrickPonyABCs(ABCTestCase):
Guido van Rossum64c06e32007-11-22 00:55:51 +0000330
331 def test_Hashable(self):
332 # Check some non-hashables
333 non_samples = [list(), set(), dict()]
334 for x in non_samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000335 self.assertNotIsInstance(x, Hashable)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000336 self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000337 # Check some hashables
338 samples = [None,
339 int(), float(), complex(),
340 str(),
341 tuple(), frozenset(),
342 int, list, object, type,
343 ]
344 for x in samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000345 self.assertIsInstance(x, Hashable)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000346 self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000347 self.assertRaises(TypeError, Hashable)
348 # Check direct subclassing
349 class H(Hashable):
350 def __hash__(self):
351 return super(H, self).__hash__()
Nick Coghlan48361f52008-08-11 15:45:58 +0000352 __eq__ = Hashable.__eq__ # Silence Py3k warning
Guido van Rossum64c06e32007-11-22 00:55:51 +0000353 self.assertEqual(hash(H()), 0)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000354 self.assertFalse(issubclass(int, H))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000355 self.validate_abstract_methods(Hashable, '__hash__')
Florent Xicluna47627d52010-03-08 15:20:28 +0000356 self.validate_isinstance(Hashable, '__hash__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000357
358 def test_Iterable(self):
359 # Check some non-iterables
360 non_samples = [None, 42, 3.14, 1j]
361 for x in non_samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000362 self.assertNotIsInstance(x, Iterable)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000363 self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000364 # Check some iterables
365 samples = [str(),
366 tuple(), list(), set(), frozenset(), dict(),
367 dict().keys(), dict().items(), dict().values(),
368 (lambda: (yield))(),
369 (x for x in []),
370 ]
371 for x in samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000372 self.assertIsInstance(x, Iterable)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000373 self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000374 # Check direct subclassing
375 class I(Iterable):
376 def __iter__(self):
377 return super(I, self).__iter__()
378 self.assertEqual(list(I()), [])
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000379 self.assertFalse(issubclass(str, I))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000380 self.validate_abstract_methods(Iterable, '__iter__')
Florent Xicluna47627d52010-03-08 15:20:28 +0000381 self.validate_isinstance(Iterable, '__iter__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000382
383 def test_Iterator(self):
384 non_samples = [None, 42, 3.14, 1j, "".encode('ascii'), "", (), [],
385 {}, set()]
386 for x in non_samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000387 self.assertNotIsInstance(x, Iterator)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000388 self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000389 samples = [iter(str()),
390 iter(tuple()), iter(list()), iter(dict()),
391 iter(set()), iter(frozenset()),
392 iter(dict().keys()), iter(dict().items()),
393 iter(dict().values()),
394 (lambda: (yield))(),
395 (x for x in []),
396 ]
397 for x in samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000398 self.assertIsInstance(x, Iterator)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000399 self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
Alexander Belopolsky1fea5c42010-11-30 01:18:17 +0000400 self.validate_abstract_methods(Iterator, 'next', '__iter__')
401
402 # Issue 10565
403 class NextOnly:
404 def __next__(self):
405 yield 1
406 raise StopIteration
407 self.assertNotIsInstance(NextOnly(), Iterator)
408 class NextOnlyNew(object):
409 def __next__(self):
410 yield 1
411 raise StopIteration
412 self.assertNotIsInstance(NextOnlyNew(), Iterator)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000413
414 def test_Sized(self):
415 non_samples = [None, 42, 3.14, 1j,
416 (lambda: (yield))(),
417 (x for x in []),
418 ]
419 for x in non_samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000420 self.assertNotIsInstance(x, Sized)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000421 self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000422 samples = [str(),
423 tuple(), list(), set(), frozenset(), dict(),
424 dict().keys(), dict().items(), dict().values(),
425 ]
426 for x in samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000427 self.assertIsInstance(x, Sized)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000428 self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000429 self.validate_abstract_methods(Sized, '__len__')
Florent Xicluna47627d52010-03-08 15:20:28 +0000430 self.validate_isinstance(Sized, '__len__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000431
432 def test_Container(self):
433 non_samples = [None, 42, 3.14, 1j,
434 (lambda: (yield))(),
435 (x for x in []),
436 ]
437 for x in non_samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000438 self.assertNotIsInstance(x, Container)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000439 self.assertFalse(issubclass(type(x), Container), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000440 samples = [str(),
441 tuple(), list(), set(), frozenset(), dict(),
442 dict().keys(), dict().items(),
443 ]
444 for x in samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000445 self.assertIsInstance(x, Container)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000446 self.assertTrue(issubclass(type(x), Container), repr(type(x)))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000447 self.validate_abstract_methods(Container, '__contains__')
Florent Xicluna47627d52010-03-08 15:20:28 +0000448 self.validate_isinstance(Container, '__contains__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000449
450 def test_Callable(self):
451 non_samples = [None, 42, 3.14, 1j,
452 "", "".encode('ascii'), (), [], {}, set(),
453 (lambda: (yield))(),
454 (x for x in []),
455 ]
456 for x in non_samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000457 self.assertNotIsInstance(x, Callable)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000458 self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000459 samples = [lambda: None,
460 type, int, object,
461 len,
462 list.append, [].append,
463 ]
464 for x in samples:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000465 self.assertIsInstance(x, Callable)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000466 self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000467 self.validate_abstract_methods(Callable, '__call__')
Florent Xicluna47627d52010-03-08 15:20:28 +0000468 self.validate_isinstance(Callable, '__call__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000469
470 def test_direct_subclassing(self):
471 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
472 class C(B):
473 pass
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000474 self.assertTrue(issubclass(C, B))
475 self.assertFalse(issubclass(int, C))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000476
477 def test_registration(self):
478 for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
479 class C:
480 __metaclass__ = type
481 __hash__ = None # Make sure it isn't hashable by default
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000482 self.assertFalse(issubclass(C, B), B.__name__)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000483 B.register(C)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000484 self.assertTrue(issubclass(C, B))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000485
Raymond Hettinger66c4a6b2009-04-01 18:50:56 +0000486class WithSet(MutableSet):
487
488 def __init__(self, it=()):
489 self.data = set(it)
490
491 def __len__(self):
492 return len(self.data)
493
494 def __iter__(self):
495 return iter(self.data)
496
497 def __contains__(self, item):
498 return item in self.data
499
500 def add(self, item):
501 self.data.add(item)
502
503 def discard(self, item):
504 self.data.discard(item)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000505
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000506class TestCollectionABCs(ABCTestCase):
Guido van Rossum64c06e32007-11-22 00:55:51 +0000507
508 # XXX For now, we only test some virtual inheritance properties.
509 # We should also test the proper behavior of the collection ABCs
510 # as real base classes or mix-in classes.
511
512 def test_Set(self):
513 for sample in [set, frozenset]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000514 self.assertIsInstance(sample(), Set)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000515 self.assertTrue(issubclass(sample, Set))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000516 self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
Benjamin Petersoneb318d32010-05-21 20:51:45 +0000517 class MySet(Set):
518 def __contains__(self, x):
519 return False
520 def __len__(self):
521 return 0
522 def __iter__(self):
523 return iter([])
524 self.validate_comparison(MySet())
Guido van Rossum64c06e32007-11-22 00:55:51 +0000525
Raymond Hettinger4c52f522008-06-23 03:29:28 +0000526 def test_hash_Set(self):
527 class OneTwoThreeSet(Set):
528 def __init__(self):
529 self.contents = [1, 2, 3]
530 def __contains__(self, x):
531 return x in self.contents
532 def __len__(self):
533 return len(self.contents)
534 def __iter__(self):
535 return iter(self.contents)
536 def __hash__(self):
537 return self._hash()
538 a, b = OneTwoThreeSet(), OneTwoThreeSet()
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000539 self.assertTrue(hash(a) == hash(b))
Raymond Hettinger4c52f522008-06-23 03:29:28 +0000540
Guido van Rossum64c06e32007-11-22 00:55:51 +0000541 def test_MutableSet(self):
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000542 self.assertIsInstance(set(), MutableSet)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000543 self.assertTrue(issubclass(set, MutableSet))
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000544 self.assertNotIsInstance(frozenset(), MutableSet)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000545 self.assertFalse(issubclass(frozenset, MutableSet))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000546 self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
547 'add', 'discard')
548
Raymond Hettinger66c4a6b2009-04-01 18:50:56 +0000549 def test_issue_5647(self):
550 # MutableSet.__iand__ mutated the set during iteration
551 s = WithSet('abcd')
552 s &= WithSet('cdef') # This used to fail
553 self.assertEqual(set(s), set('cd'))
554
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000555 def test_issue_4920(self):
556 # MutableSet.pop() method did not work
557 class MySet(collections.MutableSet):
558 __slots__=['__s']
559 def __init__(self,items=None):
560 if items is None:
561 items=[]
562 self.__s=set(items)
563 def __contains__(self,v):
564 return v in self.__s
565 def __iter__(self):
566 return iter(self.__s)
567 def __len__(self):
568 return len(self.__s)
569 def add(self,v):
570 result=v not in self.__s
571 self.__s.add(v)
572 return result
573 def discard(self,v):
574 result=v in self.__s
575 self.__s.discard(v)
576 return result
577 def __repr__(self):
578 return "MySet(%s)" % repr(list(self))
579 s = MySet([5,43,2,1])
580 self.assertEqual(s.pop(), 1)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000581
Daniel Stutzbach91287322010-08-24 21:09:30 +0000582 def test_issue8750(self):
583 empty = WithSet()
584 full = WithSet(range(10))
585 s = WithSet(full)
586 s -= s
587 self.assertEqual(s, empty)
588 s = WithSet(full)
589 s ^= s
590 self.assertEqual(s, empty)
591 s = WithSet(full)
592 s &= s
593 self.assertEqual(s, full)
594 s |= s
595 self.assertEqual(s, full)
596
Serhiy Storchaka7c573852013-12-06 23:23:15 +0200597 def test_issue16373(self):
598 # Recursion error comparing comparable and noncomparable
599 # Set instances
600 class MyComparableSet(Set):
601 def __contains__(self, x):
602 return False
603 def __len__(self):
604 return 0
605 def __iter__(self):
606 return iter([])
607 class MyNonComparableSet(Set):
608 def __contains__(self, x):
609 return False
610 def __len__(self):
611 return 0
612 def __iter__(self):
613 return iter([])
614 def __le__(self, x):
615 return NotImplemented
616 def __lt__(self, x):
617 return NotImplemented
618
619 cs = MyComparableSet()
620 ncs = MyNonComparableSet()
621 self.assertFalse(ncs < cs)
622 self.assertFalse(ncs <= cs)
623 self.assertFalse(cs > ncs)
624 self.assertFalse(cs >= ncs)
625
Guido van Rossum64c06e32007-11-22 00:55:51 +0000626 def test_Mapping(self):
627 for sample in [dict]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000628 self.assertIsInstance(sample(), Mapping)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000629 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000630 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
631 '__getitem__')
Benjamin Petersoneb318d32010-05-21 20:51:45 +0000632 class MyMapping(collections.Mapping):
633 def __len__(self):
634 return 0
635 def __getitem__(self, i):
636 raise IndexError
637 def __iter__(self):
638 return iter(())
639 self.validate_comparison(MyMapping())
Guido van Rossum64c06e32007-11-22 00:55:51 +0000640
641 def test_MutableMapping(self):
642 for sample in [dict]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000643 self.assertIsInstance(sample(), MutableMapping)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000644 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000645 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
646 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000647
648 def test_Sequence(self):
649 for sample in [tuple, list, str]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000650 self.assertIsInstance(sample(), Sequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000651 self.assertTrue(issubclass(sample, Sequence))
652 self.assertTrue(issubclass(basestring, Sequence))
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000653 self.assertIsInstance(range(10), Sequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000654 self.assertTrue(issubclass(xrange, Sequence))
655 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000656 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
657 '__getitem__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000658
659 def test_MutableSequence(self):
660 for sample in [tuple, str]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000661 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000662 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000663 for sample in [list]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000664 self.assertIsInstance(sample(), MutableSequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000665 self.assertTrue(issubclass(sample, MutableSequence))
666 self.assertFalse(issubclass(basestring, MutableSequence))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000667 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
668 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000669
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000670class TestCounter(unittest.TestCase):
671
672 def test_basics(self):
673 c = Counter('abcaba')
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000674 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
675 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000676 self.assertIsInstance(c, dict)
677 self.assertIsInstance(c, Mapping)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000678 self.assertTrue(issubclass(Counter, dict))
679 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000680 self.assertEqual(len(c), 3)
681 self.assertEqual(sum(c.values()), 6)
682 self.assertEqual(sorted(c.values()), [1, 2, 3])
683 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
684 self.assertEqual(sorted(c), ['a', 'b', 'c'])
685 self.assertEqual(sorted(c.items()),
686 [('a', 3), ('b', 2), ('c', 1)])
687 self.assertEqual(c['b'], 2)
688 self.assertEqual(c['z'], 0)
Florent Xicluna47627d52010-03-08 15:20:28 +0000689 with test_support.check_py3k_warnings():
690 self.assertEqual(c.has_key('c'), True)
691 self.assertEqual(c.has_key('z'), False)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000692 self.assertEqual(c.__contains__('c'), True)
693 self.assertEqual(c.__contains__('z'), False)
694 self.assertEqual(c.get('b', 10), 2)
695 self.assertEqual(c.get('z', 10), 10)
696 self.assertEqual(c, dict(a=3, b=2, c=1))
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000697 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000698 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
699 for i in range(5):
700 self.assertEqual(c.most_common(i),
701 [('a', 3), ('b', 2), ('c', 1)][:i])
702 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
703 c['a'] += 1 # increment an existing value
704 c['b'] -= 2 # sub existing value to zero
705 del c['c'] # remove an entry
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000706 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000707 c['d'] -= 2 # sub from a missing value
708 c['e'] = -5 # directly assign a missing value
709 c['f'] += 4 # add to a missing value
710 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
711 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
712 self.assertEqual(c.pop('f'), 4)
Ezio Melottiaa980582010-01-23 23:04:36 +0000713 self.assertNotIn('f', c)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000714 for i in range(3):
715 elem, cnt = c.popitem()
Ezio Melottiaa980582010-01-23 23:04:36 +0000716 self.assertNotIn(elem, c)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000717 c.clear()
718 self.assertEqual(c, {})
719 self.assertEqual(repr(c), 'Counter()')
720 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
721 self.assertRaises(TypeError, hash, c)
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000722 c.update(dict(a=5, b=3))
723 c.update(c=1)
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000724 c.update(Counter('a' * 50 + 'b' * 30))
Raymond Hettingerafd112b2009-01-14 01:15:06 +0000725 c.update() # test case with no args
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000726 c.__init__('a' * 500 + 'b' * 300)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000727 c.__init__('cdc')
Raymond Hettingerafd112b2009-01-14 01:15:06 +0000728 c.__init__()
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000729 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
730 self.assertEqual(c.setdefault('d', 5), 1)
731 self.assertEqual(c['d'], 1)
732 self.assertEqual(c.setdefault('e', 5), 5)
733 self.assertEqual(c['e'], 5)
734
735 def test_copying(self):
736 # Check that counters are copyable, deepcopyable, picklable, and
737 #have a repr/eval round-trip
738 words = Counter('which witch had which witches wrist watch'.split())
739 update_test = Counter()
740 update_test.update(words)
741 for i, dup in enumerate([
742 words.copy(),
743 copy.copy(words),
744 copy.deepcopy(words),
745 pickle.loads(pickle.dumps(words, 0)),
746 pickle.loads(pickle.dumps(words, 1)),
747 pickle.loads(pickle.dumps(words, 2)),
748 pickle.loads(pickle.dumps(words, -1)),
749 cPickle.loads(cPickle.dumps(words, 0)),
750 cPickle.loads(cPickle.dumps(words, 1)),
751 cPickle.loads(cPickle.dumps(words, 2)),
752 cPickle.loads(cPickle.dumps(words, -1)),
753 eval(repr(words)),
754 update_test,
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000755 Counter(words),
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000756 ]):
757 msg = (i, dup, words)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000758 self.assertTrue(dup is not words)
Ezio Melotti2623a372010-11-21 13:34:58 +0000759 self.assertEqual(dup, words)
760 self.assertEqual(len(dup), len(words))
761 self.assertEqual(type(dup), type(words))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000762
Raymond Hettinger37c0fe52011-04-15 13:12:21 -0700763 def test_copy_subclass(self):
764 class MyCounter(Counter):
765 pass
766 c = MyCounter('slartibartfast')
767 d = c.copy()
768 self.assertEqual(d, c)
769 self.assertEqual(len(d), len(c))
770 self.assertEqual(type(d), type(c))
771
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000772 def test_conversions(self):
773 # Convert to: set, list, dict
774 s = 'she sells sea shells by the sea shore'
775 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
776 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
777 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
778 self.assertEqual(set(Counter(s)), set(s))
779
Raymond Hettinger0a1f7b82009-01-21 23:12:51 +0000780 def test_invariant_for_the_in_operator(self):
781 c = Counter(a=10, b=-2, c=0)
782 for elem in c:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000783 self.assertTrue(elem in c)
Ezio Melottiaa980582010-01-23 23:04:36 +0000784 self.assertIn(elem, c)
Raymond Hettinger0a1f7b82009-01-21 23:12:51 +0000785
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000786 def test_multiset_operations(self):
787 # Verify that adding a zero counter will strip zeros and negatives
788 c = Counter(a=10, b=-2, c=0) + Counter()
789 self.assertEqual(dict(c), dict(a=10))
790
791 elements = 'abcd'
792 for i in range(1000):
793 # test random pairs of multisets
794 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettinger4571f342009-01-21 20:31:50 +0000795 p.update(e=1, f=-1, g=0)
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000796 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettinger4571f342009-01-21 20:31:50 +0000797 q.update(h=1, i=-1, j=0)
798 for counterop, numberop in [
799 (Counter.__add__, lambda x, y: max(0, x+y)),
800 (Counter.__sub__, lambda x, y: max(0, x-y)),
801 (Counter.__or__, lambda x, y: max(0,x,y)),
802 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000803 ]:
804 result = counterop(p, q)
805 for x in elements:
Raymond Hettinger4571f342009-01-21 20:31:50 +0000806 self.assertEqual(numberop(p[x], q[x]), result[x],
807 (counterop, x, p, q))
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000808 # verify that results exclude non-positive counts
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000809 self.assertTrue(x>0 for x in result.values())
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000810
811 elements = 'abcdef'
812 for i in range(100):
813 # verify that random multisets with no repeats are exactly like sets
814 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
815 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
816 for counterop, setop in [
817 (Counter.__sub__, set.__sub__),
818 (Counter.__or__, set.__or__),
819 (Counter.__and__, set.__and__),
820 ]:
821 counter_result = counterop(p, q)
822 set_result = setop(set(p.elements()), set(q.elements()))
823 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000824
Raymond Hettinger34c35b22010-04-03 10:22:00 +0000825 def test_subtract(self):
826 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
827 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
828 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
829 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
830 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
831 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
832 c = Counter('aaabbcd')
833 c.subtract('aaaabbcce')
834 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
835
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000836class TestOrderedDict(unittest.TestCase):
837
838 def test_init(self):
839 with self.assertRaises(TypeError):
840 OrderedDict([('a', 1), ('b', 2)], None) # too many args
841 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
842 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
843 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
844 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
845 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
846 c=3, e=5).items()), pairs) # mixed input
847
848 # make sure no positional args conflict with possible kwdargs
849 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
850 ['self'])
851
852 # Make sure that direct calls to __init__ do not clear previous contents
853 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
854 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
855 self.assertEqual(list(d.items()),
856 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
857
858 def test_update(self):
859 with self.assertRaises(TypeError):
860 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
861 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
862 od = OrderedDict()
863 od.update(dict(pairs))
864 self.assertEqual(sorted(od.items()), pairs) # dict input
865 od = OrderedDict()
866 od.update(**dict(pairs))
867 self.assertEqual(sorted(od.items()), pairs) # kwds input
868 od = OrderedDict()
869 od.update(pairs)
870 self.assertEqual(list(od.items()), pairs) # pairs input
871 od = OrderedDict()
872 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
873 self.assertEqual(list(od.items()), pairs) # mixed input
874
Mark Dickinson42add992010-07-11 19:17:28 +0000875 # Issue 9137: Named argument called 'other' or 'self'
876 # shouldn't be treated specially.
877 od = OrderedDict()
878 od.update(self=23)
879 self.assertEqual(list(od.items()), [('self', 23)])
880 od = OrderedDict()
881 od.update(other={})
882 self.assertEqual(list(od.items()), [('other', {})])
883 od = OrderedDict()
884 od.update(red=5, blue=6, other=7, self=8)
885 self.assertEqual(sorted(list(od.items())),
886 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
887
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000888 # Make sure that direct calls to update do not clear previous contents
889 # add that updates items are not moved to the end
890 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
891 d.update([('e', 5), ('f', 6)], g=7, d=4)
892 self.assertEqual(list(d.items()),
893 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
894
Raymond Hettinger8ebebd82011-01-02 01:03:26 +0000895 def test_abc(self):
896 self.assertIsInstance(OrderedDict(), MutableMapping)
897 self.assertTrue(issubclass(OrderedDict, MutableMapping))
898
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000899 def test_clear(self):
900 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
901 shuffle(pairs)
902 od = OrderedDict(pairs)
903 self.assertEqual(len(od), len(pairs))
904 od.clear()
905 self.assertEqual(len(od), 0)
906
907 def test_delitem(self):
908 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
909 od = OrderedDict(pairs)
910 del od['a']
Ezio Melottiaa980582010-01-23 23:04:36 +0000911 self.assertNotIn('a', od)
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000912 with self.assertRaises(KeyError):
913 del od['a']
914 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
915
916 def test_setitem(self):
917 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
918 od['c'] = 10 # existing element
919 od['f'] = 20 # new element
920 self.assertEqual(list(od.items()),
921 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
922
923 def test_iterators(self):
924 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
925 shuffle(pairs)
926 od = OrderedDict(pairs)
927 self.assertEqual(list(od), [t[0] for t in pairs])
Raymond Hettingerf17f81d2009-03-03 07:12:09 +0000928 self.assertEqual(od.keys()[:], [t[0] for t in pairs])
929 self.assertEqual(od.values()[:], [t[1] for t in pairs])
930 self.assertEqual(od.items()[:], pairs)
931 self.assertEqual(list(od.iterkeys()), [t[0] for t in pairs])
932 self.assertEqual(list(od.itervalues()), [t[1] for t in pairs])
933 self.assertEqual(list(od.iteritems()), pairs)
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000934 self.assertEqual(list(reversed(od)),
935 [t[0] for t in reversed(pairs)])
936
937 def test_popitem(self):
938 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
939 shuffle(pairs)
940 od = OrderedDict(pairs)
941 while pairs:
942 self.assertEqual(od.popitem(), pairs.pop())
943 with self.assertRaises(KeyError):
944 od.popitem()
945 self.assertEqual(len(od), 0)
946
947 def test_pop(self):
948 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
949 shuffle(pairs)
950 od = OrderedDict(pairs)
951 shuffle(pairs)
952 while pairs:
953 k, v = pairs.pop()
954 self.assertEqual(od.pop(k), v)
955 with self.assertRaises(KeyError):
956 od.pop('xyz')
957 self.assertEqual(len(od), 0)
958 self.assertEqual(od.pop(k, 12345), 12345)
959
Raymond Hettinger8ebebd82011-01-02 01:03:26 +0000960 # make sure pop still works when __missing__ is defined
961 class Missing(OrderedDict):
962 def __missing__(self, key):
963 return 0
964 m = Missing(a=1)
965 self.assertEqual(m.pop('b', 5), 5)
966 self.assertEqual(m.pop('a', 6), 1)
967 self.assertEqual(m.pop('a', 6), 6)
968 with self.assertRaises(KeyError):
969 m.pop('a')
970
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000971 def test_equality(self):
972 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
973 shuffle(pairs)
974 od1 = OrderedDict(pairs)
975 od2 = OrderedDict(pairs)
976 self.assertEqual(od1, od2) # same order implies equality
977 pairs = pairs[2:] + pairs[:2]
978 od2 = OrderedDict(pairs)
979 self.assertNotEqual(od1, od2) # different order implies inequality
980 # comparison to regular dict is not order sensitive
981 self.assertEqual(od1, dict(od2))
982 self.assertEqual(dict(od2), od1)
983 # different length implied inequality
984 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
985
986 def test_copying(self):
987 # Check that ordered dicts are copyable, deepcopyable, picklable,
988 # and have a repr/eval round-trip
989 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
990 od = OrderedDict(pairs)
991 update_test = OrderedDict()
992 update_test.update(od)
993 for i, dup in enumerate([
994 od.copy(),
995 copy.copy(od),
996 copy.deepcopy(od),
997 pickle.loads(pickle.dumps(od, 0)),
998 pickle.loads(pickle.dumps(od, 1)),
999 pickle.loads(pickle.dumps(od, 2)),
1000 pickle.loads(pickle.dumps(od, -1)),
1001 eval(repr(od)),
1002 update_test,
1003 OrderedDict(od),
1004 ]):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001005 self.assertTrue(dup is not od)
Ezio Melotti2623a372010-11-21 13:34:58 +00001006 self.assertEqual(dup, od)
1007 self.assertEqual(list(dup.items()), list(od.items()))
1008 self.assertEqual(len(dup), len(od))
1009 self.assertEqual(type(dup), type(od))
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001010
Raymond Hettinger131af652009-03-03 22:59:25 +00001011 def test_yaml_linkage(self):
1012 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
1013 # In yaml, lists are native but tuples are not.
1014 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1015 od = OrderedDict(pairs)
1016 # yaml.dump(od) -->
1017 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001018 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger131af652009-03-03 22:59:25 +00001019
1020 def test_reduce_not_too_fat(self):
1021 # do not save instance dictionary if not needed
1022 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1023 od = OrderedDict(pairs)
Alexandre Vassalotticb73bda2009-06-12 23:03:35 +00001024 self.assertEqual(len(od.__reduce__()), 2)
Raymond Hettinger131af652009-03-03 22:59:25 +00001025 od.x = 10
Alexandre Vassalotticb73bda2009-06-12 23:03:35 +00001026 self.assertEqual(len(od.__reduce__()), 3)
Raymond Hettinger131af652009-03-03 22:59:25 +00001027
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001028 def test_repr(self):
1029 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1030 self.assertEqual(repr(od),
1031 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1032 self.assertEqual(eval(repr(od)), od)
1033 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1034
Raymond Hettinger74f869e2010-09-13 22:14:36 +00001035 def test_repr_recursive(self):
1036 # See issue #9826
1037 od = OrderedDict.fromkeys('abc')
1038 od['x'] = od
1039 self.assertEqual(repr(od),
1040 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1041
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001042 def test_setdefault(self):
1043 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1044 shuffle(pairs)
1045 od = OrderedDict(pairs)
1046 pair_order = list(od.items())
1047 self.assertEqual(od.setdefault('a', 10), 3)
1048 # make sure order didn't change
1049 self.assertEqual(list(od.items()), pair_order)
1050 self.assertEqual(od.setdefault('x', 10), 10)
1051 # make sure 'x' is added to the end
1052 self.assertEqual(list(od.items())[-1], ('x', 10))
1053
Raymond Hettinger8ebebd82011-01-02 01:03:26 +00001054 # make sure setdefault still works when __missing__ is defined
1055 class Missing(OrderedDict):
1056 def __missing__(self, key):
1057 return 0
1058 self.assertEqual(Missing().setdefault(5, 9), 9)
1059
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001060 def test_reinsert(self):
1061 # Given insert a, insert b, delete a, re-insert a,
1062 # verify that a is now later than b.
1063 od = OrderedDict()
1064 od['a'] = 1
1065 od['b'] = 2
1066 del od['a']
1067 od['a'] = 1
1068 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1069
Raymond Hettingera54b2da2010-08-17 19:03:06 +00001070 def test_views(self):
1071 s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split()
1072 od = OrderedDict.fromkeys(s)
1073 self.assertEqual(list(od.viewkeys()), s)
1074 self.assertEqual(list(od.viewvalues()), [None for k in s])
1075 self.assertEqual(list(od.viewitems()), [(k, None) for k in s])
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001076
Raymond Hettinger8ebebd82011-01-02 01:03:26 +00001077 def test_override_update(self):
1078 # Verify that subclasses can override update() without breaking __init__()
1079 class MyOD(OrderedDict):
1080 def update(self, *args, **kwds):
1081 raise Exception()
1082 items = [('a', 1), ('c', 3), ('b', 2)]
1083 self.assertEqual(list(MyOD(items).items()), items)
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001084
1085class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1086 type2test = OrderedDict
1087
Raymond Hettinger24122992009-03-19 19:59:58 +00001088 def test_popitem(self):
1089 d = self._empty_mapping()
1090 self.assertRaises(KeyError, d.popitem)
1091
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001092class MyOrderedDict(OrderedDict):
1093 pass
1094
1095class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1096 type2test = MyOrderedDict
1097
Raymond Hettinger24122992009-03-19 19:59:58 +00001098 def test_popitem(self):
1099 d = self._empty_mapping()
1100 self.assertRaises(KeyError, d.popitem)
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001101
Georg Brandla4f46e12010-02-07 17:03:15 +00001102import collections
Guido van Rossum64c06e32007-11-22 00:55:51 +00001103
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00001104def test_main(verbose=None):
Amaury Forgeot d'Arccb0f2ad2008-04-02 00:55:04 +00001105 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +00001106 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001107 TestCollectionABCs, TestCounter,
1108 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00001109 test_support.run_unittest(*test_classes)
Amaury Forgeot d'Arccb0f2ad2008-04-02 00:55:04 +00001110 test_support.run_doctest(collections, verbose)
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00001111
1112if __name__ == "__main__":
1113 test_main(verbose=True)