# Check every path through every method of UserDict

from test import test_support, mapping_tests
import UserDict
import warnings

d0 = {}
d1 = {"one": 1}
d2 = {"one": 1, "two": 2}
d3 = {"one": 1, "two": 3, "three": 5}
d4 = {"one": None, "two": None}
d5 = {"one": 1, "two": 1}

class UserDictTest(mapping_tests.TestHashMappingProtocol):
    type2test = UserDict.IterableUserDict

    def test_all(self):
        # Test constructors
        u = UserDict.UserDict()
        u0 = UserDict.UserDict(d0)
        u1 = UserDict.UserDict(d1)
        u2 = UserDict.IterableUserDict(d2)

        uu = UserDict.UserDict(u)
        uu0 = UserDict.UserDict(u0)
        uu1 = UserDict.UserDict(u1)
        uu2 = UserDict.UserDict(u2)

        # keyword arg constructor
        self.assertEqual(UserDict.UserDict(one=1, two=2), d2)
        # item sequence constructor
        self.assertEqual(UserDict.UserDict([('one',1), ('two',2)]), d2)
        with test_support.check_warnings((".*'dict'.*",
                                          PendingDeprecationWarning)):
            self.assertEqual(UserDict.UserDict(dict=[('one',1), ('two',2)]), d2)
        # both together
        self.assertEqual(UserDict.UserDict([('one',1), ('two',2)], two=3, three=5), d3)

        # alternate constructor
        self.assertEqual(UserDict.UserDict.fromkeys('one two'.split()), d4)
        self.assertEqual(UserDict.UserDict().fromkeys('one two'.split()), d4)
        self.assertEqual(UserDict.UserDict.fromkeys('one two'.split(), 1), d5)
        self.assertEqual(UserDict.UserDict().fromkeys('one two'.split(), 1), d5)
        self.assertTrue(u1.fromkeys('one two'.split()) is not u1)
        self.assertIsInstance(u1.fromkeys('one two'.split()), UserDict.UserDict)
        self.assertIsInstance(u2.fromkeys('one two'.split()), UserDict.IterableUserDict)

        # Test __repr__
        self.assertEqual(str(u0), str(d0))
        self.assertEqual(repr(u1), repr(d1))
        self.assertEqual(repr(u2), repr(d2))

        # Test __cmp__ and __len__
        all = [d0, d1, d2, u, u0, u1, u2, uu, uu0, uu1, uu2]
        for a in all:
            for b in all:
                self.assertEqual(cmp(a, b), cmp(len(a), len(b)))

        # Test __getitem__
        self.assertEqual(u2["one"], 1)
        self.assertRaises(KeyError, u1.__getitem__, "two")

        # Test __setitem__
        u3 = UserDict.UserDict(u2)
        u3["two"] = 2
        u3["three"] = 3

        # Test __delitem__
        del u3["three"]
        self.assertRaises(KeyError, u3.__delitem__, "three")

        # Test clear
        u3.clear()
        self.assertEqual(u3, {})

        # Test copy()
        u2a = u2.copy()
        self.assertEqual(u2a, u2)
        u2b = UserDict.UserDict(x=42, y=23)
        u2c = u2b.copy() # making a copy of a UserDict is special cased
        self.assertEqual(u2b, u2c)

        class MyUserDict(UserDict.UserDict):
            def display(self): print self

        m2 = MyUserDict(u2)
        m2a = m2.copy()
        self.assertEqual(m2a, m2)

        # SF bug #476616 -- copy() of UserDict subclass shared data
        m2['foo'] = 'bar'
        self.assertNotEqual(m2a, m2)

        # Test keys, items, values
        self.assertEqual(u2.keys(), d2.keys())
        self.assertEqual(u2.items(), d2.items())
        self.assertEqual(u2.values(), d2.values())

        # Test has_key and "in".
        for i in u2.keys():
            self.assertIn(i, u2)
            self.assertEqual(i in u1, i in d1)
            self.assertEqual(i in u0, i in d0)
            with test_support.check_py3k_warnings():
                self.assertTrue(u2.has_key(i))
                self.assertEqual(u1.has_key(i), d1.has_key(i))
                self.assertEqual(u0.has_key(i), d0.has_key(i))

        # Test update
        t = UserDict.UserDict()
        t.update(u2)
        self.assertEqual(t, u2)
        class Items:
            def items(self):
                return (("x", 42), ("y", 23))
        t = UserDict.UserDict()
        t.update(Items())
        self.assertEqual(t, {"x": 42, "y": 23})

        # Test get
        for i in u2.keys():
            self.assertEqual(u2.get(i), u2[i])
            self.assertEqual(u1.get(i), d1.get(i))
            self.assertEqual(u0.get(i), d0.get(i))

        # Test "in" iteration.
        for i in xrange(20):
            u2[i] = str(i)
        ikeys = []
        for k in u2:
            ikeys.append(k)
        keys = u2.keys()
        self.assertEqual(set(ikeys), set(keys))

        # Test setdefault
        t = UserDict.UserDict()
        self.assertEqual(t.setdefault("x", 42), 42)
        self.assertTrue(t.has_key("x"))
        self.assertEqual(t.setdefault("x", 23), 42)

        # Test pop
        t = UserDict.UserDict(x=42)
        self.assertEqual(t.pop("x"), 42)
        self.assertRaises(KeyError, t.pop, "x")
        self.assertEqual(t.pop("x", 1), 1)
        t["x"] = 42
        self.assertEqual(t.pop("x", 1), 42)

        # Test popitem
        t = UserDict.UserDict(x=42)
        self.assertEqual(t.popitem(), ("x", 42))
        self.assertRaises(KeyError, t.popitem)

    def test_init(self):
        for kw in 'self', 'other', 'iterable':
            self.assertEqual(list(UserDict.UserDict(**{kw: 42}).items()),
                             [(kw, 42)])
        self.assertEqual(list(UserDict.UserDict({}, dict=42).items()),
                         [('dict', 42)])
        self.assertEqual(list(UserDict.UserDict({}, dict=None).items()),
                         [('dict', None)])
        with test_support.check_warnings((".*'dict'.*",
                                          PendingDeprecationWarning)):
            self.assertEqual(list(UserDict.UserDict(dict={'a': 42}).items()),
                             [('a', 42)])
        self.assertRaises(TypeError, UserDict.UserDict, 42)
        self.assertRaises(TypeError, UserDict.UserDict, (), ())
        self.assertRaises(TypeError, UserDict.UserDict.__init__)

    def test_update(self):
        for kw in 'self', 'other', 'iterable':
            d = UserDict.UserDict()
            d.update(**{kw: 42})
            self.assertEqual(list(d.items()), [(kw, 42)])
        d = UserDict.UserDict()
        with test_support.check_warnings((".*'dict'.*",
                                          PendingDeprecationWarning)):
            d.update(dict={'a': 42})
        self.assertEqual(list(d.items()), [('a', 42)])
        self.assertRaises(TypeError, UserDict.UserDict().update, 42)
        self.assertRaises(TypeError, UserDict.UserDict().update, {}, {})
        self.assertRaises(TypeError, UserDict.UserDict.update)

    def test_missing(self):
        # Make sure UserDict doesn't have a __missing__ method
        self.assertEqual(hasattr(UserDict, "__missing__"), False)
        # Test several cases:
        # (D) subclass defines __missing__ method returning a value
        # (E) subclass defines __missing__ method raising RuntimeError
        # (F) subclass sets __missing__ instance variable (no effect)
        # (G) subclass doesn't define __missing__ at all
        class D(UserDict.UserDict):
            def __missing__(self, key):
                return 42
        d = D({1: 2, 3: 4})
        self.assertEqual(d[1], 2)
        self.assertEqual(d[3], 4)
        self.assertNotIn(2, d)
        self.assertNotIn(2, d.keys())
        self.assertEqual(d[2], 42)
        class E(UserDict.UserDict):
            def __missing__(self, key):
                raise RuntimeError(key)
        e = E()
        try:
            e[42]
        except RuntimeError, err:
            self.assertEqual(err.args, (42,))
        else:
            self.fail("e[42] didn't raise RuntimeError")
        class F(UserDict.UserDict):
            def __init__(self):
                # An instance variable __missing__ should have no effect
                self.__missing__ = lambda key: None
                UserDict.UserDict.__init__(self)
        f = F()
        try:
            f[42]
        except KeyError, err:
            self.assertEqual(err.args, (42,))
        else:
            self.fail("f[42] didn't raise KeyError")
        class G(UserDict.UserDict):
            pass
        g = G()
        try:
            g[42]
        except KeyError, err:
            self.assertEqual(err.args, (42,))
        else:
            self.fail("g[42] didn't raise KeyError")

