summaryrefslogtreecommitdiffstats
path: root/Python/Dependencies/future-0.18.2/tests/test_future/test_backports.py
diff options
context:
space:
mode:
Diffstat (limited to 'Python/Dependencies/future-0.18.2/tests/test_future/test_backports.py')
-rw-r--r--Python/Dependencies/future-0.18.2/tests/test_future/test_backports.py665
1 files changed, 665 insertions, 0 deletions
diff --git a/Python/Dependencies/future-0.18.2/tests/test_future/test_backports.py b/Python/Dependencies/future-0.18.2/tests/test_future/test_backports.py
new file mode 100644
index 0000000..9eeb741
--- /dev/null
+++ b/Python/Dependencies/future-0.18.2/tests/test_future/test_backports.py
@@ -0,0 +1,665 @@
+# -*- coding: utf-8 -*-
+"""
+Tests for various backported functions and classes in ``future.backports``
+"""
+
+from __future__ import absolute_import, print_function
+
+import sys
+import copy
+import inspect
+import pickle
+from random import randrange, shuffle
+
+from future.backports.misc import (count,
+ _count,
+ OrderedDict,
+ Counter,
+ ChainMap,
+ _count_elements)
+from future.utils import PY2, PY26
+from future.tests.base import unittest, skip26, expectedFailurePY27
+
+if PY2:
+ from collections import Mapping, MutableMapping
+else:
+ from collections.abc import Mapping, MutableMapping
+
+
+class CountTest(unittest.TestCase):
+ """Test the count function."""
+
+ def _test_count_func(self, func):
+ self.assertEqual(next(func(1)), 1)
+ self.assertEqual(next(func(start=1)), 1)
+
+ c = func()
+ self.assertEqual(next(c), 0)
+ self.assertEqual(next(c), 1)
+ self.assertEqual(next(c), 2)
+ c = func(1, 1)
+ self.assertEqual(next(c), 1)
+ self.assertEqual(next(c), 2)
+ c = func(step=1)
+ self.assertEqual(next(c), 0)
+ self.assertEqual(next(c), 1)
+ c = func(start=1, step=1)
+ self.assertEqual(next(c), 1)
+ self.assertEqual(next(c), 2)
+
+ c = func(-1)
+ self.assertEqual(next(c), -1)
+ self.assertEqual(next(c), 0)
+ self.assertEqual(next(c), 1)
+ c = func(1, -1)
+ self.assertEqual(next(c), 1)
+ self.assertEqual(next(c), 0)
+ self.assertEqual(next(c), -1)
+ c = func(-1, -1)
+ self.assertEqual(next(c), -1)
+ self.assertEqual(next(c), -2)
+ self.assertEqual(next(c), -3)
+
+ def test_count(self):
+ """Test the count function."""
+ self._test_count_func(count)
+
+ def test_own_count(self):
+ """Test own count implementation."""
+ if PY26:
+ self.assertIs(count, _count)
+ else:
+ self.assertNotEqual(count, _count)
+ self._test_count_func(_count)
+
+
+################################################################################
+### ChainMap (helper class for configparser and the string module)
+################################################################################
+
+class TestChainMap(unittest.TestCase):
+
+ def test_basics(self):
+ c = ChainMap()
+ c['a'] = 1
+ c['b'] = 2
+ d = c.new_child()
+ d['b'] = 20
+ d['c'] = 30
+ self.assertEqual(d.maps, [{'b':20, 'c':30}, {'a':1, 'b':2}]) # check internal state
+ self.assertEqual(d.items(), dict(a=1, b=20, c=30).items()) # check items/iter/getitem
+ self.assertEqual(len(d), 3) # check len
+ for key in 'abc': # check contains
+ self.assertIn(key, d)
+ for k, v in dict(a=1, b=20, c=30, z=100).items(): # check get
+ self.assertEqual(d.get(k, 100), v)
+
+ del d['b'] # unmask a value
+ self.assertEqual(d.maps, [{'c':30}, {'a':1, 'b':2}]) # check internal state
+ self.assertEqual(d.items(), dict(a=1, b=2, c=30).items()) # check items/iter/getitem
+ self.assertEqual(len(d), 3) # check len
+ for key in 'abc': # check contains
+ self.assertIn(key, d)
+ for k, v in dict(a=1, b=2, c=30, z=100).items(): # check get
+ self.assertEqual(d.get(k, 100), v)
+ self.assertIn(repr(d), [ # check repr
+ type(d).__name__ + "({'c': 30}, {'a': 1, 'b': 2})",
+ type(d).__name__ + "({'c': 30}, {'b': 2, 'a': 1})"
+ ])
+
+ for e in d.copy(), copy.copy(d): # check shallow copies
+ self.assertEqual(d, e)
+ self.assertEqual(d.maps, e.maps)
+ self.assertIsNot(d, e)
+ self.assertIsNot(d.maps[0], e.maps[0])
+ for m1, m2 in zip(d.maps[1:], e.maps[1:]):
+ self.assertIs(m1, m2)
+
+ _ChainMap = ChainMap
+
+ for e in [pickle.loads(pickle.dumps(d)),
+ copy.deepcopy(d),
+ eval(repr(d))
+ ]: # check deep copies
+ self.assertEqual(d, e)
+ self.assertEqual(d.maps, e.maps)
+ self.assertIsNot(d, e)
+ for m1, m2 in zip(d.maps, e.maps):
+ self.assertIsNot(m1, m2, e)
+
+ f = d.new_child()
+ f['b'] = 5
+ self.assertEqual(f.maps, [{'b': 5}, {'c':30}, {'a':1, 'b':2}])
+ self.assertEqual(f.parents.maps, [{'c':30}, {'a':1, 'b':2}]) # check parents
+ self.assertEqual(f['b'], 5) # find first in chain
+ self.assertEqual(f.parents['b'], 2) # look beyond maps[0]
+
+ def test_contructor(self):
+ self.assertEqual(ChainMap().maps, [{}]) # no-args --> one new dict
+ self.assertEqual(ChainMap({1:2}).maps, [{1:2}]) # 1 arg --> list
+
+ def test_bool(self):
+ self.assertFalse(ChainMap())
+ self.assertFalse(ChainMap({}, {}))
+ self.assertTrue(ChainMap({1:2}, {}))
+ self.assertTrue(ChainMap({}, {1:2}))
+
+ def test_missing(self):
+ class DefaultChainMap(ChainMap):
+ def __missing__(self, key):
+ return 999
+ d = DefaultChainMap(dict(a=1, b=2), dict(b=20, c=30))
+ for k, v in dict(a=1, b=2, c=30, d=999).items():
+ self.assertEqual(d[k], v) # check __getitem__ w/missing
+ for k, v in dict(a=1, b=2, c=30, d=77).items():
+ self.assertEqual(d.get(k, 77), v) # check get() w/ missing
+ for k, v in dict(a=True, b=True, c=True, d=False).items():
+ self.assertEqual(k in d, v) # check __contains__ w/missing
+ self.assertEqual(d.pop('a', 1001), 1, d)
+ self.assertEqual(d.pop('a', 1002), 1002) # check pop() w/missing
+ self.assertEqual(d.popitem(), ('b', 2)) # check popitem() w/missing
+ with self.assertRaises(KeyError):
+ d.popitem()
+
+ def test_dict_coercion(self):
+ d = ChainMap(dict(a=1, b=2), dict(b=20, c=30))
+ self.assertEqual(dict(d), dict(a=1, b=2, c=30))
+ self.assertEqual(dict(d.items()), dict(a=1, b=2, c=30))
+
+
+################################################################################
+### Counter
+################################################################################
+
+class CounterSubclassWithSetItem(Counter):
+ # Test a counter subclass that overrides __setitem__
+ def __init__(self, *args, **kwds):
+ self.called = False
+ Counter.__init__(self, *args, **kwds)
+ def __setitem__(self, key, value):
+ self.called = True
+ Counter.__setitem__(self, key, value)
+
+class CounterSubclassWithGet(Counter):
+ # Test a counter subclass that overrides get()
+ def __init__(self, *args, **kwds):
+ self.called = False
+ Counter.__init__(self, *args, **kwds)
+ def get(self, key, default):
+ self.called = True
+ return Counter.get(self, key, default)
+
+class TestCounter(unittest.TestCase):
+
+ def test_basics(self):
+ c = Counter('abcaba')
+ self.assertEqual(c, Counter({'a':3 , 'b': 2, 'c': 1}))
+ self.assertEqual(c, Counter(a=3, b=2, c=1))
+ self.assertIsInstance(c, dict)
+ self.assertIsInstance(c, Mapping)
+ self.assertTrue(issubclass(Counter, dict))
+ self.assertTrue(issubclass(Counter, Mapping))
+ self.assertEqual(len(c), 3)
+ self.assertEqual(sum(c.values()), 6)
+ self.assertEqual(sorted(c.values()), [1, 2, 3])
+ self.assertEqual(sorted(c.keys()), ['a', 'b', 'c'])
+ self.assertEqual(sorted(c), ['a', 'b', 'c'])
+ self.assertEqual(sorted(c.items()),
+ [('a', 3), ('b', 2), ('c', 1)])
+ self.assertEqual(c['b'], 2)
+ self.assertEqual(c['z'], 0)
+ self.assertEqual(c.__contains__('c'), True)
+ self.assertEqual(c.__contains__('z'), False)
+ self.assertEqual(c.get('b', 10), 2)
+ self.assertEqual(c.get('z', 10), 10)
+ self.assertEqual(c, dict(a=3, b=2, c=1))
+ self.assertEqual(repr(c), "Counter({'a': 3, 'b': 2, 'c': 1})")
+ self.assertEqual(c.most_common(), [('a', 3), ('b', 2), ('c', 1)])
+ for i in range(5):
+ self.assertEqual(c.most_common(i),
+ [('a', 3), ('b', 2), ('c', 1)][:i])
+ self.assertEqual(''.join(sorted(c.elements())), 'aaabbc')
+ c['a'] += 1 # increment an existing value
+ c['b'] -= 2 # sub existing value to zero
+ del c['c'] # remove an entry
+ del c['c'] # make sure that del doesn't raise KeyError
+ c['d'] -= 2 # sub from a missing value
+ c['e'] = -5 # directly assign a missing value
+ c['f'] += 4 # add to a missing value
+ self.assertEqual(c, dict(a=4, b=0, d=-2, e=-5, f=4))
+ self.assertEqual(''.join(sorted(c.elements())), 'aaaaffff')
+ self.assertEqual(c.pop('f'), 4)
+ self.assertNotIn('f', c)
+ for i in range(3):
+ elem, cnt = c.popitem()
+ self.assertNotIn(elem, c)
+ c.clear()
+ self.assertEqual(c, {})
+ self.assertEqual(repr(c), 'Counter()')
+ self.assertRaises(NotImplementedError, Counter.fromkeys, 'abc')
+ self.assertRaises(TypeError, hash, c)
+ c.update(dict(a=5, b=3))
+ c.update(c=1)
+ c.update(Counter('a' * 50 + 'b' * 30))
+ c.update() # test case with no args
+ c.__init__('a' * 500 + 'b' * 300)
+ c.__init__('cdc')
+ c.__init__()
+ self.assertEqual(c, dict(a=555, b=333, c=3, d=1))
+ self.assertEqual(c.setdefault('d', 5), 1)
+ self.assertEqual(c['d'], 1)
+ self.assertEqual(c.setdefault('e', 5), 5)
+ self.assertEqual(c['e'], 5)
+
+ def test_copying(self):
+ # Check that counters are copyable, deepcopyable, picklable, and
+ #have a repr/eval round-trip
+ words = Counter('which witch had which witches wrist watch'.split())
+ update_test = Counter()
+ update_test.update(words)
+ for i, dup in enumerate([
+ words.copy(),
+ copy.copy(words),
+ copy.deepcopy(words),
+ pickle.loads(pickle.dumps(words, 0)),
+ pickle.loads(pickle.dumps(words, 1)),
+ pickle.loads(pickle.dumps(words, 2)),
+ pickle.loads(pickle.dumps(words, -1)),
+ eval(repr(words)),
+ update_test,
+ Counter(words),
+ ]):
+ msg = (i, dup, words)
+ self.assertTrue(dup is not words)
+ self.assertEqual(dup, words)
+ self.assertEqual(len(dup), len(words))
+ self.assertEqual(type(dup), type(words))
+
+ def test_copy_subclass(self):
+ class MyCounter(Counter):
+ pass
+ c = MyCounter('slartibartfast')
+ d = c.copy()
+ self.assertEqual(d, c)
+ self.assertEqual(len(d), len(c))
+ self.assertEqual(type(d), type(c))
+
+ def test_conversions(self):
+ # Convert to: set, list, dict
+ s = 'she sells sea shells by the sea shore'
+ self.assertEqual(sorted(Counter(s).elements()), sorted(s))
+ self.assertEqual(sorted(Counter(s)), sorted(set(s)))
+ self.assertEqual(dict(Counter(s)), dict(Counter(s).items()))
+ self.assertEqual(set(Counter(s)), set(s))
+
+ def test_invariant_for_the_in_operator(self):
+ c = Counter(a=10, b=-2, c=0)
+ for elem in c:
+ self.assertTrue(elem in c)
+ self.assertIn(elem, c)
+
+ def test_multiset_operations(self):
+ # Verify that adding a zero counter will strip zeros and negatives
+ c = Counter(a=10, b=-2, c=0) + Counter()
+ self.assertEqual(dict(c), dict(a=10))
+
+ elements = 'abcd'
+ for i in range(1000):
+ # test random pairs of multisets
+ p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
+ p.update(e=1, f=-1, g=0)
+ q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
+ q.update(h=1, i=-1, j=0)
+ for counterop, numberop in [
+ (Counter.__add__, lambda x, y: max(0, x+y)),
+ (Counter.__sub__, lambda x, y: max(0, x-y)),
+ (Counter.__or__, lambda x, y: max(0,x,y)),
+ (Counter.__and__, lambda x, y: max(0, min(x,y))),
+ ]:
+ result = counterop(p, q)
+ for x in elements:
+ self.assertEqual(numberop(p[x], q[x]), result[x],
+ (counterop, x, p, q))
+ # verify that results exclude non-positive counts
+ self.assertTrue(x>0 for x in result.values())
+
+ elements = 'abcdef'
+ for i in range(100):
+ # verify that random multisets with no repeats are exactly like sets
+ p = Counter(dict((elem, randrange(0, 2)) for elem in elements))
+ q = Counter(dict((elem, randrange(0, 2)) for elem in elements))
+ for counterop, setop in [
+ (Counter.__sub__, set.__sub__),
+ (Counter.__or__, set.__or__),
+ (Counter.__and__, set.__and__),
+ ]:
+ counter_result = counterop(p, q)
+ set_result = setop(set(p.elements()), set(q.elements()))
+ self.assertEqual(counter_result, dict.fromkeys(set_result, 1))
+
+ @expectedFailurePY27
+ def test_inplace_operations(self):
+ elements = 'abcd'
+ for i in range(1000):
+ # test random pairs of multisets
+ p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
+ p.update(e=1, f=-1, g=0)
+ q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
+ q.update(h=1, i=-1, j=0)
+ for inplace_op, regular_op in [
+ (Counter.__iadd__, Counter.__add__),
+ (Counter.__isub__, Counter.__sub__),
+ (Counter.__ior__, Counter.__or__),
+ (Counter.__iand__, Counter.__and__),
+ ]:
+ c = p.copy()
+ c_id = id(c)
+ regular_result = regular_op(c, q)
+ inplace_result = inplace_op(c, q)
+ self.assertEqual(inplace_result, regular_result)
+ self.assertEqual(id(inplace_result), c_id)
+
+ def test_subtract(self):
+ c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
+ c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)
+ self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
+ c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
+ c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50))
+ self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50))
+ c = Counter('aaabbcd')
+ c.subtract('aaaabbcce')
+ self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
+
+ @expectedFailurePY27
+ def test_unary(self):
+ c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40)
+ self.assertEqual(dict(+c), dict(c=5, d=10, e=15, g=40))
+ self.assertEqual(dict(-c), dict(a=5))
+
+ def test_repr_nonsortable(self):
+ c = Counter(a=2, b=None)
+ r = repr(c)
+ self.assertIn("'a': 2", r)
+ self.assertIn("'b': None", r)
+
+ def test_helper_function(self):
+ # two paths, one for real dicts and one for other mappings
+ elems = list('abracadabra')
+
+ d = dict()
+ _count_elements(d, elems)
+ self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
+
+ m = OrderedDict()
+ _count_elements(m, elems)
+ self.assertEqual(m,
+ OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
+
+ # test fidelity to the pure python version
+ c = CounterSubclassWithSetItem('abracadabra')
+ self.assertTrue(c.called)
+ c = CounterSubclassWithGet('abracadabra')
+ self.assertTrue(c.called)
+
+
+################################################################################
+### OrderedDict
+################################################################################
+
+class TestOrderedDict(unittest.TestCase):
+
+ def test_init(self):
+ with self.assertRaises(TypeError):
+ OrderedDict([('a', 1), ('b', 2)], None) # too many args
+ pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+ self.assertEqual(sorted(OrderedDict(dict(pairs)).items()), pairs) # dict input
+ self.assertEqual(sorted(OrderedDict(**dict(pairs)).items()), pairs) # kwds input
+ self.assertEqual(list(OrderedDict(pairs).items()), pairs) # pairs input
+ self.assertEqual(list(OrderedDict([('a', 1), ('b', 2), ('c', 9), ('d', 4)],
+ c=3, e=5).items()), pairs) # mixed input
+
+ # Make sure that direct calls to __init__ do not clear previous contents
+ d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
+ d.__init__([('e', 5), ('f', 6)], g=7, d=4)
+ self.assertEqual(list(d.items()),
+ [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
+
+ def test_update(self):
+ with self.assertRaises(TypeError):
+ OrderedDict().update([('a', 1), ('b', 2)], None) # too many args
+ pairs = [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]
+ od = OrderedDict()
+ od.update(dict(pairs))
+ self.assertEqual(sorted(od.items()), pairs) # dict input
+ od = OrderedDict()
+ od.update(**dict(pairs))
+ self.assertEqual(sorted(od.items()), pairs) # kwds input
+ od = OrderedDict()
+ od.update(pairs)
+ self.assertEqual(list(od.items()), pairs) # pairs input
+ od = OrderedDict()
+ od.update([('a', 1), ('b', 2), ('c', 9), ('d', 4)], c=3, e=5)
+ self.assertEqual(list(od.items()), pairs) # mixed input
+
+ ### The tests below fail on Py2.6
+ if PY26:
+ return
+ # Issue 9137: Named argument called 'other' or 'self'
+ # shouldn't be treated specially.
+ od = OrderedDict()
+ od.update(self=23)
+ self.assertEqual(list(od.items()), [('self', 23)])
+ od = OrderedDict()
+ od.update(other={})
+ self.assertEqual(list(od.items()), [('other', {})])
+ od = OrderedDict()
+ od.update(red=5, blue=6, other=7, self=8)
+ self.assertEqual(sorted(list(od.items())),
+ [('blue', 6), ('other', 7), ('red', 5), ('self', 8)])
+
+ # Make sure that direct calls to update do not clear previous contents
+ # add that updates items are not moved to the end
+ d = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 44), ('e', 55)])
+ d.update([('e', 5), ('f', 6)], g=7, d=4)
+ self.assertEqual(list(d.items()),
+ [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7)])
+
+ def test_abc(self):
+ self.assertIsInstance(OrderedDict(), MutableMapping)
+ self.assertTrue(issubclass(OrderedDict, MutableMapping))
+
+ def test_clear(self):
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ self.assertEqual(len(od), len(pairs))
+ od.clear()
+ self.assertEqual(len(od), 0)
+
+ def test_delitem(self):
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ od = OrderedDict(pairs)
+ del od['a']
+ self.assertNotIn('a', od)
+ with self.assertRaises(KeyError):
+ del od['a']
+ self.assertEqual(list(od.items()), pairs[:2] + pairs[3:])
+
+ def test_setitem(self):
+ od = OrderedDict([('d', 1), ('b', 2), ('c', 3), ('a', 4), ('e', 5)])
+ od['c'] = 10 # existing element
+ od['f'] = 20 # new element
+ self.assertEqual(list(od.items()),
+ [('d', 1), ('b', 2), ('c', 10), ('a', 4), ('e', 5), ('f', 20)])
+
+ def test_iterators(self):
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ self.assertEqual(list(od), [t[0] for t in pairs])
+ self.assertEqual(list(od.keys()), [t[0] for t in pairs])
+ self.assertEqual(list(od.values()), [t[1] for t in pairs])
+ self.assertEqual(list(od.items()), pairs)
+ self.assertEqual(list(reversed(od)),
+ [t[0] for t in reversed(pairs)])
+
+ def test_popitem(self):
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ while pairs:
+ self.assertEqual(od.popitem(), pairs.pop())
+ with self.assertRaises(KeyError):
+ od.popitem()
+ self.assertEqual(len(od), 0)
+
+ def test_pop(self):
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ shuffle(pairs)
+ while pairs:
+ k, v = pairs.pop()
+ self.assertEqual(od.pop(k), v)
+ with self.assertRaises(KeyError):
+ od.pop('xyz')
+ self.assertEqual(len(od), 0)
+ self.assertEqual(od.pop(k, 12345), 12345)
+
+ # make sure pop still works when __missing__ is defined
+ class Missing(OrderedDict):
+ def __missing__(self, key):
+ return 0
+ m = Missing(a=1)
+ self.assertEqual(m.pop('b', 5), 5)
+ self.assertEqual(m.pop('a', 6), 1)
+ self.assertEqual(m.pop('a', 6), 6)
+ with self.assertRaises(KeyError):
+ m.pop('a')
+
+ def test_equality(self):
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od1 = OrderedDict(pairs)
+ od2 = OrderedDict(pairs)
+ self.assertEqual(od1, od2) # same order implies equality
+ pairs = pairs[2:] + pairs[:2]
+ od2 = OrderedDict(pairs)
+ self.assertNotEqual(od1, od2) # different order implies inequality
+ # comparison to regular dict is not order sensitive
+ self.assertEqual(od1, dict(od2))
+ self.assertEqual(dict(od2), od1)
+ # different length implied inequality
+ self.assertNotEqual(od1, OrderedDict(pairs[:-1]))
+
+ def test_copying(self):
+ # Check that ordered dicts are copyable, deepcopyable, picklable,
+ # and have a repr/eval round-trip
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ od = OrderedDict(pairs)
+ update_test = OrderedDict()
+ update_test.update(od)
+ for i, dup in enumerate([
+ od.copy(),
+ copy.copy(od),
+ copy.deepcopy(od),
+ pickle.loads(pickle.dumps(od, 0)),
+ pickle.loads(pickle.dumps(od, 1)),
+ pickle.loads(pickle.dumps(od, 2)),
+ # pickle.loads(pickle.dumps(od, 3)),
+ pickle.loads(pickle.dumps(od, -1)),
+ eval(repr(od)),
+ update_test,
+ OrderedDict(od),
+ ]):
+ self.assertTrue(dup is not od)
+ self.assertEqual(dup, od)
+ self.assertEqual(list(dup.items()), list(od.items()))
+ self.assertEqual(len(dup), len(od))
+ self.assertEqual(type(dup), type(od))
+
+ def test_yaml_linkage(self):
+ # Verify that __reduce__ is setup in a way that supports PyYAML's dump() feature.
+ # In yaml, lists are native but tuples are not.
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ od = OrderedDict(pairs)
+ # yaml.dump(od) -->
+ # '!!python/object/apply:__main__.OrderedDict\n- - [a, 1]\n - [b, 2]\n'
+ self.assertTrue(all(type(pair)==list for pair in od.__reduce__()[1]))
+
+ # def test_reduce_not_too_fat(self):
+ # # do not save instance dictionary if not needed
+ # pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ # od = OrderedDict(pairs)
+ # self.assertEqual(len(od.__reduce__()), 2)
+ # od.x = 10
+ # self.assertEqual(len(od.__reduce__()), 3)
+
+ def test_repr(self):
+ od = OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])
+ self.assertEqual(repr(od),
+ "OrderedDict([('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)])")
+ self.assertEqual(eval(repr(od)), od)
+ self.assertEqual(repr(OrderedDict()), "OrderedDict()")
+
+ def test_repr_recursive(self):
+ # See issue #9826
+ od = OrderedDict.fromkeys('abc')
+ od['x'] = od
+ self.assertEqual(repr(od),
+ "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])")
+
+ def test_setdefault(self):
+ pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)]
+ shuffle(pairs)
+ od = OrderedDict(pairs)
+ pair_order = list(od.items())
+ self.assertEqual(od.setdefault('a', 10), 3)
+ # make sure order didn't change
+ self.assertEqual(list(od.items()), pair_order)
+ self.assertEqual(od.setdefault('x', 10), 10)
+ # make sure 'x' is added to the end
+ self.assertEqual(list(od.items())[-1], ('x', 10))
+
+ # make sure setdefault still works when __missing__ is defined
+ class Missing(OrderedDict):
+ def __missing__(self, key):
+ return 0
+ self.assertEqual(Missing().setdefault(5, 9), 9)
+
+ def test_reinsert(self):
+ # Given insert a, insert b, delete a, re-insert a,
+ # verify that a is now later than b.
+ od = OrderedDict()
+ od['a'] = 1
+ od['b'] = 2
+ del od['a']
+ od['a'] = 1
+ self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
+
+ @expectedFailurePY27
+ def test_move_to_end(self):
+ od = OrderedDict.fromkeys('abcde')
+ self.assertEqual(list(od), list('abcde'))
+ od.move_to_end('c')
+ self.assertEqual(list(od), list('abdec'))
+ od.move_to_end('c', 0)
+ self.assertEqual(list(od), list('cabde'))
+ od.move_to_end('c', 0)
+ self.assertEqual(list(od), list('cabde'))
+ od.move_to_end('e')
+ self.assertEqual(list(od), list('cabde'))
+ with self.assertRaises(KeyError):
+ od.move_to_end('x')
+
+ def test_override_update(self):
+ # Verify that subclasses can override update() without breaking __init__()
+ class MyOD(OrderedDict):
+ def update(self, *args, **kwds):
+ raise Exception()
+ items = [('a', 1), ('c', 3), ('b', 2)]
+ self.assertEqual(list(MyOD(items).items()), items)
+
+
+if __name__ == '__main__':
+ unittest.main()