2 import unittest
, doctest
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
.__doc
__, 'Point(x, y)')
26 self
.assertEqual(Point
.__slots
__, ())
27 self
.assertEqual(Point
.__module
__, __name__
)
28 self
.assertEqual(Point
.__getitem
__, tuple.__getitem
__)
29 self
.assertEqual(Point
._fields
, ('x', 'y'))
31 self
.assertRaises(ValueError, namedtuple
, 'abc%', 'efg ghi') # type has non-alpha char
32 self
.assertRaises(ValueError, namedtuple
, 'class', 'efg ghi') # type has keyword
33 self
.assertRaises(ValueError, namedtuple
, '9abc', 'efg ghi') # type starts with digit
35 self
.assertRaises(ValueError, namedtuple
, 'abc', 'efg g%hi') # field with non-alpha char
36 self
.assertRaises(ValueError, namedtuple
, 'abc', 'abc class') # field has keyword
37 self
.assertRaises(ValueError, namedtuple
, 'abc', '8efg 9ghi') # field starts with digit
38 self
.assertRaises(ValueError, namedtuple
, 'abc', '_efg ghi') # field with leading underscore
39 self
.assertRaises(ValueError, namedtuple
, 'abc', 'efg efg ghi') # duplicate field
41 namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
42 namedtuple('_', 'a b c') # Test leading underscores in a typename
44 nt
= namedtuple('nt', u
'the quick brown fox') # check unicode input
45 self
.assertTrue("u'" not in repr(nt
._fields
))
46 nt
= namedtuple('nt', (u
'the', u
'quick')) # check unicode input
47 self
.assertTrue("u'" not in repr(nt
._fields
))
49 self
.assertRaises(TypeError, Point
._make
, [11]) # catch too few args
50 self
.assertRaises(TypeError, Point
._make
, [11, 22, 33]) # catch too many args
52 def test_name_fixer(self
):
53 for spec
, renamed
in [
54 [('efg', 'g%hi'), ('efg', '_1')], # field with non-alpha char
55 [('abc', 'class'), ('abc', '_1')], # field has keyword
56 [('8efg', '9ghi'), ('_0', '_1')], # field starts with digit
57 [('abc', '_efg'), ('abc', '_1')], # field with leading underscore
58 [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')], # duplicate field
59 [('abc', '', 'x'), ('abc', '_1', 'x')], # fieldname is a space
61 self
.assertEqual(namedtuple('NT', spec
, rename
=True)._fields
, renamed
)
63 def test_instance(self
):
64 Point
= namedtuple('Point', 'x y')
66 self
.assertEqual(p
, Point(x
=11, y
=22))
67 self
.assertEqual(p
, Point(11, y
=22))
68 self
.assertEqual(p
, Point(y
=22, x
=11))
69 self
.assertEqual(p
, Point(*(11, 22)))
70 self
.assertEqual(p
, Point(**dict(x
=11, y
=22)))
71 self
.assertRaises(TypeError, Point
, 1) # too few args
72 self
.assertRaises(TypeError, Point
, 1, 2, 3) # too many args
73 self
.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals()) # wrong keyword argument
74 self
.assertRaises(TypeError, eval, 'Point(x=1)', locals()) # missing keyword argument
75 self
.assertEqual(repr(p
), 'Point(x=11, y=22)')
76 self
.assertTrue('__dict__' not in dir(p
)) # verify instance has no dict
77 self
.assertTrue('__weakref__' not in dir(p
))
78 self
.assertEqual(p
, Point
._make
([11, 22])) # test _make classmethod
79 self
.assertEqual(p
._fields
, ('x', 'y')) # test _fields attribute
80 self
.assertEqual(p
._replace
(x
=1), (1, 22)) # test _replace method
81 self
.assertEqual(p
._asdict
(), dict(x
=11, y
=22)) # test _asdict method
84 p
._replace
(x
=1, error
=2)
88 self
._fail
('Did not detect an incorrect fieldname')
90 # verify that field string can have commas
91 Point
= namedtuple('Point', 'x, y')
93 self
.assertEqual(repr(p
), 'Point(x=11, y=22)')
95 # verify that fieldspec can be a non-string sequence
96 Point
= namedtuple('Point', ('x', 'y'))
98 self
.assertEqual(repr(p
), 'Point(x=11, y=22)')
100 def test_tupleness(self
):
101 Point
= namedtuple('Point', 'x y')
104 self
.assertTrue(isinstance(p
, tuple))
105 self
.assertEqual(p
, (11, 22)) # matches a real tuple
106 self
.assertEqual(tuple(p
), (11, 22)) # coercable to a real tuple
107 self
.assertEqual(list(p
), [11, 22]) # coercable to a list
108 self
.assertEqual(max(p
), 22) # iterable
109 self
.assertEqual(max(*p
), 22) # star-able
111 self
.assertEqual(p
, (x
, y
)) # unpacks like a tuple
112 self
.assertEqual((p
[0], p
[1]), (11, 22)) # indexable like a tuple
113 self
.assertRaises(IndexError, p
.__getitem
__, 3)
115 self
.assertEqual(p
.x
, x
)
116 self
.assertEqual(p
.y
, y
)
117 self
.assertRaises(AttributeError, eval, 'p.z', locals())
119 def test_odd_sizes(self
):
120 Zero
= namedtuple('Zero', '')
121 self
.assertEqual(Zero(), ())
122 self
.assertEqual(Zero
._make
([]), ())
123 self
.assertEqual(repr(Zero()), 'Zero()')
124 self
.assertEqual(Zero()._asdict
(), {})
125 self
.assertEqual(Zero()._fields
, ())
127 Dot
= namedtuple('Dot', 'd')
128 self
.assertEqual(Dot(1), (1,))
129 self
.assertEqual(Dot
._make
([1]), (1,))
130 self
.assertEqual(Dot(1).d
, 1)
131 self
.assertEqual(repr(Dot(1)), 'Dot(d=1)')
132 self
.assertEqual(Dot(1)._asdict
(), {'d':1})
133 self
.assertEqual(Dot(1)._replace
(d
=999), (999,))
134 self
.assertEqual(Dot(1)._fields
, ('d',))
137 import string
, random
138 names
= list(set(''.join([random
.choice(string
.ascii_letters
)
139 for j
in range(10)]) for i
in range(n
)))
141 Big
= namedtuple('Big', names
)
143 self
.assertEqual(b
, tuple(range(n
)))
144 self
.assertEqual(Big
._make
(range(n
)), tuple(range(n
)))
145 for pos
, name
in enumerate(names
):
146 self
.assertEqual(getattr(b
, name
), pos
)
147 repr(b
) # make sure repr() doesn't blow-up
149 d_expected
= dict(zip(names
, range(n
)))
150 self
.assertEqual(d
, d_expected
)
151 b2
= b
._replace
(**dict([(names
[1], 999),(names
[-5], 42)]))
152 b2_expected
= range(n
)
155 self
.assertEqual(b2
, tuple(b2_expected
))
156 self
.assertEqual(b
._fields
, tuple(names
))
158 def test_pickle(self
):
159 p
= TestNT(x
=10, y
=20, z
=30)
160 for module
in pickle
, cPickle
:
161 loads
= getattr(module
, 'loads')
162 dumps
= getattr(module
, 'dumps')
163 for protocol
in -1, 0, 1, 2:
164 q
= loads(dumps(p
, protocol
))
165 self
.assertEqual(p
, q
)
166 self
.assertEqual(p
._fields
, q
._fields
)
169 p
= TestNT(x
=10, y
=20, z
=30)
170 for copier
in copy
.copy
, copy
.deepcopy
:
172 self
.assertEqual(p
, q
)
173 self
.assertEqual(p
._fields
, q
._fields
)
175 def test_name_conflicts(self
):
176 # Some names like "self", "cls", "tuple", "itemgetter", and "property"
177 # failed when used as field names. Test to make sure these now work.
178 T
= namedtuple('T', 'itemgetter property self cls tuple')
180 self
.assertEqual(t
, (1,2,3,4,5))
181 newt
= t
._replace
(itemgetter
=10, property=20, self
=30, cls
=40, tuple=50)
182 self
.assertEqual(newt
, (10,20,30,40,50))
184 # Broader test of all interesting names in a template
185 with test_support
.captured_stdout() as template
:
186 T
= namedtuple('T', 'x', verbose
=True)
187 words
= set(re
.findall('[A-Za-z]+', template
.getvalue()))
188 words
-= set(keyword
.kwlist
)
189 T
= namedtuple('T', words
)
191 values
= tuple(range(len(words
)))
193 self
.assertEqual(t
, values
)
194 t
= T(**dict(zip(T
._fields
, values
)))
195 self
.assertEqual(t
, values
)
198 self
.assertEqual(t
, values
)
202 self
.assertEqual(t
._asdict
(), dict(zip(T
._fields
, values
)))
205 newvalues
= tuple(v
*10 for v
in values
)
206 newt
= t
._replace
(**dict(zip(T
._fields
, newvalues
)))
207 self
.assertEqual(newt
, newvalues
)
209 self
.assertEqual(T
._fields
, tuple(words
))
210 # test __getnewargs__
211 self
.assertEqual(t
.__getnewargs
__(), values
)
213 class ABCTestCase(unittest
.TestCase
):
215 def validate_abstract_methods(self
, abc
, *names
):
216 methodstubs
= dict.fromkeys(names
, lambda s
, *args
: 0)
218 # everything should work will all required methods are present
219 C
= type('C', (abc
,), methodstubs
)
222 # instantiation should fail if a required method is missing
224 stubs
= methodstubs
.copy()
226 C
= type('C', (abc
,), stubs
)
227 self
.assertRaises(TypeError, C
, name
)
230 class TestOneTrickPonyABCs(ABCTestCase
):
232 def test_Hashable(self
):
233 # Check some non-hashables
234 non_samples
= [list(), set(), dict()]
235 for x
in non_samples
:
236 self
.assertFalse(isinstance(x
, Hashable
), repr(x
))
237 self
.assertFalse(issubclass(type(x
), Hashable
), repr(type(x
)))
238 # Check some hashables
240 int(), float(), complex(),
242 tuple(), frozenset(),
243 int, list, object, type,
246 self
.assertTrue(isinstance(x
, Hashable
), repr(x
))
247 self
.assertTrue(issubclass(type(x
), Hashable
), repr(type(x
)))
248 self
.assertRaises(TypeError, Hashable
)
249 # Check direct subclassing
252 return super(H
, self
).__hash
__()
253 __eq__
= Hashable
.__eq
__ # Silence Py3k warning
254 self
.assertEqual(hash(H()), 0)
255 self
.assertFalse(issubclass(int, H
))
256 self
.validate_abstract_methods(Hashable
, '__hash__')
258 def test_Iterable(self
):
259 # Check some non-iterables
260 non_samples
= [None, 42, 3.14, 1j
]
261 for x
in non_samples
:
262 self
.assertFalse(isinstance(x
, Iterable
), repr(x
))
263 self
.assertFalse(issubclass(type(x
), Iterable
), repr(type(x
)))
264 # Check some iterables
266 tuple(), list(), set(), frozenset(), dict(),
267 dict().keys(), dict().items(), dict().values(),
272 self
.assertTrue(isinstance(x
, Iterable
), repr(x
))
273 self
.assertTrue(issubclass(type(x
), Iterable
), repr(type(x
)))
274 # Check direct subclassing
277 return super(I
, self
).__iter
__()
278 self
.assertEqual(list(I()), [])
279 self
.assertFalse(issubclass(str, I
))
280 self
.validate_abstract_methods(Iterable
, '__iter__')
282 def test_Iterator(self
):
283 non_samples
= [None, 42, 3.14, 1j
, "".encode('ascii'), "", (), [],
285 for x
in non_samples
:
286 self
.assertFalse(isinstance(x
, Iterator
), repr(x
))
287 self
.assertFalse(issubclass(type(x
), Iterator
), repr(type(x
)))
288 samples
= [iter(str()),
289 iter(tuple()), iter(list()), iter(dict()),
290 iter(set()), iter(frozenset()),
291 iter(dict().keys()), iter(dict().items()),
292 iter(dict().values()),
297 self
.assertTrue(isinstance(x
, Iterator
), repr(x
))
298 self
.assertTrue(issubclass(type(x
), Iterator
), repr(type(x
)))
299 self
.validate_abstract_methods(Iterator
, 'next')
301 def test_Sized(self
):
302 non_samples
= [None, 42, 3.14, 1j
,
306 for x
in non_samples
:
307 self
.assertFalse(isinstance(x
, Sized
), repr(x
))
308 self
.assertFalse(issubclass(type(x
), Sized
), repr(type(x
)))
310 tuple(), list(), set(), frozenset(), dict(),
311 dict().keys(), dict().items(), dict().values(),
314 self
.assertTrue(isinstance(x
, Sized
), repr(x
))
315 self
.assertTrue(issubclass(type(x
), Sized
), repr(type(x
)))
316 self
.validate_abstract_methods(Sized
, '__len__')
318 def test_Container(self
):
319 non_samples
= [None, 42, 3.14, 1j
,
323 for x
in non_samples
:
324 self
.assertFalse(isinstance(x
, Container
), repr(x
))
325 self
.assertFalse(issubclass(type(x
), Container
), repr(type(x
)))
327 tuple(), list(), set(), frozenset(), dict(),
328 dict().keys(), dict().items(),
331 self
.assertTrue(isinstance(x
, Container
), repr(x
))
332 self
.assertTrue(issubclass(type(x
), Container
), repr(type(x
)))
333 self
.validate_abstract_methods(Container
, '__contains__')
335 def test_Callable(self
):
336 non_samples
= [None, 42, 3.14, 1j
,
337 "", "".encode('ascii'), (), [], {}, set(),
341 for x
in non_samples
:
342 self
.assertFalse(isinstance(x
, Callable
), repr(x
))
343 self
.assertFalse(issubclass(type(x
), Callable
), repr(type(x
)))
344 samples
= [lambda: None,
347 list.append
, [].append
,
350 self
.assertTrue(isinstance(x
, Callable
), repr(x
))
351 self
.assertTrue(issubclass(type(x
), Callable
), repr(type(x
)))
352 self
.validate_abstract_methods(Callable
, '__call__')
354 def test_direct_subclassing(self
):
355 for B
in Hashable
, Iterable
, Iterator
, Sized
, Container
, Callable
:
358 self
.assertTrue(issubclass(C
, B
))
359 self
.assertFalse(issubclass(int, C
))
361 def test_registration(self
):
362 for B
in Hashable
, Iterable
, Iterator
, Sized
, Container
, Callable
:
365 __hash__
= None # Make sure it isn't hashable by default
366 self
.assertFalse(issubclass(C
, B
), B
.__name
__)
368 self
.assertTrue(issubclass(C
, B
))
370 class WithSet(MutableSet
):
372 def __init__(self
, it
=()):
376 return len(self
.data
)
379 return iter(self
.data
)
381 def __contains__(self
, item
):
382 return item
in self
.data
387 def discard(self
, item
):
388 self
.data
.discard(item
)
390 class TestCollectionABCs(ABCTestCase
):
392 # XXX For now, we only test some virtual inheritance properties.
393 # We should also test the proper behavior of the collection ABCs
394 # as real base classes or mix-in classes.
397 for sample
in [set, frozenset]:
398 self
.assertTrue(isinstance(sample(), Set
))
399 self
.assertTrue(issubclass(sample
, Set
))
400 self
.validate_abstract_methods(Set
, '__contains__', '__iter__', '__len__')
402 def test_hash_Set(self
):
403 class OneTwoThreeSet(Set
):
405 self
.contents
= [1, 2, 3]
406 def __contains__(self
, x
):
407 return x
in self
.contents
409 return len(self
.contents
)
411 return iter(self
.contents
)
414 a
, b
= OneTwoThreeSet(), OneTwoThreeSet()
415 self
.assertTrue(hash(a
) == hash(b
))
417 def test_MutableSet(self
):
418 self
.assertTrue(isinstance(set(), MutableSet
))
419 self
.assertTrue(issubclass(set, MutableSet
))
420 self
.assertFalse(isinstance(frozenset(), MutableSet
))
421 self
.assertFalse(issubclass(frozenset, MutableSet
))
422 self
.validate_abstract_methods(MutableSet
, '__contains__', '__iter__', '__len__',
425 def test_issue_5647(self
):
426 # MutableSet.__iand__ mutated the set during iteration
428 s
&= WithSet('cdef') # This used to fail
429 self
.assertEqual(set(s
), set('cd'))
431 def test_issue_4920(self
):
432 # MutableSet.pop() method did not work
433 class MySet(collections
.MutableSet
):
435 def __init__(self
,items
=None):
439 def __contains__(self
,v
):
442 return iter(self
.__s
)
446 result
=v
not in self
.__s
454 return "MySet(%s)" % repr(list(self
))
455 s
= MySet([5,43,2,1])
456 self
.assertEqual(s
.pop(), 1)
458 def test_Mapping(self
):
459 for sample
in [dict]:
460 self
.assertTrue(isinstance(sample(), Mapping
))
461 self
.assertTrue(issubclass(sample
, Mapping
))
462 self
.validate_abstract_methods(Mapping
, '__contains__', '__iter__', '__len__',
465 def test_MutableMapping(self
):
466 for sample
in [dict]:
467 self
.assertTrue(isinstance(sample(), MutableMapping
))
468 self
.assertTrue(issubclass(sample
, MutableMapping
))
469 self
.validate_abstract_methods(MutableMapping
, '__contains__', '__iter__', '__len__',
470 '__getitem__', '__setitem__', '__delitem__')
472 def test_Sequence(self
):
473 for sample
in [tuple, list, str]:
474 self
.assertTrue(isinstance(sample(), Sequence
))
475 self
.assertTrue(issubclass(sample
, Sequence
))
476 self
.assertTrue(issubclass(basestring
, Sequence
))
477 self
.assertTrue(isinstance(range(10), Sequence
))
478 self
.assertTrue(issubclass(xrange, Sequence
))
479 self
.assertTrue(issubclass(str, Sequence
))
480 self
.validate_abstract_methods(Sequence
, '__contains__', '__iter__', '__len__',
483 def test_MutableSequence(self
):
484 for sample
in [tuple, str]:
485 self
.assertFalse(isinstance(sample(), MutableSequence
))
486 self
.assertFalse(issubclass(sample
, MutableSequence
))
487 for sample
in [list]:
488 self
.assertTrue(isinstance(sample(), MutableSequence
))
489 self
.assertTrue(issubclass(sample
, MutableSequence
))
490 self
.assertFalse(issubclass(basestring
, MutableSequence
))
491 self
.validate_abstract_methods(MutableSequence
, '__contains__', '__iter__',
492 '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
494 class TestCounter(unittest
.TestCase
):
496 def test_basics(self
):
497 c
= Counter('abcaba')
498 self
.assertEqual(c
, Counter({'a':3 , 'b': 2, 'c': 1}))
499 self
.assertEqual(c
, Counter(a
=3, b
=2, c
=1))
500 self
.assertTrue(isinstance(c
, dict))
501 self
.assertTrue(isinstance(c
, Mapping
))
502 self
.assertTrue(issubclass(Counter
, dict))
503 self
.assertTrue(issubclass(Counter
, Mapping
))
504 self
.assertEqual(len(c
), 3)
505 self
.assertEqual(sum(c
.values()), 6)
506 self
.assertEqual(sorted(c
.values()), [1, 2, 3])
507 self
.assertEqual(sorted(c
.keys()), ['a', 'b', 'c'])
508 self
.assertEqual(sorted(c
), ['a', 'b', 'c'])
509 self
.assertEqual(sorted(c
.items()),
510 [('a', 3), ('b', 2), ('c', 1)])
511 self
.assertEqual(c
['b'], 2)
512 self
.assertEqual(c
['z'], 0)
513 self
.assertEqual(c
.has_key('c'), True)
514 self
.assertEqual(c
.has_key('z'), False)
515 self
.assertEqual(c
.__contains
__('c'), True)
516 self
.assertEqual(c
.__contains
__('z'), False)
517 self
.assertEqual(c
.get('b', 10), 2)
518 self
.assertEqual(c
.get('z', 10), 10)
519 self
.assertEqual(c
, dict(a
=3, b
=2, c
=1))
520 self
.assertEqual(repr(c
), "Counter({'a': 3, 'b': 2, 'c': 1})")
521 self
.assertEqual(c
.most_common(), [('a', 3), ('b', 2), ('c', 1)])
523 self
.assertEqual(c
.most_common(i
),
524 [('a', 3), ('b', 2), ('c', 1)][:i
])
525 self
.assertEqual(''.join(sorted(c
.elements())), 'aaabbc')
526 c
['a'] += 1 # increment an existing value
527 c
['b'] -= 2 # sub existing value to zero
528 del c
['c'] # remove an entry
529 del c
['c'] # make sure that del doesn't raise KeyError
530 c
['d'] -= 2 # sub from a missing value
531 c
['e'] = -5 # directly assign a missing value
532 c
['f'] += 4 # add to a missing value
533 self
.assertEqual(c
, dict(a
=4, b
=0, d
=-2, e
=-5, f
=4))
534 self
.assertEqual(''.join(sorted(c
.elements())), 'aaaaffff')
535 self
.assertEqual(c
.pop('f'), 4)
536 self
.assertEqual('f' in c
, False)
538 elem
, cnt
= c
.popitem()
539 self
.assertEqual(elem
in c
, False)
541 self
.assertEqual(c
, {})
542 self
.assertEqual(repr(c
), 'Counter()')
543 self
.assertRaises(NotImplementedError, Counter
.fromkeys
, 'abc')
544 self
.assertRaises(TypeError, hash, c
)
545 c
.update(dict(a
=5, b
=3))
547 c
.update(Counter('a' * 50 + 'b' * 30))
548 c
.update() # test case with no args
549 c
.__init
__('a' * 500 + 'b' * 300)
552 self
.assertEqual(c
, dict(a
=555, b
=333, c
=3, d
=1))
553 self
.assertEqual(c
.setdefault('d', 5), 1)
554 self
.assertEqual(c
['d'], 1)
555 self
.assertEqual(c
.setdefault('e', 5), 5)
556 self
.assertEqual(c
['e'], 5)
558 def test_copying(self
):
559 # Check that counters are copyable, deepcopyable, picklable, and
560 #have a repr/eval round-trip
561 words
= Counter('which witch had which witches wrist watch'.split())
562 update_test
= Counter()
563 update_test
.update(words
)
564 for i
, dup
in enumerate([
567 copy
.deepcopy(words
),
568 pickle
.loads(pickle
.dumps(words
, 0)),
569 pickle
.loads(pickle
.dumps(words
, 1)),
570 pickle
.loads(pickle
.dumps(words
, 2)),
571 pickle
.loads(pickle
.dumps(words
, -1)),
572 cPickle
.loads(cPickle
.dumps(words
, 0)),
573 cPickle
.loads(cPickle
.dumps(words
, 1)),
574 cPickle
.loads(cPickle
.dumps(words
, 2)),
575 cPickle
.loads(cPickle
.dumps(words
, -1)),
580 msg
= (i
, dup
, words
)
581 self
.assertTrue(dup
is not words
)
582 self
.assertEquals(dup
, words
)
583 self
.assertEquals(len(dup
), len(words
))
584 self
.assertEquals(type(dup
), type(words
))
586 def test_conversions(self
):
587 # Convert to: set, list, dict
588 s
= 'she sells sea shells by the sea shore'
589 self
.assertEqual(sorted(Counter(s
).elements()), sorted(s
))
590 self
.assertEqual(sorted(Counter(s
)), sorted(set(s
)))
591 self
.assertEqual(dict(Counter(s
)), dict(Counter(s
).items()))
592 self
.assertEqual(set(Counter(s
)), set(s
))
594 def test_invariant_for_the_in_operator(self
):
595 c
= Counter(a
=10, b
=-2, c
=0)
597 self
.assertTrue(elem
in c
)
599 def test_multiset_operations(self
):
600 # Verify that adding a zero counter will strip zeros and negatives
601 c
= Counter(a
=10, b
=-2, c
=0) + Counter()
602 self
.assertEqual(dict(c
), dict(a
=10))
605 for i
in range(1000):
606 # test random pairs of multisets
607 p
= Counter(dict((elem
, randrange(-2,4)) for elem
in elements
))
608 p
.update(e
=1, f
=-1, g
=0)
609 q
= Counter(dict((elem
, randrange(-2,4)) for elem
in elements
))
610 q
.update(h
=1, i
=-1, j
=0)
611 for counterop
, numberop
in [
612 (Counter
.__add
__, lambda x
, y
: max(0, x
+y
)),
613 (Counter
.__sub
__, lambda x
, y
: max(0, x
-y
)),
614 (Counter
.__or
__, lambda x
, y
: max(0,x
,y
)),
615 (Counter
.__and
__, lambda x
, y
: max(0, min(x
,y
))),
617 result
= counterop(p
, q
)
619 self
.assertEqual(numberop(p
[x
], q
[x
]), result
[x
],
620 (counterop
, x
, p
, q
))
621 # verify that results exclude non-positive counts
622 self
.assertTrue(x
>0 for x
in result
.values())
626 # verify that random multisets with no repeats are exactly like sets
627 p
= Counter(dict((elem
, randrange(0, 2)) for elem
in elements
))
628 q
= Counter(dict((elem
, randrange(0, 2)) for elem
in elements
))
629 for counterop
, setop
in [
630 (Counter
.__sub
__, set.__sub
__),
631 (Counter
.__or
__, set.__or
__),
632 (Counter
.__and
__, set.__and
__),
634 counter_result
= counterop(p
, q
)
635 set_result
= setop(set(p
.elements()), set(q
.elements()))
636 self
.assertEqual(counter_result
, dict.fromkeys(set_result
, 1))
638 class TestOrderedDict(unittest
.TestCase
):
641 with self
.assertRaises(TypeError):
642 OrderedDict([('a', 1), ('b', 2)], None) # too many args
643 pairs
= [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
644 self
.assertEqual(sorted(OrderedDict(dict(pairs
)).items()), pairs
) # dict input
645 self
.assertEqual(sorted(OrderedDict(**dict(pairs
)).items()), pairs
) # kwds input
646 self
.assertEqual(list(OrderedDict(pairs
).items()), pairs
) # pairs input
647 self
.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
648 c
=3, e
=5).items()), pairs
) # mixed input
650 # make sure no positional args conflict with possible kwdargs
651 self
.assertEqual(inspect
.getargspec(OrderedDict
.__dict
__['__init__']).args
,
654 # Make sure that direct calls to __init__ do not clear previous contents
655 d
= OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
656 d
.__init
__([('e', 5), ('f', 6)], g
=7, d
=4)
657 self
.assertEqual(list(d
.items()),
658 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
660 def test_update(self
):
661 with self
.assertRaises(TypeError):
662 OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
663 pairs
= [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
665 od
.update(dict(pairs
))
666 self
.assertEqual(sorted(od
.items()), pairs
) # dict input
668 od
.update(**dict(pairs
))
669 self
.assertEqual(sorted(od
.items()), pairs
) # kwds input
672 self
.assertEqual(list(od
.items()), pairs
) # pairs input
674 od
.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c
=3, e
=5)
675 self
.assertEqual(list(od
.items()), pairs
) # mixed input
677 # Make sure that direct calls to update do not clear previous contents
678 # add that updates items are not moved to the end
679 d
= OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
680 d
.update([('e', 5), ('f', 6)], g
=7, d
=4)
681 self
.assertEqual(list(d
.items()),
682 [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
684 def test_clear(self
):
685 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
687 od
= OrderedDict(pairs
)
688 self
.assertEqual(len(od
), len(pairs
))
690 self
.assertEqual(len(od
), 0)
692 def test_delitem(self
):
693 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
694 od
= OrderedDict(pairs
)
696 self
.assertTrue('a' not in od
)
697 with self
.assertRaises(KeyError):
699 self
.assertEqual(list(od
.items()), pairs
[:2] + pairs
[3:])
701 def test_setitem(self
):
702 od
= OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
703 od
['c'] = 10 # existing element
704 od
['f'] = 20 # new element
705 self
.assertEqual(list(od
.items()),
706 [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
708 def test_iterators(self
):
709 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
711 od
= OrderedDict(pairs
)
712 self
.assertEqual(list(od
), [t
[0] for t
in pairs
])
713 self
.assertEqual(od
.keys()[:], [t
[0] for t
in pairs
])
714 self
.assertEqual(od
.values()[:], [t
[1] for t
in pairs
])
715 self
.assertEqual(od
.items()[:], pairs
)
716 self
.assertEqual(list(od
.iterkeys()), [t
[0] for t
in pairs
])
717 self
.assertEqual(list(od
.itervalues()), [t
[1] for t
in pairs
])
718 self
.assertEqual(list(od
.iteritems()), pairs
)
719 self
.assertEqual(list(reversed(od
)),
720 [t
[0] for t
in reversed(pairs
)])
722 def test_popitem(self
):
723 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
725 od
= OrderedDict(pairs
)
727 self
.assertEqual(od
.popitem(), pairs
.pop())
728 with self
.assertRaises(KeyError):
730 self
.assertEqual(len(od
), 0)
733 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
735 od
= OrderedDict(pairs
)
739 self
.assertEqual(od
.pop(k
), v
)
740 with self
.assertRaises(KeyError):
742 self
.assertEqual(len(od
), 0)
743 self
.assertEqual(od
.pop(k
, 12345), 12345)
745 def test_equality(self
):
746 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
748 od1
= OrderedDict(pairs
)
749 od2
= OrderedDict(pairs
)
750 self
.assertEqual(od1
, od2
) # same order implies equality
751 pairs
= pairs
[2:] + pairs
[:2]
752 od2
= OrderedDict(pairs
)
753 self
.assertNotEqual(od1
, od2
) # different order implies inequality
754 # comparison to regular dict is not order sensitive
755 self
.assertEqual(od1
, dict(od2
))
756 self
.assertEqual(dict(od2
), od1
)
757 # different length implied inequality
758 self
.assertNotEqual(od1
, OrderedDict(pairs
[:-1]))
760 def test_copying(self
):
761 # Check that ordered dicts are copyable, deepcopyable, picklable,
762 # and have a repr/eval round-trip
763 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
764 od
= OrderedDict(pairs
)
765 update_test
= OrderedDict()
766 update_test
.update(od
)
767 for i
, dup
in enumerate([
771 pickle
.loads(pickle
.dumps(od
, 0)),
772 pickle
.loads(pickle
.dumps(od
, 1)),
773 pickle
.loads(pickle
.dumps(od
, 2)),
774 pickle
.loads(pickle
.dumps(od
, -1)),
779 self
.assertTrue(dup
is not od
)
780 self
.assertEquals(dup
, od
)
781 self
.assertEquals(list(dup
.items()), list(od
.items()))
782 self
.assertEquals(len(dup
), len(od
))
783 self
.assertEquals(type(dup
), type(od
))
785 def test_yaml_linkage(self
):
786 # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
787 # In yaml, lists are native but tuples are not.
788 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
789 od
= OrderedDict(pairs
)
791 # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
792 self
.assertTrue(all(type(pair
)==list for pair
in od
.__reduce
__()[1]))
794 def test_reduce_not_too_fat(self
):
795 # do not save instance dictionary if not needed
796 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
797 od
= OrderedDict(pairs
)
798 self
.assertEqual(len(od
.__reduce
__()), 2)
800 self
.assertEqual(len(od
.__reduce
__()), 3)
803 od
= OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
804 self
.assertEqual(repr(od
),
805 "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
806 self
.assertEqual(eval(repr(od
)), od
)
807 self
.assertEqual(repr(OrderedDict()), "OrderedDict()")
809 def test_setdefault(self
):
810 pairs
= [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
812 od
= OrderedDict(pairs
)
813 pair_order
= list(od
.items())
814 self
.assertEqual(od
.setdefault('a', 10), 3)
815 # make sure order didn't change
816 self
.assertEqual(list(od
.items()), pair_order
)
817 self
.assertEqual(od
.setdefault('x', 10), 10)
818 # make sure 'x' is added to the end
819 self
.assertEqual(list(od
.items())[-1], ('x', 10))
821 def test_reinsert(self
):
822 # Given insert a, insert b, delete a, re-insert a,
823 # verify that a is now later than b.
829 self
.assertEqual(list(od
.items()), [('b', 2), ('a', 1)])
833 class GeneralMappingTests(mapping_tests
.BasicTestMappingProtocol
):
834 type2test
= OrderedDict
836 def test_popitem(self
):
837 d
= self
._empty
_mapping
()
838 self
.assertRaises(KeyError, d
.popitem
)
840 class MyOrderedDict(OrderedDict
):
843 class SubclassMappingTests(mapping_tests
.BasicTestMappingProtocol
):
844 type2test
= MyOrderedDict
846 def test_popitem(self
):
847 d
= self
._empty
_mapping
()
848 self
.assertRaises(KeyError, d
.popitem
)
850 import doctest
, collections
852 def test_main(verbose
=None):
853 NamedTupleDocs
= doctest
.DocTestSuite(module
=collections
)
854 test_classes
= [TestNamedTuple
, NamedTupleDocs
, TestOneTrickPonyABCs
,
855 TestCollectionABCs
, TestCounter
,
856 TestOrderedDict
, GeneralMappingTests
, SubclassMappingTests
]
857 test_support
.run_unittest(*test_classes
)
858 test_support
.run_doctest(collections
, verbose
)
860 if __name__
== "__main__":
861 test_main(verbose
=True)