1
"""Unit tests for collections.py."""
3
import unittest, doctest, operator
4
from test.support import TESTFN, forget, unlink
6
from test import support
7
from collections import namedtuple, Counter, OrderedDict, _count_elements
8
from test import mapping_tests
10
from random import randrange, shuffle
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
24
################################################################################
25
### ChainMap (helper class for configparser and the string module)
26
################################################################################
28
class TestChainMap(unittest.TestCase):
30
def test_basics(self):
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
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)
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
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})"
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:]):
66
for e in [pickle.loads(pickle.dumps(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)
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]
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
88
self.assertFalse(ChainMap())
89
self.assertFalse(ChainMap({}, {}))
90
self.assertTrue(ChainMap({1:2}, {}))
91
self.assertTrue(ChainMap({}, {1:2}))
93
def test_missing(self):
94
class DefaultChainMap(ChainMap):
95
def __missing__(self, key):
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):
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))
115
def test_new_child(self):
116
'Tests for changes for issue #16613.'
120
m = {'b':20, 'c': 30}
122
self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
123
self.assertIs(m, d.maps[0])
125
# Use a different map than a dict
126
class lowerdict(dict):
127
def __getitem__(self, key):
128
if isinstance(key, str):
130
return dict.__getitem__(self, key)
131
def __contains__(self, key):
132
if isinstance(key, str):
134
return dict.__contains__(self, key)
139
m = lowerdict(b=20, c=30)
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)
148
################################################################################
150
################################################################################
152
TestNT = namedtuple('TestNT', 'x y z') # type used for pickle tests
154
class TestNamedTuple(unittest.TestCase):
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)
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
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
175
namedtuple('Point0', 'x1 y2') # Verify that numbers are allowed in names
176
namedtuple('_', 'a b c') # Test leading underscores in a typename
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))
183
self.assertRaises(TypeError, Point._make, [11]) # catch too few args
184
self.assertRaises(TypeError, Point._make, [11, 22, 33]) # catch too many args
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)')
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
201
self.assertEqual(namedtuple('NT', spec, rename=True)._fields, renamed)
203
def test_instance(self):
204
Point = namedtuple('Point', 'x y')
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
224
p._replace(x=1, error=2)
228
self._fail('Did not detect an incorrect fieldname')
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)')
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)')
240
def test_tupleness(self):
241
Point = namedtuple('Point', 'x y')
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
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)
255
self.assertEqual(p.x, x)
256
self.assertEqual(p.y, y)
257
self.assertRaises(AttributeError, eval, 'p.z', locals())
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, ())
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',))
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)))
282
Big = namedtuple('Big', names)
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
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))
296
self.assertEqual(b2, tuple(b2_expected))
297
self.assertEqual(b._fields, tuple(names))
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))
311
p = TestNT(x=10, y=20, z=30)
312
for copier in copy.copy, copy.deepcopy:
314
self.assertEqual(p, q)
315
self.assertEqual(p._fields, q._fields)
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')
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))
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)
333
values = tuple(range(len(words)))
335
self.assertEqual(t, values)
336
t = T(**dict(zip(T._fields, values)))
337
self.assertEqual(t, values)
340
self.assertEqual(t, values)
344
self.assertEqual(t._asdict(), dict(zip(T._fields, values)))
347
newvalues = tuple(v*10 for v in values)
348
newt = t._replace(**dict(zip(T._fields, newvalues)))
349
self.assertEqual(newt, newvalues)
351
self.assertEqual(T._fields, tuple(words))
352
# test __getnewargs__
353
self.assertEqual(t.__getnewargs__(), values)
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
362
self.assertEqual(repr(B(1)), 'B(x=1)')
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
376
################################################################################
377
### Abstract Base Classes
378
################################################################################
380
class ABCTestCase(unittest.TestCase):
382
def validate_abstract_methods(self, abc, *names):
383
methodstubs = dict.fromkeys(names, lambda s, *args: 0)
385
# everything should work will all required methods are present
386
C = type('C', (abc,), methodstubs)
389
# instantiation should fail if a required method is missing
391
stubs = methodstubs.copy()
393
C = type('C', (abc,), stubs)
394
self.assertRaises(TypeError, C, name)
396
def validate_isinstance(self, abc, name):
397
stub = lambda s, *args: 0
399
C = type('C', (object,), {'__hash__': None})
400
setattr(C, name, stub)
401
self.assertIsInstance(C(), abc)
402
self.assertTrue(issubclass(C, abc))
404
C = type('C', (object,), {'__hash__': None})
405
self.assertNotIsInstance(C(), abc)
406
self.assertFalse(issubclass(C, abc))
408
def validate_comparison(self, instance):
409
ops = ['lt', 'gt', 'le', 'ge', 'ne', 'or', 'and', 'xor', 'sub']
412
name = '__' + op + '__'
413
operators[name] = getattr(operator, name)
417
self.right_side = False
418
def __eq__(self, other):
419
self.right_side = True
431
for name, op in operators.items():
432
if not hasattr(instance, name):
436
self.assertTrue(other.right_side,'Right side not called for %s.%s'
437
% (type(instance), name))
439
class TestOneTrickPonyABCs(ABCTestCase):
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
449
int(), float(), complex(),
451
tuple(), frozenset(),
452
int, list, object, type, bytes()
455
self.assertIsInstance(x, Hashable)
456
self.assertTrue(issubclass(type(x), Hashable), repr(type(x)))
457
self.assertRaises(TypeError, Hashable)
458
# Check direct subclassing
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__')
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(),
481
self.assertIsInstance(x, Iterable)
482
self.assertTrue(issubclass(type(x), Iterable), repr(type(x)))
483
# Check direct subclassing
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__')
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()),
506
self.assertIsInstance(x, Iterator)
507
self.assertTrue(issubclass(type(x), Iterator), repr(type(x)))
508
self.validate_abstract_methods(Iterator, '__next__', '__iter__')
515
self.assertNotIsInstance(NextOnly(), Iterator)
517
def test_Sized(self):
518
non_samples = [None, 42, 3.14, 1j,
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(),
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__')
535
def test_Container(self):
536
non_samples = [None, 42, 3.14, 1j,
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(),
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__')
553
def test_Callable(self):
554
non_samples = [None, 42, 3.14, 1j,
555
"", b"", (), [], {}, set(),
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,
565
list.append, [].append,
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__')
573
def test_direct_subclassing(self):
574
for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
577
self.assertTrue(issubclass(C, B))
578
self.assertFalse(issubclass(int, C))
580
def test_registration(self):
581
for B in Hashable, Iterable, Iterator, Sized, Container, Callable:
583
__hash__ = None # Make sure it isn't hashable by default
584
self.assertFalse(issubclass(C, B), B.__name__)
586
self.assertTrue(issubclass(C, B))
588
class WithSet(MutableSet):
590
def __init__(self, it=()):
594
return len(self.data)
597
return iter(self.data)
599
def __contains__(self, item):
600
return item in self.data
605
def discard(self, item):
606
self.data.discard(item)
608
class TestCollectionABCs(ABCTestCase):
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.
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__')
620
def __contains__(self, x):
626
self.validate_comparison(MySet())
628
def test_hash_Set(self):
629
class OneTwoThreeSet(Set):
631
self.contents = [1, 2, 3]
632
def __contains__(self, x):
633
return x in self.contents
635
return len(self.contents)
637
return iter(self.contents)
640
a, b = OneTwoThreeSet(), OneTwoThreeSet()
641
self.assertTrue(hash(a) == hash(b))
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__',
651
def test_issue_5647(self):
652
# MutableSet.__iand__ mutated the set during iteration
654
s &= WithSet('cdef') # This used to fail
655
self.assertEqual(set(s), set('cd'))
657
def test_issue_4920(self):
658
# MutableSet.pop() method did not work
659
class MySet(MutableSet):
661
def __init__(self,items=None):
665
def __contains__(self,v):
668
return iter(self.__s)
672
result=v not in self.__s
680
return "MySet(%s)" % repr(list(self))
681
s = MySet([5,43,2,1])
682
self.assertEqual(s.pop(), 1)
684
def test_issue8750(self):
686
full = WithSet(range(10))
689
self.assertEqual(s, empty)
692
self.assertEqual(s, empty)
695
self.assertEqual(s, full)
697
self.assertEqual(s, full)
699
def test_issue16373(self):
700
# Recursion error comparing comparable and noncomparable
702
class MyComparableSet(Set):
703
def __contains__(self, x):
709
class MyNonComparableSet(Set):
710
def __contains__(self, x):
717
return NotImplemented
719
return NotImplemented
721
cs = MyComparableSet()
722
ncs = MyNonComparableSet()
723
with self.assertRaises(TypeError):
725
with self.assertRaises(TypeError):
727
with self.assertRaises(TypeError):
729
with self.assertRaises(TypeError):
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__',
738
class MyMapping(Mapping):
741
def __getitem__(self, i):
745
self.validate_comparison(MyMapping())
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__')
754
def test_MutableMapping_subclass(self):
758
self.assertIsInstance(mymap.keys(), Set)
759
self.assertIsInstance(mymap.keys(), KeysView)
760
self.assertIsInstance(mymap.items(), Set)
761
self.assertIsInstance(mymap.items(), ItemsView)
765
z = mymap.keys() | {'orange'}
766
self.assertIsInstance(z, set)
768
mymap['blue'] = 7 # Shouldn't affect 'z'
769
self.assertEqual(sorted(z), ['orange', 'red'])
773
z = mymap.items() | {('orange', 3)}
774
self.assertIsInstance(z, set)
776
mymap['blue'] = 7 # Shouldn't affect 'z'
777
self.assertEqual(sorted(z), [('orange', 3), ('red', 5)])
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__',
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))
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')
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):
819
def __setitem__(self, index, value):
820
self.lst[index] = value
822
def __getitem__(self, index):
823
return self.lst[index]
828
def __delitem__(self, index):
831
def insert(self, index, value):
832
self.lst.insert(index, value)
834
mss = MutableSequenceSubclass()
836
mss.extend((1, 2, 3, 4))
837
self.assertEqual(len(mss), 5)
838
self.assertEqual(mss[3], 3)
840
self.assertEqual(mss[3], 1)
842
self.assertEqual(len(mss), 4)
844
self.assertEqual(len(mss), 3)
846
self.assertEqual(len(mss), 6)
847
self.assertEqual(mss[-1], 30)
849
self.assertEqual(len(mss), 0)
851
################################################################################
853
################################################################################
855
class CounterSubclassWithSetItem(Counter):
856
# Test a counter subclass that overrides __setitem__
857
def __init__(self, *args, **kwds):
859
Counter.__init__(self, *args, **kwds)
860
def __setitem__(self, key, value):
862
Counter.__setitem__(self, key, value)
864
class CounterSubclassWithGet(Counter):
865
# Test a counter subclass that overrides get()
866
def __init__(self, *args, **kwds):
868
Counter.__init__(self, *args, **kwds)
869
def get(self, key, default):
871
return Counter.get(self, key, default)
873
class TestCounter(unittest.TestCase):
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)])
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)
915
elem, cnt = c.popitem()
916
self.assertNotIn(elem, c)
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))
924
c.update(Counter('a' * 50 + 'b' * 30))
925
c.update() # test case with no args
926
c.__init__('a' * 500 + 'b' * 300)
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)
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)
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)),
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)
962
def test_copy_subclass(self):
963
class MyCounter(Counter):
965
c = MyCounter('slartibartfast')
967
self.assertEqual(d, c)
968
self.assertEqual(len(d), len(c))
969
self.assertEqual(type(d), type(c))
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))
979
def test_invariant_for_the_in_operator(self):
980
c = Counter(a=10, b=-2, c=0)
982
self.assertTrue(elem in c)
983
self.assertIn(elem, c)
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))
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))),
1003
result = counterop(p, q)
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())
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__),
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))
1024
def test_inplace_operations(self):
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__),
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)
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))
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))
1061
def test_repr_nonsortable(self):
1062
c = Counter(a=2, b=None)
1064
self.assertIn("'a': 2", r)
1065
self.assertIn("'b': None", r)
1067
def test_helper_function(self):
1068
# two paths, one for real dicts and one for other mappings
1069
elems = list('abracadabra')
1072
_count_elements(d, elems)
1073
self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
1076
_count_elements(m, elems)
1078
OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
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 })
1089
################################################################################
1091
################################################################################
1093
class TestOrderedDict(unittest.TestCase):
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
1105
# make sure no positional args conflict with possible kwdargs
1106
self.assertEqual(inspect.getargspec(OrderedDict.__dict__['__init__']).args,
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)])
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)]
1120
od.update(dict(pairs))
1121
self.assertEqual(sorted(od.items()), pairs) # dict input
1123
od.update(**dict(pairs))
1124
self.assertEqual(sorted(od.items()), pairs) # kwds input
1127
self.assertEqual(list(od.items()), pairs) # pairs input
1129
od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
1130
self.assertEqual(list(od.items()), pairs) # mixed input
1132
# Issue 9137: Named argument called 'other' or 'self'
1133
# shouldn't be treated specially.
1136
self.assertEqual(list(od.items()), [('self', 23)])
1139
self.assertEqual(list(od.items()), [('other', {})])
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)])
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)])
1153
self.assertIsInstance(OrderedDict(), MutableMapping)
1154
self.assertTrue(issubclass(OrderedDict, MutableMapping))
1156
def test_clear(self):
1157
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1159
od = OrderedDict(pairs)
1160
self.assertEqual(len(od), len(pairs))
1162
self.assertEqual(len(od), 0)
1164
def test_delitem(self):
1165
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1166
od = OrderedDict(pairs)
1168
self.assertNotIn('a', od)
1169
with self.assertRaises(KeyError):
1171
self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
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)])
1180
def test_iterators(self):
1181
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
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)])
1191
def test_popitem(self):
1192
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1194
od = OrderedDict(pairs)
1196
self.assertEqual(od.popitem(), pairs.pop())
1197
with self.assertRaises(KeyError):
1199
self.assertEqual(len(od), 0)
1202
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
1204
od = OrderedDict(pairs)
1208
self.assertEqual(od.pop(k), v)
1209
with self.assertRaises(KeyError):
1211
self.assertEqual(len(od), 0)
1212
self.assertEqual(od.pop(k, 12345), 12345)
1214
# make sure pop still works when __missing__ is defined
1215
class Missing(OrderedDict):
1216
def __missing__(self, key):
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):
1225
def test_equality(self):
1226
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
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]))
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)
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)),
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)
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)
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]))
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])
1285
self.assertIsNotNone(od.__reduce__()[2])
1287
def test_pickle_recursive(self):
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)
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()")
1303
def test_repr_recursive(self):
1305
od = OrderedDict.fromkeys('abc')
1307
self.assertEqual(repr(od),
1308
"OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
1310
def test_setdefault(self):
1311
pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
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))
1322
# make sure setdefault still works when __missing__ is defined
1323
class Missing(OrderedDict):
1324
def __missing__(self, key):
1326
self.assertEqual(Missing().setdefault(5, 9), 9)
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.
1336
self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
1338
def test_move_to_end(self):
1339
od = OrderedDict.fromkeys('abcde')
1340
self.assertEqual(list(od), list('abcde'))
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'))
1348
self.assertEqual(list(od), list('cabde'))
1349
with self.assertRaises(KeyError):
1352
def test_sizeof(self):
1353
# Wimpy test: Just verify the reported size is larger than a regular dict
1355
od = OrderedDict(**d)
1356
self.assertGreater(sys.getsizeof(od), sys.getsizeof(d))
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):
1363
items = [('a', 1), ('c', 3), ('b', 2)]
1364
self.assertEqual(list(MyOD(items).items()), items)
1366
class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
1367
type2test = OrderedDict
1369
def test_popitem(self):
1370
d = self._empty_mapping()
1371
self.assertRaises(KeyError, d.popitem)
1373
class MyOrderedDict(OrderedDict):
1376
class SubclassMappingTests(mapping_tests.BasicTestMappingProtocol):
1377
type2test = MyOrderedDict
1379
def test_popitem(self):
1380
d = self._empty_mapping()
1381
self.assertRaises(KeyError, d.popitem)
1384
################################################################################
1386
################################################################################
1388
import doctest, collections
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)
1399
if __name__ == "__main__":
1400
test_main(verbose=True)