~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Lib/test/test_collections.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""Unit tests for collections.py."""
 
2
 
 
3
import unittest, doctest, operator
 
4
from test.support import TESTFN, forget, unlink
 
5
import inspect
 
6
from test import support
 
7
from collections import namedtuple, Counter, OrderedDict, _count_elements
 
8
from test import mapping_tests
 
9
import pickle, copy
 
10
from random import randrange, shuffle
 
11
import keyword
 
12
import re
 
13
import sys
 
14
from collections import UserDict
 
15
from collections import ChainMap
 
16
from collections.abc import Hashable, Iterable, Iterator
 
17
from collections.abc import Sized, Container, Callable
 
18
from collections.abc import Set, MutableSet
 
19
from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
 
20
from collections.abc import Sequence, MutableSequence
 
21
from collections.abc import ByteString
 
22
 
 
23
 
 
24
################################################################################
 
25
### ChainMap (helper class for configparser and the string module)
 
26
################################################################################
 
27
 
 
28
class TestChainMap(unittest.TestCase):
 
29
 
 
30
    def test_basics(self):
 
31
        c = ChainMap()
 
32
        c['a'] = 1
 
33
        c['b'] = 2
 
34
        d = c.new_child()
 
35
        d['b'] = 20
 
36
        d['c'] = 30
 
37
        self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}])  # check internal state
 
38
        self.assertEqual(d.items(), dict(a=1, b=20, c=30).items())    # check items/iter/getitem
 
39
        self.assertEqual(len(d), 3)                                   # check len
 
40
        for key in 'abc':                                             # check contains
 
41
            self.assertIn(key, d)
 
42
        for k, v in dict(a=1, b=20, c=30, z=100).items():             # check get
 
43
            self.assertEqual(d.get(k, 100), v)
 
44
 
 
45
        del d['b']                                                    # unmask a value
 
46
        self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}])          # check internal state
 
47
        self.assertEqual(d.items(), dict(a=1, b=2, c=30).items())     # check items/iter/getitem
 
48
        self.assertEqual(len(d), 3)                                   # check len
 
49
        for key in 'abc':                                             # check contains
 
50
            self.assertIn(key, d)
 
51
        for k, v in dict(a=1, b=2, c=30, z=100).items():              # check get
 
52
            self.assertEqual(d.get(k, 100), v)
 
53
        self.assertIn(repr(d), [                                      # check repr
 
54
            type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
 
55
            type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
 
56
        ])
 
57
 
 
58
        for e in d.copy(), copy.copy(d):                               # check shallow copies
 
59
            self.assertEqual(d, e)
 
60
            self.assertEqual(d.maps, e.maps)
 
61
            self.assertIsNot(d, e)
 
62
            self.assertIsNot(d.maps[0], e.maps[0])
 
63
            for m1, m2 in zip(d.maps[1:], e.maps[1:]):
 
64
                self.assertIs(m1, m2)
 
65
 
 
66
        for e in [pickle.loads(pickle.dumps(d)),
 
67
                  copy.deepcopy(d),
 
68
                  eval(repr(d))
 
69
                ]:                                                    # check deep copies
 
70
            self.assertEqual(d, e)
 
71
            self.assertEqual(d.maps, e.maps)
 
72
            self.assertIsNot(d, e)
 
73
            for m1, m2 in zip(d.maps, e.maps):
 
74
                self.assertIsNot(m1, m2, e)
 
75
 
 
76
        f = d.new_child()
 
77
        f['b'] = 5
 
78
        self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
 
79
        self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}])   # check parents
 
80
        self.assertEqual(f['b'], 5)                                    # find first in chain
 
81
        self.assertEqual(f.parents['b'], 2)                            # look beyond maps[0]
 
82
 
 
83
    def test_contructor(self):
 
84
        self.assertEqual(ChainMap().maps, [{}])                        # no-args --> one new dict
 
85
        self.assertEqual(ChainMap({1:2}).maps, [{1:2}])                # 1 arg --> list
 
86
 
 
87
    def test_bool(self):
 
88
        self.assertFalse(ChainMap())
 
89
        self.assertFalse(ChainMap({}, {}))
 
90
        self.assertTrue(ChainMap({1:2}, {}))
 
91
        self.assertTrue(ChainMap({}, {1:2}))
 
92
 
 
93
    def test_missing(self):
 
94
        class DefaultChainMap(ChainMap):
 
95
            def __missing__(self, key):
 
96
                return 999
 
97
        d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
 
98
        for k, v in dict(a=1, b=2, c=30, d=999).items():
 
99
            self.assertEqual(d[k], v)                                  # check __getitem__ w/missing
 
100
        for k, v in dict(a=1, b=2, c=30, d=77).items():
 
101
            self.assertEqual(d.get(k, 77), v)                          # check get() w/ missing
 
102
        for k, v in dict(a=True, b=True, c=True, d=False).items():
 
103
            self.assertEqual(k in d, v)                                # check __contains__ w/missing
 
104
        self.assertEqual(d.pop('a', 1001), 1, d)
 
105
        self.assertEqual(d.pop('a', 1002), 1002)                       # check pop() w/missing
 
106
        self.assertEqual(d.popitem(), ('b', 2))                        # check popitem() w/missing
 
107
        with self.assertRaises(KeyError):
 
108
            d.popitem()
 
109
 
 
110
    def test_dict_coercion(self):
 
111
        d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
 
112
        self.assertEqual(dict(d), dict(a=1, b=2, c=30))
 
113
        self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
 
114
 
 
115
    def test_new_child(self):
 
116
        'Tests for changes for issue #16613.'
 
117
        c = ChainMap()
 
118
        c['a'] = 1
 
119
        c['b'] = 2
 
120
        m = {'b':20, 'c': 30}
 
121
        d = c.new_child(m)
 
122
        self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}])  # check internal state
 
123
        self.assertIs(m, d.maps[0])
 
124
 
 
125
        # Use a different map than a dict
 
126
        class lowerdict(dict):
 
127
            def __getitem__(self, key):
 
128
                if isinstance(key, str):
 
129
                    key = key.lower()
 
130
                return dict.__getitem__(self, key)
 
131
            def __contains__(self, key):
 
132
                if isinstance(key, str):
 
133
                    key = key.lower()
 
134
                return dict.__contains__(self, key)
 
135
 
 
136
        c = ChainMap()
 
137
        c['a'] = 1
 
138
        c['b'] = 2
 
139
        m = lowerdict(b=20, c=30)
 
140
        d = c.new_child(m)
 
141
        self.assertIs(m, d.maps[0])
 
142
        for key in 'abc':                                             # check contains
 
143
            self.assertIn(key, d)
 
144
        for k, v in dict(a=1, B=20, C=30, z=100).items():             # check get
 
145
            self.assertEqual(d.get(k, 100), v)
 
146
 
 
147
 
 
148
################################################################################
 
149
### Named Tuples
 
150
################################################################################
 
151
 
 
152
TestNT = namedtuple('TestNT', 'x y z')    # type used for pickle tests
 
153
 
 
154
class TestNamedTuple(unittest.TestCase):
 
155
 
 
156
    def test_factory(self):
 
157
        Point = namedtuple('Point', 'x y')
 
158
        self.assertEqual(Point.__name__, 'Point')
 
159
        self.assertEqual(Point.__slots__, ())
 
160
        self.assertEqual(Point.__module__, __name__)
 
161
        self.assertEqual(Point.__getitem__, tuple.__getitem__)
 
162
        self.assertEqual(Point._fields, ('x', 'y'))
 
163
        self.assertIn('class Point(tuple)', Point._source)
 
164
 
 
165
        self.assertRaises(ValueError, namedtuple, 'abc%', 'efg ghi')       # type has non-alpha char
 
166
        self.assertRaises(ValueError, namedtuple, 'class', 'efg ghi')      # type has keyword
 
167
        self.assertRaises(ValueError, namedtuple, '9abc', 'efg ghi')       # type starts with digit
 
168
 
 
169
        self.assertRaises(ValueError, namedtuple, 'abc', 'efg g%hi')       # field with non-alpha char
 
170
        self.assertRaises(ValueError, namedtuple, 'abc', 'abc class')      # field has keyword
 
171
        self.assertRaises(ValueError, namedtuple, 'abc', '8efg 9ghi')      # field starts with digit
 
172
        self.assertRaises(ValueError, namedtuple, 'abc', '_efg ghi')       # field with leading underscore
 
173
        self.assertRaises(ValueError, namedtuple, 'abc', 'efg efg ghi')    # duplicate field
 
174
 
 
175
        namedtuple('Point0', 'x1 y2')   # Verify that numbers are allowed in names
 
176
        namedtuple('_', 'a b c')        # Test leading underscores in a typename
 
177
 
 
178
        nt = namedtuple('nt', 'the quick brown fox')                       # check unicode input
 
179
        self.assertNotIn("u'", repr(nt._fields))
 
180
        nt = namedtuple('nt', ('the', 'quick'))                           # check unicode input
 
181
        self.assertNotIn("u'", repr(nt._fields))
 
182
 
 
183
        self.assertRaises(TypeError, Point._make, [11])                     # catch too few args
 
184
        self.assertRaises(TypeError, Point._make, [11, 22, 33])             # catch too many args
 
185
 
 
186
    @unittest.skipIf(sys.flags.optimize >= 2,
 
187
                     "Docstrings are omitted with -O2 and above")
 
188
    def test_factory_doc_attr(self):
 
189
        Point = namedtuple('Point', 'x y')
 
190
        self.assertEqual(Point.__doc__, 'Point(x, y)')
 
191
 
 
192
    def test_name_fixer(self):
 
193
        for spec, renamed in [
 
194
            [('efg', 'g%hi'),  ('efg', '_1')],                              # field with non-alpha char
 
195
            [('abc', 'class'), ('abc', '_1')],                              # field has keyword
 
196
            [('8efg', '9ghi'), ('_0', '_1')],                               # field starts with digit
 
197
            [('abc', '_efg'), ('abc', '_1')],                               # field with leading underscore
 
198
            [('abc', 'efg', 'efg', 'ghi'), ('abc', 'efg', '_2', 'ghi')],    # duplicate field
 
199
            [('abc', '', 'x'), ('abc', '_1', 'x')],                         # fieldname is a space
 
200
        ]:
 
201
            self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
 
202
 
 
203
    def test_instance(self):
 
204
        Point = namedtuple('Point', 'x y')
 
205
        p = Point(11, 22)
 
206
        self.assertEqual(p, Point(x=11, y=22))
 
207
        self.assertEqual(p, Point(11, y=22))
 
208
        self.assertEqual(p, Point(y=22, x=11))
 
209
        self.assertEqual(p, Point(*(11, 22)))
 
210
        self.assertEqual(p, Point(**dict(x=11, y=22)))
 
211
        self.assertRaises(TypeError, Point, 1)                              # too few args
 
212
        self.assertRaises(TypeError, Point, 1, 2, 3)                        # too many args
 
213
        self.assertRaises(TypeError, eval, 'Point(XXX=1, y=2)', locals())   # wrong keyword argument
 
214
        self.assertRaises(TypeError, eval, 'Point(x=1)', locals())          # missing keyword argument
 
215
        self.assertEqual(repr(p), 'Point(x=11, y=22)')
 
216
        self.assertNotIn('__weakref__', dir(p))
 
217
        self.assertEqual(p, Point._make([11, 22]))                          # test _make classmethod
 
218
        self.assertEqual(p._fields, ('x', 'y'))                             # test _fields attribute
 
219
        self.assertEqual(p._replace(x=1), (1, 22))                          # test _replace method
 
220
        self.assertEqual(p._asdict(), dict(x=11, y=22))                     # test _asdict method
 
221
        self.assertEqual(vars(p), p._asdict())                              # verify that vars() works
 
222
 
 
223
        try:
 
224
            p._replace(x=1, error=2)
 
225
        except ValueError:
 
226
            pass
 
227
        else:
 
228
            self._fail('Did not detect an incorrect fieldname')
 
229
 
 
230
        # verify that field string can have commas
 
231
        Point = namedtuple('Point', 'x, y')
 
232
        p = Point(x=11, y=22)
 
233
        self.assertEqual(repr(p), 'Point(x=11, y=22)')
 
234
 
 
235
        # verify that fieldspec can be a non-string sequence
 
236
        Point = namedtuple('Point', ('x', 'y'))
 
237
        p = Point(x=11, y=22)
 
238
        self.assertEqual(repr(p), 'Point(x=11, y=22)')
 
239
 
 
240
    def test_tupleness(self):
 
241
        Point = namedtuple('Point', 'x y')
 
242
        p = Point(11, 22)
 
243
 
 
244
        self.assertIsInstance(p, tuple)
 
245
        self.assertEqual(p, (11, 22))                                       # matches a real tuple
 
246
        self.assertEqual(tuple(p), (11, 22))                                # coercable to a real tuple
 
247
        self.assertEqual(list(p), [11, 22])                                 # coercable to a list
 
248
        self.assertEqual(max(p), 22)                                        # iterable
 
249
        self.assertEqual(max(*p), 22)                                       # star-able
 
250
        x, y = p
 
251
        self.assertEqual(p, (x, y))                                         # unpacks like a tuple
 
252
        self.assertEqual((p[0], p[1]), (11, 22))                            # indexable like a tuple
 
253
        self.assertRaises(IndexError, p.__getitem__, 3)
 
254
 
 
255
        self.assertEqual(p.x, x)
 
256
        self.assertEqual(p.y, y)
 
257
        self.assertRaises(AttributeError, eval, 'p.z', locals())
 
258
 
 
259
    def test_odd_sizes(self):
 
260
        Zero = namedtuple('Zero', '')
 
261
        self.assertEqual(Zero(), ())
 
262
        self.assertEqual(Zero._make([]), ())
 
263
        self.assertEqual(repr(Zero()), 'Zero()')
 
264
        self.assertEqual(Zero()._asdict(), {})
 
265
        self.assertEqual(Zero()._fields, ())
 
266
 
 
267
        Dot = namedtuple('Dot', 'd')
 
268
        self.assertEqual(Dot(1), (1,))
 
269
        self.assertEqual(Dot._make([1]), (1,))
 
270
        self.assertEqual(Dot(1).d, 1)
 
271
        self.assertEqual(repr(Dot(1)), 'Dot(d=1)')
 
272
        self.assertEqual(Dot(1)._asdict(), {'d':1})
 
273
        self.assertEqual(Dot(1)._replace(d=999), (999,))
 
274
        self.assertEqual(Dot(1)._fields, ('d',))
 
275
 
 
276
        # n = 5000
 
277
        n = 254 # SyntaxError: more than 255 arguments:
 
278
        import string, random
 
279
        names = list(set(''.join([random.choice(string.ascii_letters)
 
280
                                  for j in range(10)]) for i in range(n)))
 
281
        n = len(names)
 
282
        Big = namedtuple('Big', names)
 
283
        b = Big(*range(n))
 
284
        self.assertEqual(b, tuple(range(n)))
 
285
        self.assertEqual(Big._make(range(n)), tuple(range(n)))
 
286
        for pos, name in enumerate(names):
 
287
            self.assertEqual(getattr(b, name), pos)
 
288
        repr(b)                                 # make sure repr() doesn't blow-up
 
289
        d = b._asdict()
 
290
        d_expected = dict(zip(names, range(n)))
 
291
        self.assertEqual(d, d_expected)
 
292
        b2 = b._replace(**dict([(names[1], 999),(names[-5], 42)]))
 
293
        b2_expected = list(range(n))
 
294
        b2_expected[1] = 999
 
295
        b2_expected[-5] = 42
 
296
        self.assertEqual(b2, tuple(b2_expected))
 
297
        self.assertEqual(b._fields, tuple(names))
 
298
 
 
299
    def test_pickle(self):
 
300
        p = TestNT(x=10, y=20, z=30)
 
301
        for module in (pickle,):
 
302
            loads = getattr(module, 'loads')
 
303
            dumps = getattr(module, 'dumps')
 
304
            for protocol in -1, 0, 1, 2:
 
305
                q = loads(dumps(p, protocol))
 
306
                self.assertEqual(p, q)
 
307
                self.assertEqual(p._fields, q._fields)
 
308
                self.assertNotIn(b'OrderedDict', dumps(p, protocol))
 
309
 
 
310
    def test_copy(self):
 
311
        p = TestNT(x=10, y=20, z=30)
 
312
        for copier in copy.copy, copy.deepcopy:
 
313
            q = copier(p)
 
314
            self.assertEqual(p, q)
 
315
            self.assertEqual(p._fields, q._fields)
 
316
 
 
317
    def test_name_conflicts(self):
 
318
        # Some names like "self", "cls", "tuple", "itemgetter", and "property"
 
319
        # failed when used as field names.  Test to make sure these now work.
 
320
        T = namedtuple('T', 'itemgetter property self cls tuple')
 
321
        t = T(1, 2, 3, 4, 5)
 
322
        self.assertEqual(t, (1,2,3,4,5))
 
323
        newt = t._replace(itemgetter=10, property=20, self=30, cls=40, tuple=50)
 
324
        self.assertEqual(newt, (10,20,30,40,50))
 
325
 
 
326
        # Broader test of all interesting names in a template
 
327
        with support.captured_stdout() as template:
 
328
            T = namedtuple('T', 'x', verbose=True)
 
329
        words = set(re.findall('[A-Za-z]+', template.getvalue()))
 
330
        words -= set(keyword.kwlist)
 
331
        T = namedtuple('T', words)
 
332
        # test __new__
 
333
        values = tuple(range(len(words)))
 
334
        t = T(*values)
 
335
        self.assertEqual(t, values)
 
336
        t = T(**dict(zip(T._fields, values)))
 
337
        self.assertEqual(t, values)
 
338
        # test _make
 
339
        t = T._make(values)
 
340
        self.assertEqual(t, values)
 
341
        # exercise __repr__
 
342
        repr(t)
 
343
        # test _asdict
 
344
        self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
 
345
        # test _replace
 
346
        t = T._make(values)
 
347
        newvalues = tuple(v*10 for v in values)
 
348
        newt = t._replace(**dict(zip(T._fields, newvalues)))
 
349
        self.assertEqual(newt, newvalues)
 
350
        # test _fields
 
351
        self.assertEqual(T._fields, tuple(words))
 
352
        # test __getnewargs__
 
353
        self.assertEqual(t.__getnewargs__(), values)
 
354
 
 
355
    def test_repr(self):
 
356
        with support.captured_stdout() as template:
 
357
            A = namedtuple('A', 'x', verbose=True)
 
358
        self.assertEqual(repr(A(1)), 'A(x=1)')
 
359
        # repr should show the name of the subclass
 
360
        class B(A):
 
361
            pass
 
362
        self.assertEqual(repr(B(1)), 'B(x=1)')
 
363
 
 
364
    def test_source(self):
 
365
        # verify that _source can be run through exec()
 
366
        tmp = namedtuple('NTColor', 'red green blue')
 
367
        globals().pop('NTColor', None)          # remove artifacts from other tests
 
368
        exec(tmp._source, globals())
 
369
        self.assertIn('NTColor', globals())
 
370
        c = NTColor(10, 20, 30)
 
371
        self.assertEqual((c.red, c.green, c.blue), (10, 20, 30))
 
372
        self.assertEqual(NTColor._fields, ('red', 'green', 'blue'))
 
373
        globals().pop('NTColor', None)          # clean-up after this test
 
374
 
 
375
 
 
376
################################################################################
 
377
### Abstract Base Classes
 
378
################################################################################
 
379
 
 
380
class ABCTestCase(unittest.TestCase):
 
381
 
 
382
    def validate_abstract_methods(self, abc, *names):
 
383
        methodstubs = dict.fromkeys(names, lambda s, *args: 0)
 
384
 
 
385
        # everything should work will all required methods are present
 
386
        C = type('C', (abc,), methodstubs)
 
387
        C()
 
388
 
 
389
        # instantiation should fail if a required method is missing
 
390
        for name in names:
 
391
            stubs = methodstubs.copy()
 
392
            del stubs[name]
 
393
            C = type('C', (abc,), stubs)
 
394
            self.assertRaises(TypeError, C, name)
 
395
 
 
396
    def validate_isinstance(self, abc, name):
 
397
        stub = lambda s, *args: 0
 
398
 
 
399
        C = type('C', (object,), {'__hash__': None})
 
400
        setattr(C, name, stub)
 
401
        self.assertIsInstance(C(), abc)
 
402
        self.assertTrue(issubclass(C, abc))
 
403
 
 
404
        C = type('C', (object,), {'__hash__': None})
 
405
        self.assertNotIsInstance(C(), abc)
 
406
        self.assertFalse(issubclass(C, abc))
 
407
 
 
408
    def validate_comparison(self, instance):
 
409
        ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
 
410
        operators = {}
 
411
        for op in ops:
 
412
            name = '__' + op + '__'
 
413
            operators[name] = getattr(operator, name)
 
414
 
 
415
        class Other:
 
416
            def __init__(self):
 
417
                self.right_side = False
 
418
            def __eq__(self, other):
 
419
                self.right_side = True
 
420
                return True
 
421
            __lt__ = __eq__
 
422
            __gt__ = __eq__
 
423
            __le__ = __eq__
 
424
            __ge__ = __eq__
 
425
            __ne__ = __eq__
 
426
            __ror__ = __eq__
 
427
            __rand__ = __eq__
 
428
            __rxor__ = __eq__
 
429
            __rsub__ = __eq__
 
430
 
 
431
        for name, op in operators.items():
 
432
            if not hasattr(instance, name):
 
433
                continue
 
434
            other = Other()
 
435
            op(instance, other)
 
436
            self.assertTrue(other.right_side,'Right side not called for %s.%s'
 
437
                            % (type(instance), name))
 
438
 
 
439
class TestOneTrickPonyABCs(ABCTestCase):
 
440
 
 
441
    def test_Hashable(self):
 
442
        # Check some non-hashables
 
443
        non_samples = [bytearray(), list(), set(), dict()]
 
444
        for x in non_samples:
 
445
            self.assertNotIsInstance(x, Hashable)
 
446
            self.assertFalse(issubclass(type(x), Hashable), repr(type(x)))
 
447
        # Check some hashables
 
448
        samples = [None,
 
449
                   int(), float(), complex(),
 
450
                   str(),
 
451
                   tuple(), frozenset(),
 
452
                   int, list, object, type, bytes()
 
453
                   ]
 
454
        for x in samples:
 
455
            self.assertIsInstance(x, Hashable)
 
456
            self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
 
457
        self.assertRaises(TypeError, Hashable)
 
458
        # Check direct subclassing
 
459
        class H(Hashable):
 
460
            def __hash__(self):
 
461
                return super().__hash__()
 
462
        self.assertEqual(hash(H()), 0)
 
463
        self.assertFalse(issubclass(int, H))
 
464
        self.validate_abstract_methods(Hashable, '__hash__')
 
465
        self.validate_isinstance(Hashable, '__hash__')
 
466
 
 
467
    def test_Iterable(self):
 
468
        # Check some non-iterables
 
469
        non_samples = [None, 42, 3.14, 1j]
 
470
        for x in non_samples:
 
471
            self.assertNotIsInstance(x, Iterable)
 
472
            self.assertFalse(issubclass(type(x), Iterable), repr(type(x)))
 
473
        # Check some iterables
 
474
        samples = [bytes(), str(),
 
475
                   tuple(), list(), set(), frozenset(), dict(),
 
476
                   dict().keys(), dict().items(), dict().values(),
 
477
                   (lambda: (yield))(),
 
478
                   (x for x in []),
 
479
                   ]
 
480
        for x in samples:
 
481
            self.assertIsInstance(x, Iterable)
 
482
            self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
 
483
        # Check direct subclassing
 
484
        class I(Iterable):
 
485
            def __iter__(self):
 
486
                return super().__iter__()
 
487
        self.assertEqual(list(I()), [])
 
488
        self.assertFalse(issubclass(str, I))
 
489
        self.validate_abstract_methods(Iterable, '__iter__')
 
490
        self.validate_isinstance(Iterable, '__iter__')
 
491
 
 
492
    def test_Iterator(self):
 
493
        non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()]
 
494
        for x in non_samples:
 
495
            self.assertNotIsInstance(x, Iterator)
 
496
            self.assertFalse(issubclass(type(x), Iterator), repr(type(x)))
 
497
        samples = [iter(bytes()), iter(str()),
 
498
                   iter(tuple()), iter(list()), iter(dict()),
 
499
                   iter(set()), iter(frozenset()),
 
500
                   iter(dict().keys()), iter(dict().items()),
 
501
                   iter(dict().values()),
 
502
                   (lambda: (yield))(),
 
503
                   (x for x in []),
 
504
                   ]
 
505
        for x in samples:
 
506
            self.assertIsInstance(x, Iterator)
 
507
            self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
 
508
        self.validate_abstract_methods(Iterator, '__next__', '__iter__')
 
509
 
 
510
        # Issue 10565
 
511
        class NextOnly:
 
512
            def __next__(self):
 
513
                yield 1
 
514
                raise StopIteration
 
515
        self.assertNotIsInstance(NextOnly(), Iterator)
 
516
 
 
517
    def test_Sized(self):
 
518
        non_samples = [None, 42, 3.14, 1j,
 
519
                       (lambda: (yield))(),
 
520
                       (x for x in []),
 
521
                       ]
 
522
        for x in non_samples:
 
523
            self.assertNotIsInstance(x, Sized)
 
524
            self.assertFalse(issubclass(type(x), Sized), repr(type(x)))
 
525
        samples = [bytes(), str(),
 
526
                   tuple(), list(), set(), frozenset(), dict(),
 
527
                   dict().keys(), dict().items(), dict().values(),
 
528
                   ]
 
529
        for x in samples:
 
530
            self.assertIsInstance(x, Sized)
 
531
            self.assertTrue(issubclass(type(x), Sized), repr(type(x)))
 
532
        self.validate_abstract_methods(Sized, '__len__')
 
533
        self.validate_isinstance(Sized, '__len__')
 
534
 
 
535
    def test_Container(self):
 
536
        non_samples = [None, 42, 3.14, 1j,
 
537
                       (lambda: (yield))(),
 
538
                       (x for x in []),
 
539
                       ]
 
540
        for x in non_samples:
 
541
            self.assertNotIsInstance(x, Container)
 
542
            self.assertFalse(issubclass(type(x), Container), repr(type(x)))
 
543
        samples = [bytes(), str(),
 
544
                   tuple(), list(), set(), frozenset(), dict(),
 
545
                   dict().keys(), dict().items(),
 
546
                   ]
 
547
        for x in samples:
 
548
            self.assertIsInstance(x, Container)
 
549
            self.assertTrue(issubclass(type(x), Container), repr(type(x)))
 
550
        self.validate_abstract_methods(Container, '__contains__')
 
551
        self.validate_isinstance(Container, '__contains__')
 
552
 
 
553
    def test_Callable(self):
 
554
        non_samples = [None, 42, 3.14, 1j,
 
555
                       "", b"", (), [], {}, set(),
 
556
                       (lambda: (yield))(),
 
557
                       (x for x in []),
 
558
                       ]
 
559
        for x in non_samples:
 
560
            self.assertNotIsInstance(x, Callable)
 
561
            self.assertFalse(issubclass(type(x), Callable), repr(type(x)))
 
562
        samples = [lambda: None,
 
563
                   type, int, object,
 
564
                   len,
 
565
                   list.append, [].append,
 
566
                   ]
 
567
        for x in samples:
 
568
            self.assertIsInstance(x, Callable)
 
569
            self.assertTrue(issubclass(type(x), Callable), repr(type(x)))
 
570
        self.validate_abstract_methods(Callable, '__call__')
 
571
        self.validate_isinstance(Callable, '__call__')
 
572
 
 
573
    def test_direct_subclassing(self):
 
574
        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
 
575
            class C(B):
 
576
                pass
 
577
            self.assertTrue(issubclass(C, B))
 
578
            self.assertFalse(issubclass(int, C))
 
579
 
 
580
    def test_registration(self):
 
581
        for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
 
582
            class C:
 
583
                __hash__ = None  # Make sure it isn't hashable by default
 
584
            self.assertFalse(issubclass(C, B), B.__name__)
 
585
            B.register(C)
 
586
            self.assertTrue(issubclass(C, B))
 
587
 
 
588
class WithSet(MutableSet):
 
589
 
 
590
    def __init__(self, it=()):
 
591
        self.data = set(it)
 
592
 
 
593
    def __len__(self):
 
594
        return len(self.data)
 
595
 
 
596
    def __iter__(self):
 
597
        return iter(self.data)
 
598
 
 
599
    def __contains__(self, item):
 
600
        return item in self.data
 
601
 
 
602
    def add(self, item):
 
603
        self.data.add(item)
 
604
 
 
605
    def discard(self, item):
 
606
        self.data.discard(item)
 
607
 
 
608
class TestCollectionABCs(ABCTestCase):
 
609
 
 
610
    # XXX For now, we only test some virtual inheritance properties.
 
611
    # We should also test the proper behavior of the collection ABCs
 
612
    # as real base classes or mix-in classes.
 
613
 
 
614
    def test_Set(self):
 
615
        for sample in [set, frozenset]:
 
616
            self.assertIsInstance(sample(), Set)
 
617
            self.assertTrue(issubclass(sample, Set))
 
618
        self.validate_abstract_methods(Set, '__contains__', '__iter__', '__len__')
 
619
        class MySet(Set):
 
620
            def __contains__(self, x):
 
621
                return False
 
622
            def __len__(self):
 
623
                return 0
 
624
            def __iter__(self):
 
625
                return iter([])
 
626
        self.validate_comparison(MySet())
 
627
 
 
628
    def test_hash_Set(self):
 
629
        class OneTwoThreeSet(Set):
 
630
            def __init__(self):
 
631
                self.contents = [1, 2, 3]
 
632
            def __contains__(self, x):
 
633
                return x in self.contents
 
634
            def __len__(self):
 
635
                return len(self.contents)
 
636
            def __iter__(self):
 
637
                return iter(self.contents)
 
638
            def __hash__(self):
 
639
                return self._hash()
 
640
        a, b = OneTwoThreeSet(), OneTwoThreeSet()
 
641
        self.assertTrue(hash(a) == hash(b))
 
642
 
 
643
    def test_MutableSet(self):
 
644
        self.assertIsInstance(set(), MutableSet)
 
645
        self.assertTrue(issubclass(set, MutableSet))
 
646
        self.assertNotIsInstance(frozenset(), MutableSet)
 
647
        self.assertFalse(issubclass(frozenset, MutableSet))
 
648
        self.validate_abstract_methods(MutableSet, '__contains__', '__iter__', '__len__',
 
649
            'add', 'discard')
 
650
 
 
651
    def test_issue_5647(self):
 
652
        # MutableSet.__iand__ mutated the set during iteration
 
653
        s = WithSet('abcd')
 
654
        s &= WithSet('cdef')            # This used to fail
 
655
        self.assertEqual(set(s), set('cd'))
 
656
 
 
657
    def test_issue_4920(self):
 
658
        # MutableSet.pop() method did not work
 
659
        class MySet(MutableSet):
 
660
            __slots__=['__s']
 
661
            def __init__(self,items=None):
 
662
                if items is None:
 
663
                    items=[]
 
664
                self.__s=set(items)
 
665
            def __contains__(self,v):
 
666
                return v in self.__s
 
667
            def __iter__(self):
 
668
                return iter(self.__s)
 
669
            def __len__(self):
 
670
                return len(self.__s)
 
671
            def add(self,v):
 
672
                result=v not in self.__s
 
673
                self.__s.add(v)
 
674
                return result
 
675
            def discard(self,v):
 
676
                result=v in self.__s
 
677
                self.__s.discard(v)
 
678
                return result
 
679
            def __repr__(self):
 
680
                return "MySet(%s)" % repr(list(self))
 
681
        s = MySet([5,43,2,1])
 
682
        self.assertEqual(s.pop(), 1)
 
683
 
 
684
    def test_issue8750(self):
 
685
        empty = WithSet()
 
686
        full = WithSet(range(10))
 
687
        s = WithSet(full)
 
688
        s -= s
 
689
        self.assertEqual(s, empty)
 
690
        s = WithSet(full)
 
691
        s ^= s
 
692
        self.assertEqual(s, empty)
 
693
        s = WithSet(full)
 
694
        s &= s
 
695
        self.assertEqual(s, full)
 
696
        s |= s
 
697
        self.assertEqual(s, full)
 
698
 
 
699
    def test_issue16373(self):
 
700
        # Recursion error comparing comparable and noncomparable
 
701
        # Set instances
 
702
        class MyComparableSet(Set):
 
703
            def __contains__(self, x):
 
704
                return False
 
705
            def __len__(self):
 
706
                return 0
 
707
            def __iter__(self):
 
708
                return iter([])
 
709
        class MyNonComparableSet(Set):
 
710
            def __contains__(self, x):
 
711
                return False
 
712
            def __len__(self):
 
713
                return 0
 
714
            def __iter__(self):
 
715
                return iter([])
 
716
            def __le__(self, x):
 
717
                return NotImplemented
 
718
            def __lt__(self, x):
 
719
                return NotImplemented
 
720
 
 
721
        cs = MyComparableSet()
 
722
        ncs = MyNonComparableSet()
 
723
        with self.assertRaises(TypeError):
 
724
            ncs < cs
 
725
        with self.assertRaises(TypeError):
 
726
            ncs <= cs
 
727
        with self.assertRaises(TypeError):
 
728
            cs > ncs
 
729
        with self.assertRaises(TypeError):
 
730
            cs >= ncs
 
731
 
 
732
    def test_Mapping(self):
 
733
        for sample in [dict]:
 
734
            self.assertIsInstance(sample(), Mapping)
 
735
            self.assertTrue(issubclass(sample, Mapping))
 
736
        self.validate_abstract_methods(Mapping, '__contains__', '__iter__', '__len__',
 
737
            '__getitem__')
 
738
        class MyMapping(Mapping):
 
739
            def __len__(self):
 
740
                return 0
 
741
            def __getitem__(self, i):
 
742
                raise IndexError
 
743
            def __iter__(self):
 
744
                return iter(())
 
745
        self.validate_comparison(MyMapping())
 
746
 
 
747
    def test_MutableMapping(self):
 
748
        for sample in [dict]:
 
749
            self.assertIsInstance(sample(), MutableMapping)
 
750
            self.assertTrue(issubclass(sample, MutableMapping))
 
751
        self.validate_abstract_methods(MutableMapping, '__contains__', '__iter__', '__len__',
 
752
            '__getitem__', '__setitem__', '__delitem__')
 
753
 
 
754
    def test_MutableMapping_subclass(self):
 
755
        # Test issue 9214
 
756
        mymap = UserDict()
 
757
        mymap['red'] = 5
 
758
        self.assertIsInstance(mymap.keys(), Set)
 
759
        self.assertIsInstance(mymap.keys(), KeysView)
 
760
        self.assertIsInstance(mymap.items(), Set)
 
761
        self.assertIsInstance(mymap.items(), ItemsView)
 
762
 
 
763
        mymap = UserDict()
 
764
        mymap['red'] = 5
 
765
        z = mymap.keys() | {'orange'}
 
766
        self.assertIsInstance(z, set)
 
767
        list(z)
 
768
        mymap['blue'] = 7               # Shouldn't affect 'z'
 
769
        self.assertEqual(sorted(z), ['orange', 'red'])
 
770
 
 
771
        mymap = UserDict()
 
772
        mymap['red'] = 5
 
773
        z = mymap.items() | {('orange', 3)}
 
774
        self.assertIsInstance(z, set)
 
775
        list(z)
 
776
        mymap['blue'] = 7               # Shouldn't affect 'z'
 
777
        self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
 
778
 
 
779
    def test_Sequence(self):
 
780
        for sample in [tuple, list, bytes, str]:
 
781
            self.assertIsInstance(sample(), Sequence)
 
782
            self.assertTrue(issubclass(sample, Sequence))
 
783
        self.assertIsInstance(range(10), Sequence)
 
784
        self.assertTrue(issubclass(range, Sequence))
 
785
        self.assertIsInstance(memoryview(b""), Sequence)
 
786
        self.assertTrue(issubclass(memoryview, Sequence))
 
787
        self.assertTrue(issubclass(str, Sequence))
 
788
        self.validate_abstract_methods(Sequence, '__contains__', '__iter__', '__len__',
 
789
            '__getitem__')
 
790
 
 
791
    def test_ByteString(self):
 
792
        for sample in [bytes, bytearray]:
 
793
            self.assertIsInstance(sample(), ByteString)
 
794
            self.assertTrue(issubclass(sample, ByteString))
 
795
        for sample in [str, list, tuple]:
 
796
            self.assertNotIsInstance(sample(), ByteString)
 
797
            self.assertFalse(issubclass(sample, ByteString))
 
798
        self.assertNotIsInstance(memoryview(b""), ByteString)
 
799
        self.assertFalse(issubclass(memoryview, ByteString))
 
800
 
 
801
    def test_MutableSequence(self):
 
802
        for sample in [tuple, str, bytes]:
 
803
            self.assertNotIsInstance(sample(), MutableSequence)
 
804
            self.assertFalse(issubclass(sample, MutableSequence))
 
805
        for sample in [list, bytearray]:
 
806
            self.assertIsInstance(sample(), MutableSequence)
 
807
            self.assertTrue(issubclass(sample, MutableSequence))
 
808
        self.assertFalse(issubclass(str, MutableSequence))
 
809
        self.validate_abstract_methods(MutableSequence, '__contains__', '__iter__',
 
810
            '__len__', '__getitem__', '__setitem__', '__delitem__', 'insert')
 
811
 
 
812
    def test_MutableSequence_mixins(self):
 
813
        # Test the mixins of MutableSequence by creating a miminal concrete
 
814
        # class inherited from it.
 
815
        class MutableSequenceSubclass(MutableSequence):
 
816
            def __init__(self):
 
817
                self.lst = []
 
818
 
 
819
            def __setitem__(self, index, value):
 
820
                self.lst[index] = value
 
821
 
 
822
            def __getitem__(self, index):
 
823
                return self.lst[index]
 
824
 
 
825
            def __len__(self):
 
826
                return len(self.lst)
 
827
 
 
828
            def __delitem__(self, index):
 
829
                del self.lst[index]
 
830
 
 
831
            def insert(self, index, value):
 
832
                self.lst.insert(index, value)
 
833
 
 
834
        mss = MutableSequenceSubclass()
 
835
        mss.append(0)
 
836
        mss.extend((1, 2, 3, 4))
 
837
        self.assertEqual(len(mss), 5)
 
838
        self.assertEqual(mss[3], 3)
 
839
        mss.reverse()
 
840
        self.assertEqual(mss[3], 1)
 
841
        mss.pop()
 
842
        self.assertEqual(len(mss), 4)
 
843
        mss.remove(3)
 
844
        self.assertEqual(len(mss), 3)
 
845
        mss += (10, 20, 30)
 
846
        self.assertEqual(len(mss), 6)
 
847
        self.assertEqual(mss[-1], 30)
 
848
        mss.clear()
 
849
        self.assertEqual(len(mss), 0)
 
850
 
 
851
################################################################################
 
852
### Counter
 
853
################################################################################
 
854
 
 
855
class CounterSubclassWithSetItem(Counter):
 
856
    # Test a counter subclass that overrides __setitem__
 
857
    def __init__(self, *args, **kwds):
 
858
        self.called = False
 
859
        Counter.__init__(self, *args, **kwds)
 
860
    def __setitem__(self, key, value):
 
861
        self.called = True
 
862
        Counter.__setitem__(self, key, value)
 
863
 
 
864
class CounterSubclassWithGet(Counter):
 
865
    # Test a counter subclass that overrides get()
 
866
    def __init__(self, *args, **kwds):
 
867
        self.called = False
 
868
        Counter.__init__(self, *args, **kwds)
 
869
    def get(self, key, default):
 
870
        self.called = True
 
871
        return Counter.get(self, key, default)
 
872
 
 
873
class TestCounter(unittest.TestCase):
 
874
 
 
875
    def test_basics(self):
 
876
        c = Counter('abcaba')
 
877
        self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
 
878
        self.assertEqual(c, Counter(a=3, b=2, c=1))
 
879
        self.assertIsInstance(c, dict)
 
880
        self.assertIsInstance(c, Mapping)
 
881
        self.assertTrue(issubclass(Counter, dict))
 
882
        self.assertTrue(issubclass(Counter, Mapping))
 
883
        self.assertEqual(len(c), 3)
 
884
        self.assertEqual(sum(c.values()), 6)
 
885
        self.assertEqual(sorted(c.values()), [1, 2, 3])
 
886
        self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
 
887
        self.assertEqual(sorted(c), ['a', 'b', 'c'])
 
888
        self.assertEqual(sorted(c.items()),
 
889
                         [('a', 3), ('b', 2), ('c', 1)])
 
890
        self.assertEqual(c['b'], 2)
 
891
        self.assertEqual(c['z'], 0)
 
892
        self.assertEqual(c.__contains__('c'), True)
 
893
        self.assertEqual(c.__contains__('z'), False)
 
894
        self.assertEqual(c.get('b', 10), 2)
 
895
        self.assertEqual(c.get('z', 10), 10)
 
896
        self.assertEqual(c, dict(a=3, b=2, c=1))
 
897
        self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
 
898
        self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
 
899
        for i in range(5):
 
900
            self.assertEqual(c.most_common(i),
 
901
                             [('a', 3), ('b', 2), ('c', 1)][:i])
 
902
        self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
 
903
        c['a'] += 1         # increment an existing value
 
904
        c['b'] -= 2         # sub existing value to zero
 
905
        del c['c']          # remove an entry
 
906
        del c['c']          # make sure that del doesn't raise KeyError
 
907
        c['d'] -= 2         # sub from a missing value
 
908
        c['e'] = -5         # directly assign a missing value
 
909
        c['f'] += 4         # add to a missing value
 
910
        self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
 
911
        self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
 
912
        self.assertEqual(c.pop('f'), 4)
 
913
        self.assertNotIn('f', c)
 
914
        for i in range(3):
 
915
            elem, cnt = c.popitem()
 
916
            self.assertNotIn(elem, c)
 
917
        c.clear()
 
918
        self.assertEqual(c, {})
 
919
        self.assertEqual(repr(c), 'Counter()')
 
920
        self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
 
921
        self.assertRaises(TypeError, hash, c)
 
922
        c.update(dict(a=5, b=3))
 
923
        c.update(c=1)
 
924
        c.update(Counter('a' * 50 + 'b' * 30))
 
925
        c.update()          # test case with no args
 
926
        c.__init__('a' * 500 + 'b' * 300)
 
927
        c.__init__('cdc')
 
928
        c.__init__()
 
929
        self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
 
930
        self.assertEqual(c.setdefault('d', 5), 1)
 
931
        self.assertEqual(c['d'], 1)
 
932
        self.assertEqual(c.setdefault('e', 5), 5)
 
933
        self.assertEqual(c['e'], 5)
 
934
 
 
935
    def test_copying(self):
 
936
        # Check that counters are copyable, deepcopyable, picklable, and
 
937
        #have a repr/eval round-trip
 
938
        words = Counter('which witch had which witches wrist watch'.split())
 
939
        update_test = Counter()
 
940
        update_test.update(words)
 
941
        for label, dup in [
 
942
                    ('words.copy()', words.copy()),
 
943
                    ('copy.copy(words)', copy.copy(words)),
 
944
                    ('copy.deepcopy(words)', copy.deepcopy(words)),
 
945
                    ('pickle.loads(pickle.dumps(words, 0))',
 
946
                        pickle.loads(pickle.dumps(words, 0))),
 
947
                    ('pickle.loads(pickle.dumps(words, 1))',
 
948
                        pickle.loads(pickle.dumps(words, 1))),
 
949
                    ('pickle.loads(pickle.dumps(words, 2))',
 
950
                        pickle.loads(pickle.dumps(words, 2))),
 
951
                    ('pickle.loads(pickle.dumps(words, -1))',
 
952
                        pickle.loads(pickle.dumps(words, -1))),
 
953
                    ('eval(repr(words))', eval(repr(words))),
 
954
                    ('update_test', update_test),
 
955
                    ('Counter(words)', Counter(words)),
 
956
                    ]:
 
957
            with self.subTest(label=label):
 
958
                msg = "\ncopy: %s\nwords: %s" % (dup, words)
 
959
                self.assertIsNot(dup, words, msg)
 
960
                self.assertEqual(dup, words)
 
961
 
 
962
    def test_copy_subclass(self):
 
963
        class MyCounter(Counter):
 
964
            pass
 
965
        c = MyCounter('slartibartfast')
 
966
        d = c.copy()
 
967
        self.assertEqual(d, c)
 
968
        self.assertEqual(len(d), len(c))
 
969
        self.assertEqual(type(d), type(c))
 
970
 
 
971
    def test_conversions(self):
 
972
        # Convert to: set, list, dict
 
973
        s = 'she sells sea shells by the sea shore'
 
974
        self.assertEqual(sorted(Counter(s).elements()), sorted(s))
 
975
        self.assertEqual(sorted(Counter(s)), sorted(set(s)))
 
976
        self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
 
977
        self.assertEqual(set(Counter(s)), set(s))
 
978
 
 
979
    def test_invariant_for_the_in_operator(self):
 
980
        c = Counter(a=10, b=-2, c=0)
 
981
        for elem in c:
 
982
            self.assertTrue(elem in c)
 
983
            self.assertIn(elem, c)
 
984
 
 
985
    def test_multiset_operations(self):
 
986
        # Verify that adding a zero counter will strip zeros and negatives
 
987
        c = Counter(a=10, b=-2, c=0) + Counter()
 
988
        self.assertEqual(dict(c), dict(a=10))
 
989
 
 
990
        elements = 'abcd'
 
991
        for i in range(1000):
 
992
            # test random pairs of multisets
 
993
            p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
 
994
            p.update(e=1, f=-1, g=0)
 
995
            q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
 
996
            q.update(h=1, i=-1, j=0)
 
997
            for counterop, numberop in [
 
998
                (Counter.__add__, lambda x, y: max(0, x+y)),
 
999
                (Counter.__sub__, lambda x, y: max(0, x-y)),
 
1000
                (Counter.__or__, lambda x, y: max(0,x,y)),
 
1001
                (Counter.__and__, lambda x, y: max(0, min(x,y))),
 
1002
            ]:
 
1003
                result = counterop(p, q)
 
1004
                for x in elements:
 
1005
                    self.assertEqual(numberop(p[x], q[x]), result[x],
 
1006
                                     (counterop, x, p, q))
 
1007
                # verify that results exclude non-positive counts
 
1008
                self.assertTrue(x>0 for x in result.values())
 
1009
 
 
1010
        elements = 'abcdef'
 
1011
        for i in range(100):
 
1012
            # verify that random multisets with no repeats are exactly like sets
 
1013
            p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
 
1014
            q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
 
1015
            for counterop, setop in [
 
1016
                (Counter.__sub__, set.__sub__),
 
1017
                (Counter.__or__, set.__or__),
 
1018
                (Counter.__and__, set.__and__),
 
1019
            ]:
 
1020
                counter_result = counterop(p, q)
 
1021
                set_result = setop(set(p.elements()), set(q.elements()))
 
1022
                self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
 
1023
 
 
1024
    def test_inplace_operations(self):
 
1025
        elements = 'abcd'
 
1026
        for i in range(1000):
 
1027
            # test random pairs of multisets
 
1028
            p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
 
1029
            p.update(e=1, f=-1, g=0)
 
1030
            q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
 
1031
            q.update(h=1, i=-1, j=0)
 
1032
            for inplace_op, regular_op in [
 
1033
                (Counter.__iadd__, Counter.__add__),
 
1034
                (Counter.__isub__, Counter.__sub__),
 
1035
                (Counter.__ior__, Counter.__or__),
 
1036
                (Counter.__iand__, Counter.__and__),
 
1037
            ]:
 
1038
                c = p.copy()
 
1039
                c_id = id(c)
 
1040
                regular_result = regular_op(c, q)
 
1041
                inplace_result = inplace_op(c, q)
 
1042
                self.assertEqual(inplace_result, regular_result)
 
1043
                self.assertEqual(id(inplace_result), c_id)
 
1044
 
 
1045
    def test_subtract(self):
 
1046
        c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
 
1047
        c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
 
1048
        self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
 
1049
        c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
 
1050
        c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
 
1051
        self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
 
1052
        c = Counter('aaabbcd')
 
1053
        c.subtract('aaaabbcce')
 
1054
        self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
 
1055
 
 
1056
    def test_unary(self):
 
1057
        c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
 
1058
        self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
 
1059
        self.assertEqual(dict(-c), dict(a=5))
 
1060
 
 
1061
    def test_repr_nonsortable(self):
 
1062
        c = Counter(a=2, b=None)
 
1063
        r = repr(c)
 
1064
        self.assertIn("'a': 2", r)
 
1065
        self.assertIn("'b': None", r)
 
1066
 
 
1067
    def test_helper_function(self):
 
1068
        # two paths, one for real dicts and one for other mappings
 
1069
        elems = list('abracadabra')
 
1070
 
 
1071
        d = dict()
 
1072
        _count_elements(d, elems)
 
1073
        self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
 
1074
 
 
1075
        m = OrderedDict()
 
1076
        _count_elements(m, elems)
 
1077
        self.assertEqual(m,
 
1078
             OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
 
1079
 
 
1080
        # test fidelity to the pure python version
 
1081
        c = CounterSubclassWithSetItem('abracadabra')
 
1082
        self.assertTrue(c.called)
 
1083
        self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
 
1084
        c = CounterSubclassWithGet('abracadabra')
 
1085
        self.assertTrue(c.called)
 
1086
        self.assertEqual(dict(c), {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r':2 })
 
1087
 
 
1088
 
 
1089
################################################################################
 
1090
### OrderedDict
 
1091
################################################################################
 
1092
 
 
1093
class TestOrderedDict(unittest.TestCase):
 
1094
 
 
1095
    def test_init(self):
 
1096
        with self.assertRaises(TypeError):
 
1097
            OrderedDict([('a', 1), ('b', 2)], None)                                 # too many args
 
1098
        pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
 
1099
        self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs)           # dict input
 
1100
        self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs)         # kwds input
 
1101
        self.assertEqual(list(OrderedDict(pairs).items()), pairs)                   # pairs input
 
1102
        self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
 
1103
                                          c=3, e=5).items()), pairs)                # mixed input
 
1104
 
 
1105
        # make sure no positional args conflict with possible kwdargs
 
1106
        self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
 
1107
                         ['self'])
 
1108
 
 
1109
        # Make sure that direct calls to __init__ do not clear previous contents
 
1110
        d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
 
1111
        d.__init__([('e', 5), ('f', 6)], g=7, d=4)
 
1112
        self.assertEqual(list(d.items()),
 
1113
            [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
 
1114
 
 
1115
    def test_update(self):
 
1116
        with self.assertRaises(TypeError):
 
1117
            OrderedDict().update([('a', 1), ('b', 2)], None)                        # too many args
 
1118
        pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
 
1119
        od = OrderedDict()
 
1120
        od.update(dict(pairs))
 
1121
        self.assertEqual(sorted(od.items()), pairs)                                 # dict input
 
1122
        od = OrderedDict()
 
1123
        od.update(**dict(pairs))
 
1124
        self.assertEqual(sorted(od.items()), pairs)                                 # kwds input
 
1125
        od = OrderedDict()
 
1126
        od.update(pairs)
 
1127
        self.assertEqual(list(od.items()), pairs)                                   # pairs input
 
1128
        od = OrderedDict()
 
1129
        od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
 
1130
        self.assertEqual(list(od.items()), pairs)                                   # mixed input
 
1131
 
 
1132
        # Issue 9137: Named argument called 'other' or 'self'
 
1133
        # shouldn't be treated specially.
 
1134
        od = OrderedDict()
 
1135
        od.update(self=23)
 
1136
        self.assertEqual(list(od.items()), [('self', 23)])
 
1137
        od = OrderedDict()
 
1138
        od.update(other={})
 
1139
        self.assertEqual(list(od.items()), [('other', {})])
 
1140
        od = OrderedDict()
 
1141
        od.update(red=5, blue=6, other=7, self=8)
 
1142
        self.assertEqual(sorted(list(od.items())),
 
1143
                         [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
 
1144
 
 
1145
        # Make sure that direct calls to update do not clear previous contents
 
1146
        # add that updates items are not moved to the end
 
1147
        d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
 
1148
        d.update([('e', 5), ('f', 6)], g=7, d=4)
 
1149
        self.assertEqual(list(d.items()),
 
1150
            [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
 
1151
 
 
1152
    def test_abc(self):
 
1153
        self.assertIsInstance(OrderedDict(), MutableMapping)
 
1154
        self.assertTrue(issubclass(OrderedDict, MutableMapping))
 
1155
 
 
1156
    def test_clear(self):
 
1157
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1158
        shuffle(pairs)
 
1159
        od = OrderedDict(pairs)
 
1160
        self.assertEqual(len(od), len(pairs))
 
1161
        od.clear()
 
1162
        self.assertEqual(len(od), 0)
 
1163
 
 
1164
    def test_delitem(self):
 
1165
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1166
        od = OrderedDict(pairs)
 
1167
        del od['a']
 
1168
        self.assertNotIn('a', od)
 
1169
        with self.assertRaises(KeyError):
 
1170
            del od['a']
 
1171
        self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
 
1172
 
 
1173
    def test_setitem(self):
 
1174
        od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
 
1175
        od['c'] = 10           # existing element
 
1176
        od['f'] = 20           # new element
 
1177
        self.assertEqual(list(od.items()),
 
1178
                         [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
 
1179
 
 
1180
    def test_iterators(self):
 
1181
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1182
        shuffle(pairs)
 
1183
        od = OrderedDict(pairs)
 
1184
        self.assertEqual(list(od), [t[0] for t in pairs])
 
1185
        self.assertEqual(list(od.keys()), [t[0] for t in pairs])
 
1186
        self.assertEqual(list(od.values()), [t[1] for t in pairs])
 
1187
        self.assertEqual(list(od.items()), pairs)
 
1188
        self.assertEqual(list(reversed(od)),
 
1189
                         [t[0] for t in reversed(pairs)])
 
1190
 
 
1191
    def test_popitem(self):
 
1192
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1193
        shuffle(pairs)
 
1194
        od = OrderedDict(pairs)
 
1195
        while pairs:
 
1196
            self.assertEqual(od.popitem(), pairs.pop())
 
1197
        with self.assertRaises(KeyError):
 
1198
            od.popitem()
 
1199
        self.assertEqual(len(od), 0)
 
1200
 
 
1201
    def test_pop(self):
 
1202
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1203
        shuffle(pairs)
 
1204
        od = OrderedDict(pairs)
 
1205
        shuffle(pairs)
 
1206
        while pairs:
 
1207
            k, v = pairs.pop()
 
1208
            self.assertEqual(od.pop(k), v)
 
1209
        with self.assertRaises(KeyError):
 
1210
            od.pop('xyz')
 
1211
        self.assertEqual(len(od), 0)
 
1212
        self.assertEqual(od.pop(k, 12345), 12345)
 
1213
 
 
1214
        # make sure pop still works when __missing__ is defined
 
1215
        class Missing(OrderedDict):
 
1216
            def __missing__(self, key):
 
1217
                return 0
 
1218
        m = Missing(a=1)
 
1219
        self.assertEqual(m.pop('b', 5), 5)
 
1220
        self.assertEqual(m.pop('a', 6), 1)
 
1221
        self.assertEqual(m.pop('a', 6), 6)
 
1222
        with self.assertRaises(KeyError):
 
1223
            m.pop('a')
 
1224
 
 
1225
    def test_equality(self):
 
1226
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1227
        shuffle(pairs)
 
1228
        od1 = OrderedDict(pairs)
 
1229
        od2 = OrderedDict(pairs)
 
1230
        self.assertEqual(od1, od2)          # same order implies equality
 
1231
        pairs = pairs[2:] + pairs[:2]
 
1232
        od2 = OrderedDict(pairs)
 
1233
        self.assertNotEqual(od1, od2)       # different order implies inequality
 
1234
        # comparison to regular dict is not order sensitive
 
1235
        self.assertEqual(od1, dict(od2))
 
1236
        self.assertEqual(dict(od2), od1)
 
1237
        # different length implied inequality
 
1238
        self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
 
1239
 
 
1240
    def test_copying(self):
 
1241
        # Check that ordered dicts are copyable, deepcopyable, picklable,
 
1242
        # and have a repr/eval round-trip
 
1243
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1244
        od = OrderedDict(pairs)
 
1245
        update_test = OrderedDict()
 
1246
        update_test.update(od)
 
1247
        for label, dup in [
 
1248
                    ('od.copy()', od.copy()),
 
1249
                    ('copy.copy(od)', copy.copy(od)),
 
1250
                    ('copy.deepcopy(od)', copy.deepcopy(od)),
 
1251
                    ('pickle.loads(pickle.dumps(od, 0))',
 
1252
                        pickle.loads(pickle.dumps(od, 0))),
 
1253
                    ('pickle.loads(pickle.dumps(od, 1))',
 
1254
                        pickle.loads(pickle.dumps(od, 1))),
 
1255
                    ('pickle.loads(pickle.dumps(od, 2))',
 
1256
                        pickle.loads(pickle.dumps(od, 2))),
 
1257
                    ('pickle.loads(pickle.dumps(od, 3))',
 
1258
                        pickle.loads(pickle.dumps(od, 3))),
 
1259
                    ('pickle.loads(pickle.dumps(od, -1))',
 
1260
                        pickle.loads(pickle.dumps(od, -1))),
 
1261
                    ('eval(repr(od))', eval(repr(od))),
 
1262
                    ('update_test', update_test),
 
1263
                    ('OrderedDict(od)', OrderedDict(od)),
 
1264
                    ]:
 
1265
            with self.subTest(label=label):
 
1266
                msg = "\ncopy: %s\nod: %s" % (dup, od)
 
1267
                self.assertIsNot(dup, od, msg)
 
1268
                self.assertEqual(dup, od)
 
1269
 
 
1270
    def test_yaml_linkage(self):
 
1271
        # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
 
1272
        # In yaml, lists are native but tuples are not.
 
1273
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1274
        od = OrderedDict(pairs)
 
1275
        # yaml.dump(od) -->
 
1276
        # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n  - [b, 2]\n'
 
1277
        self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
 
1278
 
 
1279
    def test_reduce_not_too_fat(self):
 
1280
        # do not save instance dictionary if not needed
 
1281
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1282
        od = OrderedDict(pairs)
 
1283
        self.assertIsNone(od.__reduce__()[2])
 
1284
        od.x = 10
 
1285
        self.assertIsNotNone(od.__reduce__()[2])
 
1286
 
 
1287
    def test_pickle_recursive(self):
 
1288
        od = OrderedDict()
 
1289
        od[1] = od
 
1290
        for proto in range(-1, pickle.HIGHEST_PROTOCOL + 1):
 
1291
            dup = pickle.loads(pickle.dumps(od, proto))
 
1292
            self.assertIsNot(dup, od)
 
1293
            self.assertEqual(list(dup.keys()), [1])
 
1294
            self.assertIs(dup[1], dup)
 
1295
 
 
1296
    def test_repr(self):
 
1297
        od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
 
1298
        self.assertEqual(repr(od),
 
1299
            "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
 
1300
        self.assertEqual(eval(repr(od)), od)
 
1301
        self.assertEqual(repr(OrderedDict()), "OrderedDict()")
 
1302
 
 
1303
    def test_repr_recursive(self):
 
1304
        # See issue #9826
 
1305
        od = OrderedDict.fromkeys('abc')
 
1306
        od['x'] = od
 
1307
        self.assertEqual(repr(od),
 
1308
            "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
 
1309
 
 
1310
    def test_setdefault(self):
 
1311
        pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
 
1312
        shuffle(pairs)
 
1313
        od = OrderedDict(pairs)
 
1314
        pair_order = list(od.items())
 
1315
        self.assertEqual(od.setdefault('a', 10), 3)
 
1316
        # make sure order didn't change
 
1317
        self.assertEqual(list(od.items()), pair_order)
 
1318
        self.assertEqual(od.setdefault('x', 10), 10)
 
1319
        # make sure 'x' is added to the end
 
1320
        self.assertEqual(list(od.items())[-1], ('x', 10))
 
1321
 
 
1322
        # make sure setdefault still works when __missing__ is defined
 
1323
        class Missing(OrderedDict):
 
1324
            def __missing__(self, key):
 
1325
                return 0
 
1326
        self.assertEqual(Missing().setdefault(5, 9), 9)
 
1327
 
 
1328
    def test_reinsert(self):
 
1329
        # Given insert a, insert b, delete a, re-insert a,
 
1330
        # verify that a is now later than b.
 
1331
        od = OrderedDict()
 
1332
        od['a'] = 1
 
1333
        od['b'] = 2
 
1334
        del od['a']
 
1335
        od['a'] = 1
 
1336
        self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
 
1337
 
 
1338
    def test_move_to_end(self):
 
1339
        od = OrderedDict.fromkeys('abcde')
 
1340
        self.assertEqual(list(od), list('abcde'))
 
1341
        od.move_to_end('c')
 
1342
        self.assertEqual(list(od), list('abdec'))
 
1343
        od.move_to_end('c', 0)
 
1344
        self.assertEqual(list(od), list('cabde'))
 
1345
        od.move_to_end('c', 0)
 
1346
        self.assertEqual(list(od), list('cabde'))
 
1347
        od.move_to_end('e')
 
1348
        self.assertEqual(list(od), list('cabde'))
 
1349
        with self.assertRaises(KeyError):
 
1350
            od.move_to_end('x')
 
1351
 
 
1352
    def test_sizeof(self):
 
1353
        # Wimpy test: Just verify the reported size is larger than a regular dict
 
1354
        d = dict(a=1)
 
1355
        od = OrderedDict(**d)
 
1356
        self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
 
1357
 
 
1358
    def test_override_update(self):
 
1359
        # Verify that subclasses can override update() without breaking __init__()
 
1360
        class MyOD(OrderedDict):
 
1361
            def update(self, *args, **kwds):
 
1362
                raise Exception()
 
1363
        items = [('a', 1), ('c', 3), ('b', 2)]
 
1364
        self.assertEqual(list(MyOD(items).items()), items)
 
1365
 
 
1366
class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
 
1367
    type2test = OrderedDict
 
1368
 
 
1369
    def test_popitem(self):
 
1370
        d = self._empty_mapping()
 
1371
        self.assertRaises(KeyError, d.popitem)
 
1372
 
 
1373
class MyOrderedDict(OrderedDict):
 
1374
    pass
 
1375
 
 
1376
class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
 
1377
    type2test = MyOrderedDict
 
1378
 
 
1379
    def test_popitem(self):
 
1380
        d = self._empty_mapping()
 
1381
        self.assertRaises(KeyError, d.popitem)
 
1382
 
 
1383
 
 
1384
################################################################################
 
1385
### Run tests
 
1386
################################################################################
 
1387
 
 
1388
import doctest, collections
 
1389
 
 
1390
def test_main(verbose=None):
 
1391
    NamedTupleDocs = doctest.DocTestSuite(module=collections)
 
1392
    test_classes = [TestNamedTuple, NamedTupleDocs, TestOneTrickPonyABCs,
 
1393
                    TestCollectionABCs, TestCounter, TestChainMap,
 
1394
                    TestOrderedDict, GeneralMappingTests, SubclassMappingTests]
 
1395
    support.run_unittest(*test_classes)
 
1396
    support.run_doctest(collections, verbose)
 
1397
 
 
1398
 
 
1399
if __name__ == "__main__":
 
1400
    test_main(verbose=True)