1
2import unittest, doctest, operator
3import inspect
4from test import test_support
5from collections import namedtuple, Counter, OrderedDict
6from test import mapping_tests
7import pickle, cPickle, copy
8from random import randrange, shuffle
9import keyword
10import re
11import sys
12from 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
18TestNT = namedtuple('TestNT', 'x y z')    # type used for pickle tests
19
20class TestNamedTuple(unittest.TestCase):
21
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'))
29
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
33
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
39
40        namedtuple('Point0', 'x1 y2')   # Verify that numbers are allowed in names
41        namedtuple('_', 'a b c')        # Test leading underscores in a typename
42
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))
47
48        self.assertRaises(TypeError, Point._make, [11])                     # catch too few args
49        self.assertRaises(TypeError, Point._make, [11, 22, 33])             # catch too many args
50
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)')
56
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
65        ]:
66            self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
67
68    def test_instance(self):
69        Point = namedtuple('Point', 'x y')
70        p = Point(11, 22)
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
87
88        try:
89            p._replace(x=1, error=2)
90        except ValueError:
91            pass
92        else:
93            self._fail('Did not detect an incorrect fieldname')
94
95        # verify that field string can have commas
96        Point = namedtuple('Point', 'x, y')
97        p = Point(x=11, y=22)
98        self.assertEqual(repr(p), 'Point(x=11, y=22)')
99
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)')
104
105    def test_tupleness(self):
106        Point = namedtuple('Point', 'x y')
107        p = Point(11, 22)
108
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
115        x, y = p
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)
119
120        self.assertEqual(p.x, x)
121        self.assertEqual(p.y, y)
122        self.assertRaises(AttributeError, eval, 'p.z', locals())
123
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, ())
131
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',))
140
141        n = 5000
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)))
145        n = len(names)
146        Big = namedtuple('Big', names)
147        b = Big(*range(n))
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
153        d = b._asdict()
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)
158        b2_expected[1] = 999
159        b2_expected[-5] = 42
160        self.assertEqual(b2, tuple(b2_expected))
161        self.assertEqual(b._fields, tuple(names))
162
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)
172
173    def test_copy(self):
174        p = TestNT(x=10, y=20, z=30)
175        for copier in copy.copy, copy.deepcopy:
176            q = copier(p)
177            self.assertEqual(p, q)
178            self.assertEqual(p._fields, q._fields)
179
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')
184        t = T(1, 2, 3, 4, 5)
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))
188
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)
195        # test __new__
196        values = tuple(range(len(words)))
197        t = T(*values)
198        self.assertEqual(t, values)
199        t = T(**dict(zip(T._fields, values)))
200        self.assertEqual(t, values)
201        # test _make
202        t = T._make(values)
203        self.assertEqual(t, values)
204        # exercise __repr__
205        repr(t)
206        # test _asdict
207        self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
208        # test _replace
209        t = T._make(values)
210        newvalues = tuple(v*10 for v in values)
211        newt = t._replace(**dict(zip(T._fields, newvalues)))
212        self.assertEqual(newt, newvalues)
213        # test _fields
214        self.assertEqual(T._fields, tuple(words))
215        # test __getnewargs__
216        self.assertEqual(t.__getnewargs__(), values)
217
218class ABCTestCase(unittest.TestCase):
219
220    def validate_abstract_methods(self, abc, *names):
221        methodstubs = dict.fromkeys(names, lambda s, *args: 0)
222
223        # everything should work will all required methods are present
224        C = type('C', (abc,), methodstubs)
225        C()
226
227        # instantiation should fail if a required method is missing
228        for name in names:
229            stubs = methodstubs.copy()
230            del stubs[name]
231            C = type('C', (abc,), stubs)
232            self.assertRaises(TypeError, C, name)
233
234    def validate_isinstance(self, abc, name):
235        stub = lambda s, *args: 0
236
237        # new-style class
238        C = type('C', (object,), {name: stub})
239        self.assertIsInstance(C(), abc)
240        self.assertTrue(issubclass(C, abc))
241        # old-style class
242        class C: pass
243        setattr(C, name, stub)
244        self.assertIsInstance(C(), abc)
245        self.assertTrue(issubclass(C, abc))
246
247        # new-style class
248        C = type('C', (object,), {'__hash__': None})
249        self.assertNotIsInstance(C(), abc)
250        self.assertFalse(issubclass(C, abc))
251        # old-style class
252        class C: pass
253        self.assertNotIsInstance(C(), abc)
254        self.assertFalse(issubclass(C, abc))
255
256    def validate_comparison(self, instance):
257        ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
258        operators = {}
259        for op in ops:
260            name = '__' + op + '__'
261            operators[name] = getattr(operator, name)
262
263        class Other:
264            def __init__(self):
265                self.right_side = False
266            def __eq__(self, other):
267                self.right_side = True
268                return True
269            __lt__ = __eq__
270            __gt__ = __eq__
271            __le__ = __eq__
272            __ge__ = __eq__
273            __ne__ = __eq__
274            __ror__ = __eq__
275            __rand__ = __eq__
276            __rxor__ = __eq__
277            __rsub__ = __eq__
278
279        for name, op in operators.items():
280            if not hasattr(instance, name):
281                continue
282            other = Other()
283            op(instance, other)
284            self.assertTrue(other.right_side,'Right side not called for %s.%s'
285                            % (type(instance), name))
286
287class TestOneTrickPonyABCs(ABCTestCase):
288
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
296        samples = [None,
297                   int(), float(), complex(),
298                   str(),
299                   tuple(), frozenset(),
300                   int, list, object, type,
301                   ]
302        for x in samples:
303            self.assertIsInstance(x, Hashable)
304            self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
305        self.assertRaises(TypeError, Hashable)
306        # Check direct subclassing
307        class H(Hashable):
308            def __hash__(self):
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__')
315
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
323        samples = [str(),
324                   tuple(), list(), set(), frozenset(), dict(),
325                   dict().keys(), dict().items(), dict().values(),
326                   (lambda: (yield))(),
327                   (x for x in []),
328                   ]
329        for x in samples:
330            self.assertIsInstance(x, Iterable)
331            self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
332        # Check direct subclassing
333        class I(Iterable):
334            def __iter__(self):
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__')
340
341    def test_Iterator(self):
342        non_samples = [None, 42, 3.14, 1j, "".encode('ascii'), "", (), [],
343            {}, set()]
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()),
352                   (lambda: (yield))(),
353                   (x for x in []),
354                   ]
355        for x in samples:
356            self.assertIsInstance(x, Iterator)
357            self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
358        self.validate_abstract_methods(Iterator, 'next', '__iter__')
359
360        # Issue 10565
361        class NextOnly:
362            def __next__(self):
363                yield 1
364                raise StopIteration
365        self.assertNotIsInstance(NextOnly(), Iterator)
366        class NextOnlyNew(object):
367            def __next__(self):
368                yield 1
369                raise StopIteration
370        self.assertNotIsInstance(NextOnlyNew(), Iterator)
371
372    def test_Sized(self):
373        non_samples = [None, 42, 3.14, 1j,
374                       (lambda: (yield))(),
375                       (x for x in []),
376                       ]
377        for x in non_samples:
378            self.assertNotIsInstance(x, Sized)
379            self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
380        samples = [str(),
381                   tuple(), list(), set(), frozenset(), dict(),
382                   dict().keys(), dict().items(), dict().values(),
383                   ]
384        for x in samples:
385            self.assertIsInstance(x, Sized)
386            self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
387        self.validate_abstract_methods(Sized, '__len__')
388        self.validate_isinstance(Sized, '__len__')
389
390    def test_Container(self):
391        non_samples = [None, 42, 3.14, 1j,
392                       (lambda: (yield))(),
393                       (x for x in []),
394                       ]
395        for x in non_samples:
396            self.assertNotIsInstance(x, Container)
397            self.assertFalse(issubclass(type(x), Container), repr(type(x)))
398        samples = [str(),
399                   tuple(), list(), set(), frozenset(), dict(),
400                   dict().keys(), dict().items(),
401                   ]
402        for x in samples:
403            self.assertIsInstance(x, Container)
404            self.assertTrue(issubclass(type(x), Container), repr(type(x)))
405        self.validate_abstract_methods(Container, '__contains__')
406        self.validate_isinstance(Container, '__contains__')
407
408    def test_Callable(self):
409        non_samples = [None, 42, 3.14, 1j,
410                       "", "".encode('ascii'), (), [], {}, set(),
411                       (lambda: (yield))(),
412                       (x for x in []),
413                       ]
414        for x in non_samples:
415            self.assertNotIsInstance(x, Callable)
416            self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
417        samples = [lambda: None,
418                   type, int, object,
419                   len,
420                   list.append, [].append,
421                   ]
422        for x in samples:
423            self.assertIsInstance(x, Callable)
424            self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
425        self.validate_abstract_methods(Callable, '__call__')
426        self.validate_isinstance(Callable, '__call__')
427
428    def test_direct_subclassing(self):
429        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
430            class C(B):
431                pass
432            self.assertTrue(issubclass(C, B))
433            self.assertFalse(issubclass(int, C))
434
435    def test_registration(self):
436        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
437            class C:
438                __metaclass__ = type
439                __hash__ = None  # Make sure it isn't hashable by default
440            self.assertFalse(issubclass(C, B), B.__name__)
441            B.register(C)
442            self.assertTrue(issubclass(C, B))
443
444class WithSet(MutableSet):
445
446    def __init__(self, it=()):
447        self.data = set(it)
448
449    def __len__(self):
450        return len(self.data)
451
452    def __iter__(self):
453        return iter(self.data)
454
455    def __contains__(self, item):
456        return item in self.data
457
458    def add(self, item):
459        self.data.add(item)
460
461    def discard(self, item):
462        self.data.discard(item)
463
464class TestCollectionABCs(ABCTestCase):
465
466    # XXX For now, we only test some virtual inheritance properties.
467    # We should also test the proper behavior of the collection ABCs
468    # as real base classes or mix-in classes.
469
470    def test_Set(self):
471        for sample in [set, frozenset]:
472            self.assertIsInstance(sample(), Set)
473            self.assertTrue(issubclass(sample, Set))
474        self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
475        class MySet(Set):
476            def __contains__(self, x):
477                return False
478            def __len__(self):
479                return 0
480            def __iter__(self):
481                return iter([])
482        self.validate_comparison(MySet())
483
484    def test_hash_Set(self):
485        class OneTwoThreeSet(Set):
486            def __init__(self):
487                self.contents = [1, 2, 3]
488            def __contains__(self, x):
489                return x in self.contents
490            def __len__(self):
491                return len(self.contents)
492            def __iter__(self):
493                return iter(self.contents)
494            def __hash__(self):
495                return self._hash()
496        a, b = OneTwoThreeSet(), OneTwoThreeSet()
497        self.assertTrue(hash(a) == hash(b))
498
499    def test_MutableSet(self):
500        self.assertIsInstance(set(), MutableSet)
501        self.assertTrue(issubclass(set, MutableSet))
502        self.assertNotIsInstance(frozenset(), MutableSet)
503        self.assertFalse(issubclass(frozenset, MutableSet))
504        self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
505            'add', 'discard')
506
507    def test_issue_5647(self):
508        # MutableSet.__iand__ mutated the set during iteration
509        s = WithSet('abcd')
510        s &= WithSet('cdef')            # This used to fail
511        self.assertEqual(set(s), set('cd'))
512
513    def test_issue_4920(self):
514        # MutableSet.pop() method did not work
515        class MySet(collections.MutableSet):
516            __slots__=['__s']
517            def __init__(self,items=None):
518                if items is None:
519                    items=[]
520                self.__s=set(items)
521            def __contains__(self,v):
522                return v in self.__s
523            def __iter__(self):
524                return iter(self.__s)
525            def __len__(self):
526                return len(self.__s)
527            def add(self,v):
528                result=v not in self.__s
529                self.__s.add(v)
530                return result
531            def discard(self,v):
532                result=v in self.__s
533                self.__s.discard(v)
534                return result
535            def __repr__(self):
536                return "MySet(%s)" % repr(list(self))
537        s = MySet([5,43,2,1])
538        self.assertEqual(s.pop(), 1)
539
540    def test_issue8750(self):
541        empty = WithSet()
542        full = WithSet(range(10))
543        s = WithSet(full)
544        s -= s
545        self.assertEqual(s, empty)
546        s = WithSet(full)
547        s ^= s
548        self.assertEqual(s, empty)
549        s = WithSet(full)
550        s &= s
551        self.assertEqual(s, full)
552        s |= s
553        self.assertEqual(s, full)
554
555    def test_Mapping(self):
556        for sample in [dict]:
557            self.assertIsInstance(sample(), Mapping)
558            self.assertTrue(issubclass(sample, Mapping))
559        self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
560            '__getitem__')
561        class MyMapping(collections.Mapping):
562            def __len__(self):
563                return 0
564            def __getitem__(self, i):
565                raise IndexError
566            def __iter__(self):
567                return iter(())
568        self.validate_comparison(MyMapping())
569
570    def test_MutableMapping(self):
571        for sample in [dict]:
572            self.assertIsInstance(sample(), MutableMapping)
573            self.assertTrue(issubclass(sample, MutableMapping))
574        self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
575            '__getitem__', '__setitem__', '__delitem__')
576
577    def test_Sequence(self):
578        for sample in [tuple, list, str]:
579            self.assertIsInstance(sample(), Sequence)
580            self.assertTrue(issubclass(sample, Sequence))
581        self.assertTrue(issubclass(basestring, Sequence))
582        self.assertIsInstance(range(10), Sequence)
583        self.assertTrue(issubclass(xrange, Sequence))
584        self.assertTrue(issubclass(str, Sequence))
585        self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
586            '__getitem__')
587
588    def test_MutableSequence(self):
589        for sample in [tuple, str]:
590            self.assertNotIsInstance(sample(), MutableSequence)
591            self.assertFalse(issubclass(sample, MutableSequence))
592        for sample in [list]:
593            self.assertIsInstance(sample(), MutableSequence)
594            self.assertTrue(issubclass(sample, MutableSequence))
595        self.assertFalse(issubclass(basestring, MutableSequence))
596        self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
597            '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
598
599class TestCounter(unittest.TestCase):
600
601    def test_basics(self):
602        c = Counter('abcaba')
603        self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
604        self.assertEqual(c, Counter(a=3, b=2, c=1))
605        self.assertIsInstance(c, dict)
606        self.assertIsInstance(c, Mapping)
607        self.assertTrue(issubclass(Counter, dict))
608        self.assertTrue(issubclass(Counter, Mapping))
609        self.assertEqual(len(c), 3)
610        self.assertEqual(sum(c.values()), 6)
611        self.assertEqual(sorted(c.values()), [1, 2, 3])
612        self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
613        self.assertEqual(sorted(c), ['a', 'b', 'c'])
614        self.assertEqual(sorted(c.items()),
615                         [('a', 3), ('b', 2), ('c', 1)])
616        self.assertEqual(c['b'], 2)
617        self.assertEqual(c['z'], 0)
618        with test_support.check_py3k_warnings():
619            self.assertEqual(c.has_key('c'), True)
620            self.assertEqual(c.has_key('z'), False)
621        self.assertEqual(c.__contains__('c'), True)
622        self.assertEqual(c.__contains__('z'), False)
623        self.assertEqual(c.get('b', 10), 2)
624        self.assertEqual(c.get('z', 10), 10)
625        self.assertEqual(c, dict(a=3, b=2, c=1))
626        self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
627        self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
628        for i in range(5):
629            self.assertEqual(c.most_common(i),
630                             [('a', 3), ('b', 2), ('c', 1)][:i])
631        self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
632        c['a'] += 1         # increment an existing value
633        c['b'] -= 2         # sub existing value to zero
634        del c['c']          # remove an entry
635        del c['c']          # make sure that del doesn't raise KeyError
636        c['d'] -= 2         # sub from a missing value
637        c['e'] = -5         # directly assign a missing value
638        c['f'] += 4         # add to a missing value
639        self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
640        self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
641        self.assertEqual(c.pop('f'), 4)
642        self.assertNotIn('f', c)
643        for i in range(3):
644            elem, cnt = c.popitem()
645            self.assertNotIn(elem, c)
646        c.clear()
647        self.assertEqual(c, {})
648        self.assertEqual(repr(c), 'Counter()')
649        self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
650        self.assertRaises(TypeError, hash, c)
651        c.update(dict(a=5, b=3))
652        c.update(c=1)
653        c.update(Counter('a' * 50 + 'b' * 30))
654        c.update()          # test case with no args
655        c.__init__('a' * 500 + 'b' * 300)
656        c.__init__('cdc')
657        c.__init__()
658        self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
659        self.assertEqual(c.setdefault('d', 5), 1)
660        self.assertEqual(c['d'], 1)
661        self.assertEqual(c.setdefault('e', 5), 5)
662        self.assertEqual(c['e'], 5)
663
664    def test_copying(self):
665        # Check that counters are copyable, deepcopyable, picklable, and
666        #have a repr/eval round-trip
667        words = Counter('which witch had which witches wrist watch'.split())
668        update_test = Counter()
669        update_test.update(words)
670        for i, dup in enumerate([
671                    words.copy(),
672                    copy.copy(words),
673                    copy.deepcopy(words),
674                    pickle.loads(pickle.dumps(words, 0)),
675                    pickle.loads(pickle.dumps(words, 1)),
676                    pickle.loads(pickle.dumps(words, 2)),
677                    pickle.loads(pickle.dumps(words, -1)),
678                    cPickle.loads(cPickle.dumps(words, 0)),
679                    cPickle.loads(cPickle.dumps(words, 1)),
680                    cPickle.loads(cPickle.dumps(words, 2)),
681                    cPickle.loads(cPickle.dumps(words, -1)),
682                    eval(repr(words)),
683                    update_test,
684                    Counter(words),
685                    ]):
686            msg = (i, dup, words)
687            self.assertTrue(dup is not words)
688            self.assertEqual(dup, words)
689            self.assertEqual(len(dup), len(words))
690            self.assertEqual(type(dup), type(words))
691
692    def test_copy_subclass(self):
693        class MyCounter(Counter):
694            pass
695        c = MyCounter('slartibartfast')
696        d = c.copy()
697        self.assertEqual(d, c)
698        self.assertEqual(len(d), len(c))
699        self.assertEqual(type(d), type(c))
700
701    def test_conversions(self):
702        # Convert to: set, list, dict
703        s = 'she sells sea shells by the sea shore'
704        self.assertEqual(sorted(Counter(s).elements()), sorted(s))
705        self.assertEqual(sorted(Counter(s)), sorted(set(s)))
706        self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
707        self.assertEqual(set(Counter(s)), set(s))
708
709    def test_invariant_for_the_in_operator(self):
710        c = Counter(a=10, b=-2, c=0)
711        for elem in c:
712            self.assertTrue(elem in c)
713            self.assertIn(elem, c)
714
715    def test_multiset_operations(self):
716        # Verify that adding a zero counter will strip zeros and negatives
717        c = Counter(a=10, b=-2, c=0) + Counter()
718        self.assertEqual(dict(c), dict(a=10))
719
720        elements = 'abcd'
721        for i in range(1000):
722            # test random pairs of multisets
723            p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
724            p.update(e=1, f=-1, g=0)
725            q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
726            q.update(h=1, i=-1, j=0)
727            for counterop, numberop in [
728                (Counter.__add__, lambda x, y: max(0, x+y)),
729                (Counter.__sub__, lambda x, y: max(0, x-y)),
730                (Counter.__or__, lambda x, y: max(0,x,y)),
731                (Counter.__and__, lambda x, y: max(0, min(x,y))),
732            ]:
733                result = counterop(p, q)
734                for x in elements:
735                    self.assertEqual(numberop(p[x], q[x]), result[x],
736                                     (counterop, x, p, q))
737                # verify that results exclude non-positive counts
738                self.assertTrue(x>0 for x in result.values())
739
740        elements = 'abcdef'
741        for i in range(100):
742            # verify that random multisets with no repeats are exactly like sets
743            p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
744            q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
745            for counterop, setop in [
746                (Counter.__sub__, set.__sub__),
747                (Counter.__or__, set.__or__),
748                (Counter.__and__, set.__and__),
749            ]:
750                counter_result = counterop(p, q)
751                set_result = setop(set(p.elements()), set(q.elements()))
752                self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
753
754    def test_subtract(self):
755        c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
756        c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
757        self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
758        c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
759        c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
760        self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
761        c = Counter('aaabbcd')
762        c.subtract('aaaabbcce')
763        self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
764
765class TestOrderedDict(unittest.TestCase):
766
767    def test_init(self):
768        with self.assertRaises(TypeError):
769            OrderedDict([('a', 1), ('b', 2)], None)                                 # too many args
770        pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
771        self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs)           # dict input
772        self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs)         # kwds input
773        self.assertEqual(list(OrderedDict(pairs).items()), pairs)                   # pairs input
774        self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
775                                          c=3, e=5).items()), pairs)                # mixed input
776
777        # make sure no positional args conflict with possible kwdargs
778        self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
779                         ['self'])
780
781        # Make sure that direct calls to __init__ do not clear previous contents
782        d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
783        d.__init__([('e', 5), ('f', 6)], g=7, d=4)
784        self.assertEqual(list(d.items()),
785            [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
786
787    def test_update(self):
788        with self.assertRaises(TypeError):
789            OrderedDict().update([('a', 1), ('b', 2)], None)                        # too many args
790        pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
791        od = OrderedDict()
792        od.update(dict(pairs))
793        self.assertEqual(sorted(od.items()), pairs)                                 # dict input
794        od = OrderedDict()
795        od.update(**dict(pairs))
796        self.assertEqual(sorted(od.items()), pairs)                                 # kwds input
797        od = OrderedDict()
798        od.update(pairs)
799        self.assertEqual(list(od.items()), pairs)                                   # pairs input
800        od = OrderedDict()
801        od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
802        self.assertEqual(list(od.items()), pairs)                                   # mixed input
803
804        # Issue 9137: Named argument called 'other' or 'self'
805        # shouldn't be treated specially.
806        od = OrderedDict()
807        od.update(self=23)
808        self.assertEqual(list(od.items()), [('self', 23)])
809        od = OrderedDict()
810        od.update(other={})
811        self.assertEqual(list(od.items()), [('other', {})])
812        od = OrderedDict()
813        od.update(red=5, blue=6, other=7, self=8)
814        self.assertEqual(sorted(list(od.items())),
815                         [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
816
817        # Make sure that direct calls to update do not clear previous contents
818        # add that updates items are not moved to the end
819        d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
820        d.update([('e', 5), ('f', 6)], g=7, d=4)
821        self.assertEqual(list(d.items()),
822            [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
823
824    def test_abc(self):
825        self.assertIsInstance(OrderedDict(), MutableMapping)
826        self.assertTrue(issubclass(OrderedDict, MutableMapping))
827
828    def test_clear(self):
829        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
830        shuffle(pairs)
831        od = OrderedDict(pairs)
832        self.assertEqual(len(od), len(pairs))
833        od.clear()
834        self.assertEqual(len(od), 0)
835
836    def test_delitem(self):
837        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
838        od = OrderedDict(pairs)
839        del od['a']
840        self.assertNotIn('a', od)
841        with self.assertRaises(KeyError):
842            del od['a']
843        self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
844
845    def test_setitem(self):
846        od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
847        od['c'] = 10           # existing element
848        od['f'] = 20           # new element
849        self.assertEqual(list(od.items()),
850                         [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
851
852    def test_iterators(self):
853        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
854        shuffle(pairs)
855        od = OrderedDict(pairs)
856        self.assertEqual(list(od), [t[0] for t in pairs])
857        self.assertEqual(od.keys()[:], [t[0] for t in pairs])
858        self.assertEqual(od.values()[:], [t[1] for t in pairs])
859        self.assertEqual(od.items()[:], pairs)
860        self.assertEqual(list(od.iterkeys()), [t[0] for t in pairs])
861        self.assertEqual(list(od.itervalues()), [t[1] for t in pairs])
862        self.assertEqual(list(od.iteritems()), pairs)
863        self.assertEqual(list(reversed(od)),
864                         [t[0] for t in reversed(pairs)])
865
866    def test_popitem(self):
867        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
868        shuffle(pairs)
869        od = OrderedDict(pairs)
870        while pairs:
871            self.assertEqual(od.popitem(), pairs.pop())
872        with self.assertRaises(KeyError):
873            od.popitem()
874        self.assertEqual(len(od), 0)
875
876    def test_pop(self):
877        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
878        shuffle(pairs)
879        od = OrderedDict(pairs)
880        shuffle(pairs)
881        while pairs:
882            k, v = pairs.pop()
883            self.assertEqual(od.pop(k), v)
884        with self.assertRaises(KeyError):
885            od.pop('xyz')
886        self.assertEqual(len(od), 0)
887        self.assertEqual(od.pop(k, 12345), 12345)
888
889        # make sure pop still works when __missing__ is defined
890        class Missing(OrderedDict):
891            def __missing__(self, key):
892                return 0
893        m = Missing(a=1)
894        self.assertEqual(m.pop('b', 5), 5)
895        self.assertEqual(m.pop('a', 6), 1)
896        self.assertEqual(m.pop('a', 6), 6)
897        with self.assertRaises(KeyError):
898            m.pop('a')
899
900    def test_equality(self):
901        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
902        shuffle(pairs)
903        od1 = OrderedDict(pairs)
904        od2 = OrderedDict(pairs)
905        self.assertEqual(od1, od2)          # same order implies equality
906        pairs = pairs[2:] + pairs[:2]
907        od2 = OrderedDict(pairs)
908        self.assertNotEqual(od1, od2)       # different order implies inequality
909        # comparison to regular dict is not order sensitive
910        self.assertEqual(od1, dict(od2))
911        self.assertEqual(dict(od2), od1)
912        # different length implied inequality
913        self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
914
915    def test_copying(self):
916        # Check that ordered dicts are copyable, deepcopyable, picklable,
917        # and have a repr/eval round-trip
918        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
919        od = OrderedDict(pairs)
920        update_test = OrderedDict()
921        update_test.update(od)
922        for i, dup in enumerate([
923                    od.copy(),
924                    copy.copy(od),
925                    copy.deepcopy(od),
926                    pickle.loads(pickle.dumps(od, 0)),
927                    pickle.loads(pickle.dumps(od, 1)),
928                    pickle.loads(pickle.dumps(od, 2)),
929                    pickle.loads(pickle.dumps(od, -1)),
930                    eval(repr(od)),
931                    update_test,
932                    OrderedDict(od),
933                    ]):
934            self.assertTrue(dup is not od)
935            self.assertEqual(dup, od)
936            self.assertEqual(list(dup.items()), list(od.items()))
937            self.assertEqual(len(dup), len(od))
938            self.assertEqual(type(dup), type(od))
939
940    def test_yaml_linkage(self):
941        # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
942        # In yaml, lists are native but tuples are not.
943        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
944        od = OrderedDict(pairs)
945        # yaml.dump(od) -->
946        # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n  - [b, 2]\n'
947        self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
948
949    def test_reduce_not_too_fat(self):
950        # do not save instance dictionary if not needed
951        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
952        od = OrderedDict(pairs)
953        self.assertEqual(len(od.__reduce__()), 2)
954        od.x = 10
955        self.assertEqual(len(od.__reduce__()), 3)
956
957    def test_repr(self):
958        od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
959        self.assertEqual(repr(od),
960            "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
961        self.assertEqual(eval(repr(od)), od)
962        self.assertEqual(repr(OrderedDict()), "OrderedDict()")
963
964    def test_repr_recursive(self):
965        # See issue #9826
966        od = OrderedDict.fromkeys('abc')
967        od['x'] = od
968        self.assertEqual(repr(od),
969            "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
970
971    def test_setdefault(self):
972        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
973        shuffle(pairs)
974        od = OrderedDict(pairs)
975        pair_order = list(od.items())
976        self.assertEqual(od.setdefault('a', 10), 3)
977        # make sure order didn't change
978        self.assertEqual(list(od.items()), pair_order)
979        self.assertEqual(od.setdefault('x', 10), 10)
980        # make sure 'x' is added to the end
981        self.assertEqual(list(od.items())[-1], ('x', 10))
982
983        # make sure setdefault still works when __missing__ is defined
984        class Missing(OrderedDict):
985            def __missing__(self, key):
986                return 0
987        self.assertEqual(Missing().setdefault(5, 9), 9)
988
989    def test_reinsert(self):
990        # Given insert a, insert b, delete a, re-insert a,
991        # verify that a is now later than b.
992        od = OrderedDict()
993        od['a'] = 1
994        od['b'] = 2
995        del od['a']
996        od['a'] = 1
997        self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
998
999    def test_views(self):
1000        s = 'the quick brown fox jumped over a lazy dog yesterday before dawn'.split()
1001        od = OrderedDict.fromkeys(s)
1002        self.assertEqual(list(od.viewkeys()),  s)
1003        self.assertEqual(list(od.viewvalues()),  [None for k in s])
1004        self.assertEqual(list(od.viewitems()),  [(k, None) for k in s])
1005
1006    def test_override_update(self):
1007        # Verify that subclasses can override update() without breaking __init__()
1008        class MyOD(OrderedDict):
1009            def update(self, *args, **kwds):
1010                raise Exception()
1011        items = [('a', 1), ('c', 3), ('b', 2)]
1012        self.assertEqual(list(MyOD(items).items()), items)
1013
1014class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1015    type2test = OrderedDict
1016
1017    def test_popitem(self):
1018        d = self._empty_mapping()
1019        self.assertRaises(KeyError, d.popitem)
1020
1021class MyOrderedDict(OrderedDict):
1022    pass
1023
1024class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1025    type2test = MyOrderedDict
1026
1027    def test_popitem(self):
1028        d = self._empty_mapping()
1029        self.assertRaises(KeyError, d.popitem)
1030
1031import collections
1032
1033def test_main(verbose=None):
1034    NamedTupleDocs = doctest.DocTestSuite(module=collections)
1035    test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
1036                    TestCollectionABCs, TestCounter,
1037                    TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
1038    test_support.run_unittest(*test_classes)
1039    test_support.run_doctest(collections, verbose)
1040
1041if __name__ == "__main__":
1042    test_main(verbose=True)
1043