##########################
# Test Dict Mixin

class SeqDict(UserDict.DictMixin):
    """Dictionary lookalike implemented with lists.

    Used to test and demonstrate DictMixin
    """
    def __init__(self, other=None, **kwargs):
        self.keylist = []
        self.valuelist = []
        if other is not None:
            for (key, value) in other:
                self[key] = value
        for (key, value) in kwargs.iteritems():
            self[key] = value
    def __getitem__(self, key):
        try:
            i = self.keylist.index(key)
        except ValueError:
            raise KeyError
        return self.valuelist[i]
    def __setitem__(self, key, value):
        try:
            i = self.keylist.index(key)
            self.valuelist[i] = value
        except ValueError:
            self.keylist.append(key)
            self.valuelist.append(value)
    def __delitem__(self, key):
        try:
            i = self.keylist.index(key)
        except ValueError:
            raise KeyError
        self.keylist.pop(i)
        self.valuelist.pop(i)
    def keys(self):
        return list(self.keylist)
    def copy(self):
        d = self.__class__()
        for key, value in self.iteritems():
            d[key] = value
        return d
    @classmethod
    def fromkeys(cls, keys, value=None):
        d = cls()
        for key in keys:
            d[key] = value
        return d

class UserDictMixinTest(mapping_tests.TestMappingProtocol):
    type2test = SeqDict

    def test_all(self):
        ## Setup test and verify working of the test class

        # check init
        s = SeqDict()

        # exercise setitem
        s[10] = 'ten'
        s[20] = 'twenty'
        s[30] = 'thirty'

        # exercise delitem
        del s[20]
        # check getitem and setitem
        self.assertEqual(s[10], 'ten')
        # check keys() and delitem
        self.assertEqual(s.keys(), [10, 30])

        ## Now, test the DictMixin methods one by one
        # has_key
        self.assertTrue(s.has_key(10))
        self.assertTrue(not s.has_key(20))

        # __contains__
        self.assertIn(10, s)
        self.assertNotIn(20, s)

        # __iter__
        self.assertEqual([k for k in s], [10, 30])

        # __len__
        self.assertEqual(len(s), 2)

        # iteritems
        self.assertEqual(list(s.iteritems()), [(10,'ten'), (30, 'thirty')])

        # iterkeys
        self.assertEqual(list(s.iterkeys()), [10, 30])

        # itervalues
        self.assertEqual(list(s.itervalues()), ['ten', 'thirty'])

        # values
        self.assertEqual(s.values(), ['ten', 'thirty'])

        # items
        self.assertEqual(s.items(), [(10,'ten'), (30, 'thirty')])

        # get
        self.assertEqual(s.get(10), 'ten')
        self.assertEqual(s.get(15,'fifteen'), 'fifteen')
        self.assertEqual(s.get(15), None)

        # setdefault
        self.assertEqual(s.setdefault(40, 'forty'), 'forty')
        self.assertEqual(s.setdefault(10, 'null'), 'ten')
        del s[40]

        # pop
        self.assertEqual(s.pop(10), 'ten')
        self.assertNotIn(10, s)
        s[10] = 'ten'
        self.assertEqual(s.pop("x", 1), 1)
        s["x"] = 42
        self.assertEqual(s.pop("x", 1), 42)

        # popitem
        k, v = s.popitem()
        self.assertNotIn(k, s)
        s[k] = v

        # clear
        s.clear()
        self.assertEqual(len(s), 0)

        # empty popitem
        self.assertRaises(KeyError, s.popitem)

        # update
        s.update({10: 'ten', 20:'twenty'})
        self.assertEqual(s[10], 'ten')
        self.assertEqual(s[20], 'twenty')

        # cmp
        self.assertEqual(s, {10: 'ten', 20:'twenty'})
        t = SeqDict()
        t[20] = 'twenty'
        t[10] = 'ten'
        self.assertEqual(s, t)

def test_main():
    test_support.run_unittest(
        UserDictTest,
        UserDictMixinTest
    )

if __name__ == "__main__":
    test_main()
