blob: 3aaecb2a6f9b64d1957844befaeb65fea66d98fa [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
Guido van Rossum64c06e32007-11-22 00:55:51 +0000597 def test_Mapping(self):
598 for sample in [dict]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000599 self.assertIsInstance(sample(), Mapping)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000600 self.assertTrue(issubclass(sample, Mapping))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000601 self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
602 '__getitem__')
Benjamin Petersoneb318d32010-05-21 20:51:45 +0000603 class MyMapping(collections.Mapping):
604 def __len__(self):
605 return 0
606 def __getitem__(self, i):
607 raise IndexError
608 def __iter__(self):
609 return iter(())
610 self.validate_comparison(MyMapping())
Guido van Rossum64c06e32007-11-22 00:55:51 +0000611
612 def test_MutableMapping(self):
613 for sample in [dict]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000614 self.assertIsInstance(sample(), MutableMapping)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000615 self.assertTrue(issubclass(sample, MutableMapping))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000616 self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
617 '__getitem__', '__setitem__', '__delitem__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000618
619 def test_Sequence(self):
620 for sample in [tuple, list, str]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000621 self.assertIsInstance(sample(), Sequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000622 self.assertTrue(issubclass(sample, Sequence))
623 self.assertTrue(issubclass(basestring, Sequence))
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000624 self.assertIsInstance(range(10), Sequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000625 self.assertTrue(issubclass(xrange, Sequence))
626 self.assertTrue(issubclass(str, Sequence))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000627 self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
628 '__getitem__')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000629
630 def test_MutableSequence(self):
631 for sample in [tuple, str]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000632 self.assertNotIsInstance(sample(), MutableSequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000633 self.assertFalse(issubclass(sample, MutableSequence))
Guido van Rossum64c06e32007-11-22 00:55:51 +0000634 for sample in [list]:
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000635 self.assertIsInstance(sample(), MutableSequence)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000636 self.assertTrue(issubclass(sample, MutableSequence))
637 self.assertFalse(issubclass(basestring, MutableSequence))
Raymond Hettingerf779e6f2009-01-28 23:02:26 +0000638 self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
639 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
Guido van Rossum64c06e32007-11-22 00:55:51 +0000640
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000641class TestCounter(unittest.TestCase):
642
643 def test_basics(self):
644 c = Counter('abcaba')
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000645 self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
646 self.assertEqual(c, Counter(a=3, b=2, c=1))
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000647 self.assertIsInstance(c, dict)
648 self.assertIsInstance(c, Mapping)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000649 self.assertTrue(issubclass(Counter, dict))
650 self.assertTrue(issubclass(Counter, Mapping))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000651 self.assertEqual(len(c), 3)
652 self.assertEqual(sum(c.values()), 6)
653 self.assertEqual(sorted(c.values()), [1, 2, 3])
654 self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
655 self.assertEqual(sorted(c), ['a', 'b', 'c'])
656 self.assertEqual(sorted(c.items()),
657 [('a', 3), ('b', 2), ('c', 1)])
658 self.assertEqual(c['b'], 2)
659 self.assertEqual(c['z'], 0)
Florent Xicluna47627d52010-03-08 15:20:28 +0000660 with test_support.check_py3k_warnings():
661 self.assertEqual(c.has_key('c'), True)
662 self.assertEqual(c.has_key('z'), False)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000663 self.assertEqual(c.__contains__('c'), True)
664 self.assertEqual(c.__contains__('z'), False)
665 self.assertEqual(c.get('b', 10), 2)
666 self.assertEqual(c.get('z', 10), 10)
667 self.assertEqual(c, dict(a=3, b=2, c=1))
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000668 self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000669 self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
670 for i in range(5):
671 self.assertEqual(c.most_common(i),
672 [('a', 3), ('b', 2), ('c', 1)][:i])
673 self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
674 c['a'] += 1 # increment an existing value
675 c['b'] -= 2 # sub existing value to zero
676 del c['c'] # remove an entry
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000677 del c['c'] # make sure that del doesn't raise KeyError
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000678 c['d'] -= 2 # sub from a missing value
679 c['e'] = -5 # directly assign a missing value
680 c['f'] += 4 # add to a missing value
681 self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
682 self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
683 self.assertEqual(c.pop('f'), 4)
Ezio Melottiaa980582010-01-23 23:04:36 +0000684 self.assertNotIn('f', c)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000685 for i in range(3):
686 elem, cnt = c.popitem()
Ezio Melottiaa980582010-01-23 23:04:36 +0000687 self.assertNotIn(elem, c)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000688 c.clear()
689 self.assertEqual(c, {})
690 self.assertEqual(repr(c), 'Counter()')
691 self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
692 self.assertRaises(TypeError, hash, c)
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000693 c.update(dict(a=5, b=3))
694 c.update(c=1)
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000695 c.update(Counter('a' * 50 + 'b' * 30))
Raymond Hettingerafd112b2009-01-14 01:15:06 +0000696 c.update() # test case with no args
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000697 c.__init__('a' * 500 + 'b' * 300)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000698 c.__init__('cdc')
Raymond Hettingerafd112b2009-01-14 01:15:06 +0000699 c.__init__()
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000700 self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
701 self.assertEqual(c.setdefault('d', 5), 1)
702 self.assertEqual(c['d'], 1)
703 self.assertEqual(c.setdefault('e', 5), 5)
704 self.assertEqual(c['e'], 5)
705
706 def test_copying(self):
707 # Check that counters are copyable, deepcopyable, picklable, and
708 #have a repr/eval round-trip
709 words = Counter('which witch had which witches wrist watch'.split())
710 update_test = Counter()
711 update_test.update(words)
712 for i, dup in enumerate([
713 words.copy(),
714 copy.copy(words),
715 copy.deepcopy(words),
716 pickle.loads(pickle.dumps(words, 0)),
717 pickle.loads(pickle.dumps(words, 1)),
718 pickle.loads(pickle.dumps(words, 2)),
719 pickle.loads(pickle.dumps(words, -1)),
720 cPickle.loads(cPickle.dumps(words, 0)),
721 cPickle.loads(cPickle.dumps(words, 1)),
722 cPickle.loads(cPickle.dumps(words, 2)),
723 cPickle.loads(cPickle.dumps(words, -1)),
724 eval(repr(words)),
725 update_test,
Raymond Hettingeraaa6e632009-01-13 01:05:03 +0000726 Counter(words),
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000727 ]):
728 msg = (i, dup, words)
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000729 self.assertTrue(dup is not words)
Ezio Melotti2623a372010-11-21 13:34:58 +0000730 self.assertEqual(dup, words)
731 self.assertEqual(len(dup), len(words))
732 self.assertEqual(type(dup), type(words))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000733
Raymond Hettinger37c0fe52011-04-15 13:12:21 -0700734 def test_copy_subclass(self):
735 class MyCounter(Counter):
736 pass
737 c = MyCounter('slartibartfast')
738 d = c.copy()
739 self.assertEqual(d, c)
740 self.assertEqual(len(d), len(c))
741 self.assertEqual(type(d), type(c))
742
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000743 def test_conversions(self):
744 # Convert to: set, list, dict
745 s = 'she sells sea shells by the sea shore'
746 self.assertEqual(sorted(Counter(s).elements()), sorted(s))
747 self.assertEqual(sorted(Counter(s)), sorted(set(s)))
748 self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
749 self.assertEqual(set(Counter(s)), set(s))
750
Raymond Hettinger0a1f7b82009-01-21 23:12:51 +0000751 def test_invariant_for_the_in_operator(self):
752 c = Counter(a=10, b=-2, c=0)
753 for elem in c:
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000754 self.assertTrue(elem in c)
Ezio Melottiaa980582010-01-23 23:04:36 +0000755 self.assertIn(elem, c)
Raymond Hettinger0a1f7b82009-01-21 23:12:51 +0000756
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000757 def test_multiset_operations(self):
758 # Verify that adding a zero counter will strip zeros and negatives
759 c = Counter(a=10, b=-2, c=0) + Counter()
760 self.assertEqual(dict(c), dict(a=10))
761
762 elements = 'abcd'
763 for i in range(1000):
764 # test random pairs of multisets
765 p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettinger4571f342009-01-21 20:31:50 +0000766 p.update(e=1, f=-1, g=0)
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000767 q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
Raymond Hettinger4571f342009-01-21 20:31:50 +0000768 q.update(h=1, i=-1, j=0)
769 for counterop, numberop in [
770 (Counter.__add__, lambda x, y: max(0, x+y)),
771 (Counter.__sub__, lambda x, y: max(0, x-y)),
772 (Counter.__or__, lambda x, y: max(0,x,y)),
773 (Counter.__and__, lambda x, y: max(0, min(x,y))),
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000774 ]:
775 result = counterop(p, q)
776 for x in elements:
Raymond Hettinger4571f342009-01-21 20:31:50 +0000777 self.assertEqual(numberop(p[x], q[x]), result[x],
778 (counterop, x, p, q))
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000779 # verify that results exclude non-positive counts
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000780 self.assertTrue(x>0 for x in result.values())
Raymond Hettingerbad1eb22009-01-20 01:19:26 +0000781
782 elements = 'abcdef'
783 for i in range(100):
784 # verify that random multisets with no repeats are exactly like sets
785 p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
786 q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
787 for counterop, setop in [
788 (Counter.__sub__, set.__sub__),
789 (Counter.__or__, set.__or__),
790 (Counter.__and__, set.__and__),
791 ]:
792 counter_result = counterop(p, q)
793 set_result = setop(set(p.elements()), set(q.elements()))
794 self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +0000795
Raymond Hettinger34c35b22010-04-03 10:22:00 +0000796 def test_subtract(self):
797 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
798 c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
799 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
800 c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
801 c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
802 self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
803 c = Counter('aaabbcd')
804 c.subtract('aaaabbcce')
805 self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
806
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000807class TestOrderedDict(unittest.TestCase):
808
809 def test_init(self):
810 with self.assertRaises(TypeError):
811 OrderedDict([('a', 1), ('b', 2)], None) # too many args
812 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
813 self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
814 self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
815 self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
816 self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
817 c=3, e=5).items()), pairs) # mixed input
818
819 # make sure no positional args conflict with possible kwdargs
820 self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
821 ['self'])
822
823 # Make sure that direct calls to __init__ do not clear previous contents
824 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
825 d.__init__([('e', 5), ('f', 6)], g=7, d=4)
826 self.assertEqual(list(d.items()),
827 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
828
829 def test_update(self):
830 with self.assertRaises(TypeError):
831 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
832 pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
833 od = OrderedDict()
834 od.update(dict(pairs))
835 self.assertEqual(sorted(od.items()), pairs) # dict input
836 od = OrderedDict()
837 od.update(**dict(pairs))
838 self.assertEqual(sorted(od.items()), pairs) # kwds input
839 od = OrderedDict()
840 od.update(pairs)
841 self.assertEqual(list(od.items()), pairs) # pairs input
842 od = OrderedDict()
843 od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
844 self.assertEqual(list(od.items()), pairs) # mixed input
845
Mark Dickinson42add992010-07-11 19:17:28 +0000846 # Issue 9137: Named argument called 'other' or 'self'
847 # shouldn't be treated specially.
848 od = OrderedDict()
849 od.update(self=23)
850 self.assertEqual(list(od.items()), [('self', 23)])
851 od = OrderedDict()
852 od.update(other={})
853 self.assertEqual(list(od.items()), [('other', {})])
854 od = OrderedDict()
855 od.update(red=5, blue=6, other=7, self=8)
856 self.assertEqual(sorted(list(od.items())),
857 [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
858
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000859 # Make sure that direct calls to update do not clear previous contents
860 # add that updates items are not moved to the end
861 d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
862 d.update([('e', 5), ('f', 6)], g=7, d=4)
863 self.assertEqual(list(d.items()),
864 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
865
Raymond Hettinger8ebebd82011-01-02 01:03:26 +0000866 def test_abc(self):
867 self.assertIsInstance(OrderedDict(), MutableMapping)
868 self.assertTrue(issubclass(OrderedDict, MutableMapping))
869
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000870 def test_clear(self):
871 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
872 shuffle(pairs)
873 od = OrderedDict(pairs)
874 self.assertEqual(len(od), len(pairs))
875 od.clear()
876 self.assertEqual(len(od), 0)
877
878 def test_delitem(self):
879 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
880 od = OrderedDict(pairs)
881 del od['a']
Ezio Melottiaa980582010-01-23 23:04:36 +0000882 self.assertNotIn('a', od)
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000883 with self.assertRaises(KeyError):
884 del od['a']
885 self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
886
887 def test_setitem(self):
888 od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
889 od['c'] = 10 # existing element
890 od['f'] = 20 # new element
891 self.assertEqual(list(od.items()),
892 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
893
894 def test_iterators(self):
895 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
896 shuffle(pairs)
897 od = OrderedDict(pairs)
898 self.assertEqual(list(od), [t[0] for t in pairs])
Raymond Hettingerf17f81d2009-03-03 07:12:09 +0000899 self.assertEqual(od.keys()[:], [t[0] for t in pairs])
900 self.assertEqual(od.values()[:], [t[1] for t in pairs])
901 self.assertEqual(od.items()[:], pairs)
902 self.assertEqual(list(od.iterkeys()), [t[0] for t in pairs])
903 self.assertEqual(list(od.itervalues()), [t[1] for t in pairs])
904 self.assertEqual(list(od.iteritems()), pairs)
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000905 self.assertEqual(list(reversed(od)),
906 [t[0] for t in reversed(pairs)])
907
908 def test_popitem(self):
909 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
910 shuffle(pairs)
911 od = OrderedDict(pairs)
912 while pairs:
913 self.assertEqual(od.popitem(), pairs.pop())
914 with self.assertRaises(KeyError):
915 od.popitem()
916 self.assertEqual(len(od), 0)
917
918 def test_pop(self):
919 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
920 shuffle(pairs)
921 od = OrderedDict(pairs)
922 shuffle(pairs)
923 while pairs:
924 k, v = pairs.pop()
925 self.assertEqual(od.pop(k), v)
926 with self.assertRaises(KeyError):
927 od.pop('xyz')
928 self.assertEqual(len(od), 0)
929 self.assertEqual(od.pop(k, 12345), 12345)
930
Raymond Hettinger8ebebd82011-01-02 01:03:26 +0000931 # make sure pop still works when __missing__ is defined
932 class Missing(OrderedDict):
933 def __missing__(self, key):
934 return 0
935 m = Missing(a=1)
936 self.assertEqual(m.pop('b', 5), 5)
937 self.assertEqual(m.pop('a', 6), 1)
938 self.assertEqual(m.pop('a', 6), 6)
939 with self.assertRaises(KeyError):
940 m.pop('a')
941
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000942 def test_equality(self):
943 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
944 shuffle(pairs)
945 od1 = OrderedDict(pairs)
946 od2 = OrderedDict(pairs)
947 self.assertEqual(od1, od2) # same order implies equality
948 pairs = pairs[2:] + pairs[:2]
949 od2 = OrderedDict(pairs)
950 self.assertNotEqual(od1, od2) # different order implies inequality
951 # comparison to regular dict is not order sensitive
952 self.assertEqual(od1, dict(od2))
953 self.assertEqual(dict(od2), od1)
954 # different length implied inequality
955 self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
956
957 def test_copying(self):
958 # Check that ordered dicts are copyable, deepcopyable, picklable,
959 # and have a repr/eval round-trip
960 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
961 od = OrderedDict(pairs)
962 update_test = OrderedDict()
963 update_test.update(od)
964 for i, dup in enumerate([
965 od.copy(),
966 copy.copy(od),
967 copy.deepcopy(od),
968 pickle.loads(pickle.dumps(od, 0)),
969 pickle.loads(pickle.dumps(od, 1)),
970 pickle.loads(pickle.dumps(od, 2)),
971 pickle.loads(pickle.dumps(od, -1)),
972 eval(repr(od)),
973 update_test,
974 OrderedDict(od),
975 ]):
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000976 self.assertTrue(dup is not od)
Ezio Melotti2623a372010-11-21 13:34:58 +0000977 self.assertEqual(dup, od)
978 self.assertEqual(list(dup.items()), list(od.items()))
979 self.assertEqual(len(dup), len(od))
980 self.assertEqual(type(dup), type(od))
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000981
Raymond Hettinger131af652009-03-03 22:59:25 +0000982 def test_yaml_linkage(self):
983 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
984 # In yaml, lists are native but tuples are not.
985 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
986 od = OrderedDict(pairs)
987 # yaml.dump(od) -->
988 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000989 self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
Raymond Hettinger131af652009-03-03 22:59:25 +0000990
991 def test_reduce_not_too_fat(self):
992 # do not save instance dictionary if not needed
993 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
994 od = OrderedDict(pairs)
Alexandre Vassalotticb73bda2009-06-12 23:03:35 +0000995 self.assertEqual(len(od.__reduce__()), 2)
Raymond Hettinger131af652009-03-03 22:59:25 +0000996 od.x = 10
Alexandre Vassalotticb73bda2009-06-12 23:03:35 +0000997 self.assertEqual(len(od.__reduce__()), 3)
Raymond Hettinger131af652009-03-03 22:59:25 +0000998
Raymond Hettingerbc512d32009-03-03 04:45:34 +0000999 def test_repr(self):
1000 od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
1001 self.assertEqual(repr(od),
1002 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
1003 self.assertEqual(eval(repr(od)), od)
1004 self.assertEqual(repr(OrderedDict()), "OrderedDict()")
1005
Raymond Hettinger74f869e2010-09-13 22:14:36 +00001006 def test_repr_recursive(self):
1007 # See issue #9826
1008 od = OrderedDict.fromkeys('abc')
1009 od['x'] = od
1010 self.assertEqual(repr(od),
1011 "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1012
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001013 def test_setdefault(self):
1014 pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1015 shuffle(pairs)
1016 od = OrderedDict(pairs)
1017 pair_order = list(od.items())
1018 self.assertEqual(od.setdefault('a', 10), 3)
1019 # make sure order didn't change
1020 self.assertEqual(list(od.items()), pair_order)
1021 self.assertEqual(od.setdefault('x', 10), 10)
1022 # make sure 'x' is added to the end
1023 self.assertEqual(list(od.items())[-1], ('x', 10))
1024
Raymond Hettinger8ebebd82011-01-02 01:03:26 +00001025 # make sure setdefault still works when __missing__ is defined
1026 class Missing(OrderedDict):
1027 def __missing__(self, key):
1028 return 0
1029 self.assertEqual(Missing().setdefault(5, 9), 9)
1030
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001031 def test_reinsert(self):
1032 # Given insert a, insert b, delete a, re-insert a,
1033 # verify that a is now later than b.
1034 od = OrderedDict()
1035 od['a'] = 1
1036 od['b'] = 2
1037 del od['a']
1038 od['a'] = 1
1039 self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1040
Raymond Hettingera54b2da2010-08-17 19:03:06 +00001041 def test_views(self):
1042 s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split()
1043 od = OrderedDict.fromkeys(s)
1044 self.assertEqual(list(od.viewkeys()), s)
1045 self.assertEqual(list(od.viewvalues()), [None for k in s])
1046 self.assertEqual(list(od.viewitems()), [(k, None) for k in s])
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001047
Raymond Hettinger8ebebd82011-01-02 01:03:26 +00001048 def test_override_update(self):
1049 # Verify that subclasses can override update() without breaking __init__()
1050 class MyOD(OrderedDict):
1051 def update(self, *args, **kwds):
1052 raise Exception()
1053 items = [('a', 1), ('c', 3), ('b', 2)]
1054 self.assertEqual(list(MyOD(items).items()), items)
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001055
1056class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1057 type2test = OrderedDict
1058
Raymond Hettinger24122992009-03-19 19:59:58 +00001059 def test_popitem(self):
1060 d = self._empty_mapping()
1061 self.assertRaises(KeyError, d.popitem)
1062
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001063class MyOrderedDict(OrderedDict):
1064 pass
1065
1066class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1067 type2test = MyOrderedDict
1068
Raymond Hettinger24122992009-03-19 19:59:58 +00001069 def test_popitem(self):
1070 d = self._empty_mapping()
1071 self.assertRaises(KeyError, d.popitem)
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001072
Georg Brandla4f46e12010-02-07 17:03:15 +00001073import collections
Guido van Rossum64c06e32007-11-22 00:55:51 +00001074
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00001075def test_main(verbose=None):
Amaury Forgeot d'Arccb0f2ad2008-04-02 00:55:04 +00001076 NamedTupleDocs = doctest.DocTestSuite(module=collections)
Raymond Hettingerf94d7fa2009-01-12 22:58:41 +00001077 test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
Raymond Hettingerbc512d32009-03-03 04:45:34 +00001078 TestCollectionABCs, TestCounter,
1079 TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00001080 test_support.run_unittest(*test_classes)
Amaury Forgeot d'Arccb0f2ad2008-04-02 00:55:04 +00001081 test_support.run_doctest(collections, verbose)
Raymond Hettingerc37e5e02007-03-01 06:16:43 +00001082
1083if __name__ == "__main__":
1084 test_main(verbose=True)