2 import unittest
, doctest
, operator
4 from test
import test_support
5 from collections
import namedtuple
, Counter
, OrderedDict
6 from test
import mapping_tests
7 import pickle
, cPickle
, copy
8 from random
import randrange
, shuffle
12 from collections
import Hashable
, Iterable
, Iterator
13 from collections
import Sized
, Container
, Callable
14 from collections
import Set
, MutableSet
15 from collections
import Mapping
, MutableMapping
16 from collections
import Sequence
, MutableSequence
18 TestNT
= namedtuple('TestNT', 'x y z') # type used for pickle tests
20 class TestNamedTuple(unittest
.TestCase
):
22 def test_factory(self
):
23 Point
= namedtuple('Point', 'x y')
24 self
.assertEqual(Point
.__name
__, 'Point')
25 self
.assertEqual(Point
.__slots
__, ())
26 self
.assertEqual(Point
.__module
__, __name__
)
27 self
.assertEqual(Point
.__getitem
__, tuple.__getitem
__)
28 self
.assertEqual(Point
._fields
, ('x', 'y'))
30 self
.assertRaises(ValueError, namedtuple
, 'abc%', 'efg ghi') # type has non-alpha char
31 self
.assertRaises(ValueError, namedtuple
, 'class', 'efg ghi') # type has keyword
32 self
.assertRaises(ValueError, namedtuple
, '9abc', 'efg ghi') # type starts with digit
34 self
.assertRaises(ValueError, namedtuple
, 'abc', 'efg g%hi') # field with non-alpha char
35 self
.assertRaises(ValueError, namedtuple
, 'abc', 'abc class') # field has keyword
36 self
.assertRaises(ValueError, namedtuple
, 'abc', '8efg 9ghi') # field starts with digit
37 self
.assertRaises(ValueError, namedtuple
, 'abc', '_efg ghi') # field with leading underscore
38 self
.assertRaises(ValueError, namedtuple
, 'abc', 'efg efg ghi') # duplicate field
40 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
41 namedtuple('_', 'a b c') # Test leading underscores in a typename
43 nt
= namedtuple('nt', u
'the quick brown fox') # check unicode input
44 self
.assertNotIn("u'", repr(nt
._fields
))
45 nt
= namedtuple('nt', (u
'the', u
'quick')) # check unicode input
46 self
.assertNotIn("u'", repr(nt
._fields
))
48 self
.assertRaises(TypeError, Point
._make
, [11]) # catch too few args
49 self
.assertRaises(TypeError, Point
._make
, [11, 22, 33]) # catch too many args
51 @unittest.skipIf(sys
.flags
.optimize
>= 2,
52 "Docstrings are omitted with -O2 and above")
53 def test_factory_doc_attr(self
):
54 Point
= namedtuple('Point', 'x y')
55 self
.assertEqual(Point
.__doc
__, 'Point(x, y)')
57 def test_name_fixer(self
):
58 for spec
, renamed
in [
59 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
60 [('abc', 'class'), ('abc', '_1')], # field has keyword
61 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
62 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
63 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
64 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
66 self
.assertEqual(namedtuple('NT', spec
, rename
=True)._fields
, renamed
)
68 def test_instance(self
):
69 Point
= namedtuple('Point', 'x y')
71 self
.assertEqual(p
, Point(x
=11, y
=22))
72 self
.assertEqual(p
, Point(11, y
=22))
73 self
.assertEqual(p
, Point(y
=22, x
=11))
74 self
.assertEqual(p
, Point(*(11, 22)))
75 self
.assertEqual(p
, Point(**dict(x
=11, y
=22)))
76 self
.assertRaises(TypeError, Point
, 1) # too few args
77 self
.assertRaises(TypeError, Point
, 1, 2, 3) # too many args
78 self
.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
79 self
.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
80 self
.assertEqual(repr(p
), 'Point(x=11, y=22)')
81 self
.assertNotIn('__dict__', dir(p
)) # verify instance has no dict
82 self
.assertNotIn('__weakref__', dir(p
))
83 self
.assertEqual(p
, Point
._make
([11, 22])) # test _make classmethod
84 self
.assertEqual(p
._fields
, ('x', 'y')) # test _fields attribute
85 self
.assertEqual(p
._replace
(x
=1), (1, 22)) # test _replace method
86 self
.assertEqual(p
._asdict
(), dict(x
=11, y
=22)) # test _asdict method
89 p
._replace
(x
=1, error
=2)
93 self
._fail
('Did not detect an incorrect fieldname')
95 # verify that field string can have commas
96 Point
= namedtuple('Point', 'x, y')
98 self
.assertEqual(repr(p
), 'Point(x=11, y=22)')
100 # verify that fieldspec can be a non-string sequence
101 Point
= namedtuple('Point', ('x', 'y'))
102 p
= Point(x
=11, y
=22)
103 self
.assertEqual(repr(p
), 'Point(x=11, y=22)')
105 def test_tupleness(self
):
106 Point
= namedtuple('Point', 'x y')
109 self
.assertIsInstance(p
, tuple)
110 self
.assertEqual(p
, (11, 22)) # matches a real tuple
111 self
.assertEqual(tuple(p
), (11, 22)) # coercable to a real tuple
112 self
.assertEqual(list(p
), [11, 22]) # coercable to a list
113 self
.assertEqual(max(p
), 22) # iterable
114 self
.assertEqual(max(*p
), 22) # star-able
116 self
.assertEqual(p
, (x
, y
)) # unpacks like a tuple
117 self
.assertEqual((p
[0], p
[1]), (11, 22)) # indexable like a tuple
118 self
.assertRaises(IndexError, p
.__getitem
__, 3)
120 self
.assertEqual(p
.x
, x
)
121 self
.assertEqual(p
.y
, y
)
122 self
.assertRaises(AttributeError, eval, 'p.z', locals())
124 def test_odd_sizes(self
):
125 Zero
= namedtuple('Zero', '')
126 self
.assertEqual(Zero(), ())
127 self
.assertEqual(Zero
._make
([]), ())
128 self
.assertEqual(repr(Zero()), 'Zero()')
129 self
.assertEqual(Zero()._asdict
(), {})
130 self
.assertEqual(Zero()._fields
, ())
132 Dot
= namedtuple('Dot', 'd')
133 self
.assertEqual(Dot(1), (1,))
134 self
.assertEqual(Dot
._make
([1]), (1,))
135 self
.assertEqual(Dot(1).d
, 1)
136 self
.assertEqual(repr(Dot(1)), 'Dot(d=1)')
137 self
.assertEqual(Dot(1)._asdict
(), {'d':1})
138 self
.assertEqual(Dot(1)._replace
(d
=999), (999,))
139 self
.assertEqual(Dot(1)._fields
, ('d',))
142 import string
, random
143 names
= list(set(''.join([random
.choice(string
.ascii_letters
)
144 for j
in range(10)]) for i
in range(n
)))
146 Big
= namedtuple('Big', names
)
148 self
.assertEqual(b
, tuple(range(n
)))
149 self
.assertEqual(Big
._make
(range(n
)), tuple(range(n
)))
150 for pos
, name
in enumerate(names
):
151 self
.assertEqual(getattr(b
, name
), pos
)
152 repr(b
) # make sure repr() doesn't blow-up
154 d_expected
= dict(zip(names
, range(n
)))
155 self
.assertEqual(d
, d_expected
)
156 b2
= b
._replace
(**dict([(names
[1], 999),(names
[-5], 42)]))
157 b2_expected
= range(n
)
160 self
.assertEqual(b2
, tuple(b2_expected
))
161 self
.assertEqual(b
._fields
, tuple(names
))
163 def test_pickle(self
):
164 p
= TestNT(x
=10, y
=20, z
=30)
165 for module
in pickle
, cPickle
:
166 loads
= getattr(module
, 'loads')
167 dumps
= getattr(module
, 'dumps')
168 for protocol
in -1, 0, 1, 2:
169 q
= loads(dumps(p
, protocol
))
170 self
.assertEqual(p
, q
)
171 self
.assertEqual(p
._fields
, q
._fields
)
174 p
= TestNT(x
=10, y
=20, z
=30)
175 for copier
in copy
.copy
, copy
.deepcopy
:
177 self
.assertEqual(p
, q
)
178 self
.assertEqual(p
._fields
, q
._fields
)
180 def test_name_conflicts(self
):
181 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
182 # failed when used as field names. Test to make sure these now work.
183 T
= namedtuple('T', 'itemgetter property self cls tuple')
185 self
.assertEqual(t
, (1,2,3,4,5))
186 newt
= t
._replace
(itemgetter
=10, property=20, self
=30, cls
=40, tuple=50)
187 self
.assertEqual(newt
, (10,20,30,40,50))
189 # Broader test of all interesting names in a template
190 with test_support
.captured_stdout() as template
:
191 T
= namedtuple('T', 'x', verbose
=True)
192 words
= set(re
.findall('[A-Za-z]+', template
.getvalue()))
193 words
-= set(keyword
.kwlist
)
194 T
= namedtuple('T', words
)
196 values
= tuple(range(len(words
)))
198 self
.assertEqual(t
, values
)
199 t
= T(**dict(zip(T
._fields
, values
)))
200 self
.assertEqual(t
, values
)
203 self
.assertEqual(t
, values
)
207 self
.assertEqual(t
._asdict
(), dict(zip(T
._fields
, values
)))
210 newvalues
= tuple(v
*10 for v
in values
)
211 newt
= t
._replace
(**dict(zip(T
._fields
, newvalues
)))
212 self
.assertEqual(newt
, newvalues
)
214 self
.assertEqual(T
._fields
, tuple(words
))
215 # test __getnewargs__
216 self
.assertEqual(t
.__getnewargs
__(), values
)
218 class ABCTestCase(unittest
.TestCase
):
220 def validate_abstract_methods(self
, abc
, *names
):
221 methodstubs
= dict.fromkeys(names
, lambda s
, *args
: 0)
223 # everything should work will all required methods are present
224 C
= type('C', (abc
,), methodstubs
)
227 # instantiation should fail if a required method is missing
229 stubs
= methodstubs
.copy()
231 C
= type('C', (abc
,), stubs
)
232 self
.assertRaises(TypeError, C
, name
)
234 def validate_isinstance(self
, abc
, name
):
235 stub
= lambda s
, *args
: 0
238 C
= type('C', (object,), {name
: stub
})
239 self
.assertIsInstance(C(), abc
)
240 self
.assertTrue(issubclass(C
, abc
))
243 setattr(C
, name
, stub
)
244 self
.assertIsInstance(C(), abc
)
245 self
.assertTrue(issubclass(C
, abc
))
248 C
= type('C', (object,), {'__hash__': None})
249 self
.assertNotIsInstance(C(), abc
)
250 self
.assertFalse(issubclass(C
, abc
))
253 self
.assertNotIsInstance(C(), abc
)
254 self
.assertFalse(issubclass(C
, abc
))
256 def validate_comparison(self
, instance
):
257 ops
= ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
260 name
= '__' + op
+ '__'
261 operators
[name
] = getattr(operator
, name
)
265 self
.right_side
= False
266 def __eq__(self
, other
):
267 self
.right_side
= True
279 for name
, op
in operators
.items():
280 if not hasattr(instance
, name
):
284 self
.assertTrue(other
.right_side
,'Right side not called for %s.%s'
285 % (type(instance
), name
))
287 class TestOneTrickPonyABCs(ABCTestCase
):
289 def test_Hashable(self
):
290 # Check some non-hashables
291 non_samples
= [list(), set(), dict()]
292 for x
in non_samples
:
293 self
.assertNotIsInstance(x
, Hashable
)
294 self
.assertFalse(issubclass(type(x
), Hashable
), repr(type(x
)))
295 # Check some hashables
297 int(), float(), complex(),
299 tuple(), frozenset(),
300 int, list, object, type,
303 self
.assertIsInstance(x
, Hashable
)
304 self
.assertTrue(issubclass(type(x
), Hashable
), repr(type(x
)))
305 self
.assertRaises(TypeError, Hashable
)
306 # Check direct subclassing
309 return super(H
, self
).__hash
__()
310 __eq__
= Hashable
.__eq
__ # Silence Py3k warning
311 self
.assertEqual(hash(H()), 0)
312 self
.assertFalse(issubclass(int, H
))
313 self
.validate_abstract_methods(Hashable
, '__hash__')
314 self
.validate_isinstance(Hashable
, '__hash__')
316 def test_Iterable(self
):
317 # Check some non-iterables
318 non_samples
= [None, 42, 3.14, 1j
]
319 for x
in non_samples
:
320 self
.assertNotIsInstance(x
, Iterable
)
321 self
.assertFalse(issubclass(type(x
), Iterable
), repr(type(x
)))
322 # Check some iterables
324 tuple(), list(), set(), frozenset(), dict(),
325 dict().keys(), dict().items(), dict().values(),
330 self
.assertIsInstance(x
, Iterable
)
331 self
.assertTrue(issubclass(type(x
), Iterable
), repr(type(x
)))
332 # Check direct subclassing
335 return super(I
, self
).__iter
__()
336 self
.assertEqual(list(I()), [])
337 self
.assertFalse(issubclass(str, I
))
338 self
.validate_abstract_methods(Iterable
, '__iter__')
339 self
.validate_isinstance(Iterable
, '__iter__')
341 def test_Iterator(self
):
342 non_samples
= [None, 42, 3.14, 1j
, "".encode('ascii'), "", (), [],
344 for x
in non_samples
:
345 self
.assertNotIsInstance(x
, Iterator
)
346 self
.assertFalse(issubclass(type(x
), Iterator
), repr(type(x
)))
347 samples
= [iter(str()),
348 iter(tuple()), iter(list()), iter(dict()),
349 iter(set()), iter(frozenset()),
350 iter(dict().keys()), iter(dict().items()),
351 iter(dict().values()),
356 self
.assertIsInstance(x
, Iterator
)
357 self
.assertTrue(issubclass(type(x
), Iterator
), repr(type(x
)))
358 self
.validate_abstract_methods(Iterator
, 'next')
359 self
.validate_isinstance(Iterator
, 'next')
361 def test_Sized(self
):
362 non_samples
= [None, 42, 3.14, 1j
,
366 for x
in non_samples
:
367 self
.assertNotIsInstance(x
, Sized
)
368 self
.assertFalse(issubclass(type(x
), Sized
), repr(type(x
)))
370 tuple(), list(), set(), frozenset(), dict(),
371 dict().keys(), dict().items(), dict().values(),
374 self
.assertIsInstance(x
, Sized
)
375 self
.assertTrue(issubclass(type(x
), Sized
), repr(type(x
)))
376 self
.validate_abstract_methods(Sized
, '__len__')
377 self
.validate_isinstance(Sized
, '__len__')
379 def test_Container(self
):
380 non_samples
= [None, 42, 3.14, 1j
,
384 for x
in non_samples
:
385 self
.assertNotIsInstance(x
, Container
)
386 self
.assertFalse(issubclass(type(x
), Container
), repr(type(x
)))
388 tuple(), list(), set(), frozenset(), dict(),
389 dict().keys(), dict().items(),
392 self
.assertIsInstance(x
, Container
)
393 self
.assertTrue(issubclass(type(x
), Container
), repr(type(x
)))
394 self
.validate_abstract_methods(Container
, '__contains__')
395 self
.validate_isinstance(Container
, '__contains__')
397 def test_Callable(self
):
398 non_samples
= [None, 42, 3.14, 1j
,
399 "", "".encode('ascii'), (), [], {}, set(),
403 for x
in non_samples
:
404 self
.assertNotIsInstance(x
, Callable
)
405 self
.assertFalse(issubclass(type(x
), Callable
), repr(type(x
)))
406 samples
= [lambda: None,
409 list.append
, [].append
,
412 self
.assertIsInstance(x
, Callable
)
413 self
.assertTrue(issubclass(type(x
), Callable
), repr(type(x
)))
414 self
.validate_abstract_methods(Callable
, '__call__')
415 self
.validate_isinstance(Callable
, '__call__')
417 def test_direct_subclassing(self
):
418 for B
in Hashable
, Iterable
, Iterator
, Sized
, Container
, Callable
:
421 self
.assertTrue(issubclass(C
, B
))
422 self
.assertFalse(issubclass(int, C
))
424 def test_registration(self
):
425 for B
in Hashable
, Iterable
, Iterator
, Sized
, Container
, Callable
:
428 __hash__
= None # Make sure it isn't hashable by default
429 self
.assertFalse(issubclass(C
, B
), B
.__name
__)
431 self
.assertTrue(issubclass(C
, B
))
433 class WithSet(MutableSet
):
435 def __init__(self
, it
=()):
439 return len(self
.data
)
442 return iter(self
.data
)
444 def __contains__(self
, item
):
445 return item
in self
.data
450 def discard(self
, item
):
451 self
.data
.discard(item
)
453 class TestCollectionABCs(ABCTestCase
):
455 # XXX For now, we only test some virtual inheritance properties.
456 # We should also test the proper behavior of the collection ABCs
457 # as real base classes or mix-in classes.
460 for sample
in [set, frozenset]:
461 self
.assertIsInstance(sample(), Set
)
462 self
.assertTrue(issubclass(sample
, Set
))
463 self
.validate_abstract_methods(Set
, '__contains__', '__iter__', '__len__')
465 def __contains__(self
, x
):
471 self
.validate_comparison(MySet())
473 def test_hash_Set(self
):
474 class OneTwoThreeSet(Set
):
476 self
.contents
= [1, 2, 3]
477 def __contains__(self
, x
):
478 return x
in self
.contents
480 return len(self
.contents
)
482 return iter(self
.contents
)
485 a
, b
= OneTwoThreeSet(), OneTwoThreeSet()
486 self
.assertTrue(hash(a
) == hash(b
))
488 def test_MutableSet(self
):
489 self
.assertIsInstance(set(), MutableSet
)
490 self
.assertTrue(issubclass(set, MutableSet
))
491 self
.assertNotIsInstance(frozenset(), MutableSet
)
492 self
.assertFalse(issubclass(frozenset, MutableSet
))
493 self
.validate_abstract_methods(MutableSet
, '__contains__', '__iter__', '__len__',
496 def test_issue_5647(self
):
497 # MutableSet.__iand__ mutated the set during iteration
499 s
&= WithSet('cdef') # This used to fail
500 self
.assertEqual(set(s
), set('cd'))
502 def test_issue_4920(self
):
503 # MutableSet.pop() method did not work
504 class MySet(collections
.MutableSet
):
506 def __init__(self
,items
=None):
510 def __contains__(self
,v
):
513 return iter(self
.__s
)
517 result
=v
not in self
.__s
525 return "MySet(%s)" % repr(list(self
))
526 s
= MySet([5,43,2,1])
527 self
.assertEqual(s
.pop(), 1)
529 def test_Mapping(self
):
530 for sample
in [dict]:
531 self
.assertIsInstance(sample(), Mapping
)
532 self
.assertTrue(issubclass(sample
, Mapping
))
533 self
.validate_abstract_methods(Mapping
, '__contains__', '__iter__', '__len__',
535 class MyMapping(collections
.Mapping
):
538 def __getitem__(self
, i
):
542 self
.validate_comparison(MyMapping())
544 def test_MutableMapping(self
):
545 for sample
in [dict]:
546 self
.assertIsInstance(sample(), MutableMapping
)
547 self
.assertTrue(issubclass(sample
, MutableMapping
))
548 self
.validate_abstract_methods(MutableMapping
, '__contains__', '__iter__', '__len__',
549 '__getitem__', '__setitem__', '__delitem__')
551 def test_Sequence(self
):
552 for sample
in [tuple, list, str]:
553 self
.assertIsInstance(sample(), Sequence
)
554 self
.assertTrue(issubclass(sample
, Sequence
))
555 self
.assertTrue(issubclass(basestring
, Sequence
))
556 self
.assertIsInstance(range(10), Sequence
)
557 self
.assertTrue(issubclass(xrange, Sequence
))
558 self
.assertTrue(issubclass(str, Sequence
))
559 self
.validate_abstract_methods(Sequence
, '__contains__', '__iter__', '__len__',
562 def test_MutableSequence(self
):
563 for sample
in [tuple, str]:
564 self
.assertNotIsInstance(sample(), MutableSequence
)
565 self
.assertFalse(issubclass(sample
, MutableSequence
))
566 for sample
in [list]:
567 self
.assertIsInstance(sample(), MutableSequence
)
568 self
.assertTrue(issubclass(sample
, MutableSequence
))
569 self
.assertFalse(issubclass(basestring
, MutableSequence
))
570 self
.validate_abstract_methods(MutableSequence
, '__contains__', '__iter__',
571 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
573 class TestCounter(unittest
.TestCase
):
575 def test_basics(self
):
576 c
= Counter('abcaba')
577 self
.assertEqual(c
, Counter({'a':3 , 'b': 2, 'c': 1}))
578 self
.assertEqual(c
, Counter(a
=3, b
=2, c
=1))
579 self
.assertIsInstance(c
, dict)
580 self
.assertIsInstance(c
, Mapping
)
581 self
.assertTrue(issubclass(Counter
, dict))
582 self
.assertTrue(issubclass(Counter
, Mapping
))
583 self
.assertEqual(len(c
), 3)
584 self
.assertEqual(sum(c
.values()), 6)
585 self
.assertEqual(sorted(c
.values()), [1, 2, 3])
586 self
.assertEqual(sorted(c
.keys()), ['a', 'b', 'c'])
587 self
.assertEqual(sorted(c
), ['a', 'b', 'c'])
588 self
.assertEqual(sorted(c
.items()),
589 [('a', 3), ('b', 2), ('c', 1)])
590 self
.assertEqual(c
['b'], 2)
591 self
.assertEqual(c
['z'], 0)
592 with test_support
.check_py3k_warnings():
593 self
.assertEqual(c
.has_key('c'), True)
594 self
.assertEqual(c
.has_key('z'), False)
595 self
.assertEqual(c
.__contains
__('c'), True)
596 self
.assertEqual(c
.__contains
__('z'), False)
597 self
.assertEqual(c
.get('b', 10), 2)
598 self
.assertEqual(c
.get('z', 10), 10)
599 self
.assertEqual(c
, dict(a
=3, b
=2, c
=1))
600 self
.assertEqual(repr(c
), "Counter({'a': 3, 'b': 2, 'c': 1})")
601 self
.assertEqual(c
.most_common(), [('a', 3), ('b', 2), ('c', 1)])
603 self
.assertEqual(c
.most_common(i
),
604 [('a', 3), ('b', 2), ('c', 1)][:i
])
605 self
.assertEqual(''.join(sorted(c
.elements())), 'aaabbc')
606 c
['a'] += 1 # increment an existing value
607 c
['b'] -= 2 # sub existing value to zero
608 del c
['c'] # remove an entry
609 del c
['c'] # make sure that del doesn't raise KeyError
610 c
['d'] -= 2 # sub from a missing value
611 c
['e'] = -5 # directly assign a missing value
612 c
['f'] += 4 # add to a missing value
613 self
.assertEqual(c
, dict(a
=4, b
=0, d
=-2, e
=-5, f
=4))
614 self
.assertEqual(''.join(sorted(c
.elements())), 'aaaaffff')
615 self
.assertEqual(c
.pop('f'), 4)
616 self
.assertNotIn('f', c
)
618 elem
, cnt
= c
.popitem()
619 self
.assertNotIn(elem
, c
)
621 self
.assertEqual(c
, {})
622 self
.assertEqual(repr(c
), 'Counter()')
623 self
.assertRaises(NotImplementedError, Counter
.fromkeys
, 'abc')
624 self
.assertRaises(TypeError, hash, c
)
625 c
.update(dict(a
=5, b
=3))
627 c
.update(Counter('a' * 50 + 'b' * 30))
628 c
.update() # test case with no args
629 c
.__init
__('a' * 500 + 'b' * 300)
632 self
.assertEqual(c
, dict(a
=555, b
=333, c
=3, d
=1))
633 self
.assertEqual(c
.setdefault('d', 5), 1)
634 self
.assertEqual(c
['d'], 1)
635 self
.assertEqual(c
.setdefault('e', 5), 5)
636 self
.assertEqual(c
['e'], 5)
638 def test_copying(self
):
639 # Check that counters are copyable, deepcopyable, picklable, and
640 #have a repr/eval round-trip
641 words
= Counter('which witch had which witches wrist watch'.split())
642 update_test
= Counter()
643 update_test
.update(words
)
644 for i
, dup
in enumerate([
647 copy
.deepcopy(words
),
648 pickle
.loads(pickle
.dumps(words
, 0)),
649 pickle
.loads(pickle
.dumps(words
, 1)),
650 pickle
.loads(pickle
.dumps(words
, 2)),
651 pickle
.loads(pickle
.dumps(words
, -1)),
652 cPickle
.loads(cPickle
.dumps(words
, 0)),
653 cPickle
.loads(cPickle
.dumps(words
, 1)),
654 cPickle
.loads(cPickle
.dumps(words
, 2)),
655 cPickle
.loads(cPickle
.dumps(words
, -1)),
660 msg
= (i
, dup
, words
)
661 self
.assertTrue(dup
is not words
)
662 self
.assertEquals(dup
, words
)
663 self
.assertEquals(len(dup
), len(words
))
664 self
.assertEquals(type(dup
), type(words
))
666 def test_conversions(self
):
667 # Convert to: set, list, dict
668 s
= 'she sells sea shells by the sea shore'
669 self
.assertEqual(sorted(Counter(s
).elements()), sorted(s
))
670 self
.assertEqual(sorted(Counter(s
)), sorted(set(s
)))
671 self
.assertEqual(dict(Counter(s
)), dict(Counter(s
).items()))
672 self
.assertEqual(set(Counter(s
)), set(s
))
674 def test_invariant_for_the_in_operator(self
):
675 c
= Counter(a
=10, b
=-2, c
=0)
677 self
.assertTrue(elem
in c
)
678 self
.assertIn(elem
, c
)
680 def test_multiset_operations(self
):
681 # Verify that adding a zero counter will strip zeros and negatives
682 c
= Counter(a
=10, b
=-2, c
=0) + Counter()
683 self
.assertEqual(dict(c
), dict(a
=10))
686 for i
in range(1000):
687 # test random pairs of multisets
688 p
= Counter(dict((elem
, randrange(-2,4)) for elem
in elements
))
689 p
.update(e
=1, f
=-1, g
=0)
690 q
= Counter(dict((elem
, randrange(-2,4)) for elem
in elements
))
691 q
.update(h
=1, i
=-1, j
=0)
692 for counterop
, numberop
in [
693 (Counter
.__add
__, lambda x
, y
: max(0, x
+y
)),
694 (Counter
.__sub
__, lambda x
, y
: max(0, x
-y
)),
695 (Counter
.__or
__, lambda x
, y
: max(0,x
,y
)),
696 (Counter
.__and
__, lambda x
, y
: max(0, min(x
,y
))),
698 result
= counterop(p
, q
)
700 self
.assertEqual(numberop(p
[x
], q
[x
]), result
[x
],
701 (counterop
, x
, p
, q
))
702 # verify that results exclude non-positive counts
703 self
.assertTrue(x
>0 for x
in result
.values())
707 # verify that random multisets with no repeats are exactly like sets
708 p
= Counter(dict((elem
, randrange(0, 2)) for elem
in elements
))
709 q
= Counter(dict((elem
, randrange(0, 2)) for elem
in elements
))
710 for counterop
, setop
in [
711 (Counter
.__sub
__, set.__sub
__),
712 (Counter
.__or
__, set.__or
__),
713 (Counter
.__and
__, set.__and
__),
715 counter_result
= counterop(p
, q
)
716 set_result
= setop(set(p
.elements()), set(q
.elements()))
717 self
.assertEqual(counter_result
, dict.fromkeys(set_result
, 1))
719 def test_subtract(self
):
720 c
= Counter(a
=-5, b
=0, c
=5, d
=10, e
=15,g
=40)
721 c
.subtract(a
=1, b
=2, c
=-3, d
=10, e
=20, f
=30, h
=-50)
722 self
.assertEqual(c
, Counter(a
=-6, b
=-2, c
=8, d
=0, e
=-5, f
=-30, g
=40, h
=50))
723 c
= Counter(a
=-5, b
=0, c
=5, d
=10, e
=15,g
=40)
724 c
.subtract(Counter(a
=1, b
=2, c
=-3, d
=10, e
=20, f
=30, h
=-50))
725 self
.assertEqual(c
, Counter(a
=-6, b
=-2, c
=8, d
=0, e
=-5, f
=-30, g
=40, h
=50))
726 c
= Counter('aaabbcd')
727 c
.subtract('aaaabbcce')
728 self
.assertEqual(c
, Counter(a
=-1, b
=0, c
=-1, d
=1, e
=-1))
730 class TestOrderedDict(unittest
.TestCase
):
733 with self
.assertRaises(TypeError):
734 OrderedDict([('a', 1), ('b', 2)], None) # too many args
735 pairs
= [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
736 self
.assertEqual(sorted(OrderedDict(dict(pairs
)).items()), pairs
) # dict input
737 self
.assertEqual(sorted(OrderedDict(**dict(pairs
)).items()), pairs
) # kwds input
738 self
.assertEqual(list(OrderedDict(pairs
).items()), pairs
) # pairs input
739 self
.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
740 c
=3, e
=5).items()), pairs
) # mixed input
742 # make sure no positional args conflict with possible kwdargs
743 self
.assertEqual(inspect
.getargspec(OrderedDict
.__dict
__['__init__']).args
,
746 # Make sure that direct calls to __init__ do not clear previous contents
747 d
= OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
748 d
.__init
__([('e', 5), ('f', 6)], g
=7, d
=4)
749 self
.assertEqual(list(d
.items()),
750 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
752 def test_update(self
):
753 with self
.assertRaises(TypeError):
754 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
755 pairs
= [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
757 od
.update(dict(pairs
))
758 self
.assertEqual(sorted(od
.items()), pairs
) # dict input
760 od
.update(**dict(pairs
))
761 self
.assertEqual(sorted(od
.items()), pairs
) # kwds input
764 self
.assertEqual(list(od
.items()), pairs
) # pairs input
766 od
.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c
=3, e
=5)
767 self
.assertEqual(list(od
.items()), pairs
) # mixed input
769 # Make sure that direct calls to update do not clear previous contents
770 # add that updates items are not moved to the end
771 d
= OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
772 d
.update([('e', 5), ('f', 6)], g
=7, d
=4)
773 self
.assertEqual(list(d
.items()),
774 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
776 def test_clear(self
):
777 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
779 od
= OrderedDict(pairs
)
780 self
.assertEqual(len(od
), len(pairs
))
782 self
.assertEqual(len(od
), 0)
784 def test_delitem(self
):
785 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
786 od
= OrderedDict(pairs
)
788 self
.assertNotIn('a', od
)
789 with self
.assertRaises(KeyError):
791 self
.assertEqual(list(od
.items()), pairs
[:2] + pairs
[3:])
793 def test_setitem(self
):
794 od
= OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
795 od
['c'] = 10 # existing element
796 od
['f'] = 20 # new element
797 self
.assertEqual(list(od
.items()),
798 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
800 def test_iterators(self
):
801 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
803 od
= OrderedDict(pairs
)
804 self
.assertEqual(list(od
), [t
[0] for t
in pairs
])
805 self
.assertEqual(od
.keys()[:], [t
[0] for t
in pairs
])
806 self
.assertEqual(od
.values()[:], [t
[1] for t
in pairs
])
807 self
.assertEqual(od
.items()[:], pairs
)
808 self
.assertEqual(list(od
.iterkeys()), [t
[0] for t
in pairs
])
809 self
.assertEqual(list(od
.itervalues()), [t
[1] for t
in pairs
])
810 self
.assertEqual(list(od
.iteritems()), pairs
)
811 self
.assertEqual(list(reversed(od
)),
812 [t
[0] for t
in reversed(pairs
)])
814 def test_popitem(self
):
815 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
817 od
= OrderedDict(pairs
)
819 self
.assertEqual(od
.popitem(), pairs
.pop())
820 with self
.assertRaises(KeyError):
822 self
.assertEqual(len(od
), 0)
825 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
827 od
= OrderedDict(pairs
)
831 self
.assertEqual(od
.pop(k
), v
)
832 with self
.assertRaises(KeyError):
834 self
.assertEqual(len(od
), 0)
835 self
.assertEqual(od
.pop(k
, 12345), 12345)
837 def test_equality(self
):
838 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
840 od1
= OrderedDict(pairs
)
841 od2
= OrderedDict(pairs
)
842 self
.assertEqual(od1
, od2
) # same order implies equality
843 pairs
= pairs
[2:] + pairs
[:2]
844 od2
= OrderedDict(pairs
)
845 self
.assertNotEqual(od1
, od2
) # different order implies inequality
846 # comparison to regular dict is not order sensitive
847 self
.assertEqual(od1
, dict(od2
))
848 self
.assertEqual(dict(od2
), od1
)
849 # different length implied inequality
850 self
.assertNotEqual(od1
, OrderedDict(pairs
[:-1]))
852 def test_copying(self
):
853 # Check that ordered dicts are copyable, deepcopyable, picklable,
854 # and have a repr/eval round-trip
855 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
856 od
= OrderedDict(pairs
)
857 update_test
= OrderedDict()
858 update_test
.update(od
)
859 for i
, dup
in enumerate([
863 pickle
.loads(pickle
.dumps(od
, 0)),
864 pickle
.loads(pickle
.dumps(od
, 1)),
865 pickle
.loads(pickle
.dumps(od
, 2)),
866 pickle
.loads(pickle
.dumps(od
, -1)),
871 self
.assertTrue(dup
is not od
)
872 self
.assertEquals(dup
, od
)
873 self
.assertEquals(list(dup
.items()), list(od
.items()))
874 self
.assertEquals(len(dup
), len(od
))
875 self
.assertEquals(type(dup
), type(od
))
877 def test_yaml_linkage(self
):
878 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
879 # In yaml, lists are native but tuples are not.
880 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
881 od
= OrderedDict(pairs
)
883 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
884 self
.assertTrue(all(type(pair
)==list for pair
in od
.__reduce
__()[1]))
886 def test_reduce_not_too_fat(self
):
887 # do not save instance dictionary if not needed
888 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
889 od
= OrderedDict(pairs
)
890 self
.assertEqual(len(od
.__reduce
__()), 2)
892 self
.assertEqual(len(od
.__reduce
__()), 3)
895 od
= OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
896 self
.assertEqual(repr(od
),
897 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
898 self
.assertEqual(eval(repr(od
)), od
)
899 self
.assertEqual(repr(OrderedDict()), "OrderedDict()")
901 def test_setdefault(self
):
902 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
904 od
= OrderedDict(pairs
)
905 pair_order
= list(od
.items())
906 self
.assertEqual(od
.setdefault('a', 10), 3)
907 # make sure order didn't change
908 self
.assertEqual(list(od
.items()), pair_order
)
909 self
.assertEqual(od
.setdefault('x', 10), 10)
910 # make sure 'x' is added to the end
911 self
.assertEqual(list(od
.items())[-1], ('x', 10))
913 def test_reinsert(self
):
914 # Given insert a, insert b, delete a, re-insert a,
915 # verify that a is now later than b.
921 self
.assertEqual(list(od
.items()), [('b', 2), ('a', 1)])
925 class GeneralMappingTests(mapping_tests
.BasicTestMappingProtocol
):
926 type2test
= OrderedDict
928 def test_popitem(self
):
929 d
= self
._empty
_mapping
()
930 self
.assertRaises(KeyError, d
.popitem
)
932 class MyOrderedDict(OrderedDict
):
935 class SubclassMappingTests(mapping_tests
.BasicTestMappingProtocol
):
936 type2test
= MyOrderedDict
938 def test_popitem(self
):
939 d
= self
._empty
_mapping
()
940 self
.assertRaises(KeyError, d
.popitem
)
944 def test_main(verbose
=None):
945 NamedTupleDocs
= doctest
.DocTestSuite(module
=collections
)
946 test_classes
= [TestNamedTuple
, NamedTupleDocs
, TestOneTrickPonyABCs
,
947 TestCollectionABCs
, TestCounter
,
948 TestOrderedDict
, GeneralMappingTests
, SubclassMappingTests
]
949 test_support
.run_unittest(*test_classes
)
950 test_support
.run_doctest(collections
, verbose
)
952 if __name__
== "__main__":
953 test_main(verbose
=True)