Remove DictMixin which is superceded by collections.MutableMapping
diff --git a/Doc/library/userdict.rst b/Doc/library/userdict.rst
index 2d66270..820a743 100644
--- a/Doc/library/userdict.rst
+++ b/Doc/library/userdict.rst
@@ -52,24 +52,6 @@
    A real dictionary used to store the contents of the :class:`UserDict` class.
 
 
-.. class:: DictMixin()
-
-   Mixin defining all dictionary methods for classes that already have a minimum
-   dictionary interface including :meth:`__getitem__`, :meth:`__setitem__`,
-   :meth:`__delitem__`, and :meth:`keys`.
-
-   This mixin should be used as a superclass.  Adding each of the above methods
-   adds progressively more functionality.  For instance, defining all but
-   :meth:`__delitem__` will preclude only :meth:`pop` and :meth:`popitem` from the
-   full interface.
-
-   In addition to the four base methods, progressively more efficiency comes
-   with defining :meth:`__contains__` and :meth:`__iter__`.
-
-   Since the mixin has no knowledge of the subclass constructor, it does not define
-   :meth:`__init__` or :meth:`copy`.
-
-
 :mod:`UserList` --- Class wrapper for list objects
 ==================================================
 
diff --git a/Lib/UserDict.py b/Lib/UserDict.py
index bc05dfb..cb8a826 100644
--- a/Lib/UserDict.py
+++ b/Lib/UserDict.py
@@ -79,103 +79,3 @@
 class IterableUserDict(UserDict):
     def __iter__(self):
         return iter(self.data)
-
-class DictMixin:
-    # Mixin defining all dictionary methods for classes that already have
-    # a minimum dictionary interface including getitem, setitem, delitem,
-    # and keys. Without knowledge of the subclass constructor, the mixin
-    # does not define __init__() or copy().  In addition to the four base
-    # methods, progressively more efficiency comes with defining
-    # __contains__(), __iter__(), and iteritems().
-
-    # XXX It would make more sense to expect __iter__ to be primitive.
-
-    # second level definitions support higher levels
-    def __iter__(self):
-        for k in self.keys():
-            yield k
-    def __contains__(self, key):
-        try:
-            value = self[key]
-        except KeyError:
-            return False
-        return True
-
-    # third level takes advantage of second level definitions
-    def iterkeys(self):
-        return self.__iter__()
-    def iteritems(self):
-        for k in self:
-            yield (k, self[k])
-
-    # fourth level uses definitions from lower levels
-    def itervalues(self):
-        for _, v in self.iteritems():
-            yield v
-    def values(self):
-        return [v for _, v in self.iteritems()]
-    def items(self):
-        return list(self.iteritems())
-    def clear(self):
-        for key in list(self.iterkeys()):
-            del self[key]
-    def setdefault(self, key, default=None):
-        try:
-            return self[key]
-        except KeyError:
-            self[key] = default
-        return default
-    def pop(self, key, *args):
-        if len(args) > 1:
-            raise TypeError("pop expected at most 2 arguments, got "
-                            + repr(1 + len(args)))
-        try:
-            value = self[key]
-        except KeyError:
-            if args:
-                return args[0]
-            raise
-        del self[key]
-        return value
-    def popitem(self):
-        try:
-            k, v = next(self.iteritems())
-        except StopIteration:
-            raise KeyError('container is empty')
-        del self[k]
-        return (k, v)
-    def update(self, other=None, **kwargs):
-        # Make progressively weaker assumptions about "other"
-        if other is None:
-            pass
-        elif hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
-            for k, v in other.iteritems():
-                self[k] = v
-        elif hasattr(other, 'items'):  # items may also save memory and lookups
-            for k, v in other.items():
-                self[k] = v
-        elif hasattr(other, 'keys'):
-            for k in other.keys():
-                self[k] = other[k]
-        else:
-            for k, v in other:
-                self[k] = v
-        if kwargs:
-            self.update(kwargs)
-    def get(self, key, default=None):
-        try:
-            return self[key]
-        except KeyError:
-            return default
-    def __repr__(self):
-        return repr(dict(self.iteritems()))
-    def __eq__(self, other):
-        if isinstance(other, DictMixin):
-            other = dict(other.iteritems())
-        return dict(self.iteritems()) == other
-    def __ne__(self, other):
-        if isinstance(other, DictMixin):
-            other = dict(other.iteritems())
-        return dict(self.iteritems()) != other
-    def __len__(self):
-        return len(self.keys())
diff --git a/Lib/bsddb/dbshelve.py b/Lib/bsddb/dbshelve.py
index 942ee17..3727270 100644
--- a/Lib/bsddb/dbshelve.py
+++ b/Lib/bsddb/dbshelve.py
@@ -32,8 +32,7 @@
 import pickle
 import sys
 
-#At version 2.3 cPickle switched to using protocol instead of bin and
-#DictMixin was added
+#At version 2.3 cPickle switched to using protocol instead of bin
 if sys.version_info[:3] >= (2, 3, 0):
     HIGHEST_PROTOCOL = pickle.HIGHEST_PROTOCOL
     def _dumps(object, protocol):
diff --git a/Lib/test/test_shelve.py b/Lib/test/test_shelve.py
index e5d19f5..6d917ff 100644
--- a/Lib/test/test_shelve.py
+++ b/Lib/test/test_shelve.py
@@ -2,13 +2,13 @@
 import shelve
 import glob
 from test import test_support
-from UserDict import DictMixin
+from collections import MutableMapping
 from test.test_anydbm import dbm_iterator
 
 def L1(s):
     return s.decode("latin-1")
 
-class byteskeydict(DictMixin):
+class byteskeydict(MutableMapping):
     "Mapping that supports bytes keys"
 
     def __init__(self):
@@ -23,10 +23,15 @@
     def __delitem__(self, key):
         del self.d[L1(key)]
 
+    def __len__(self):
+        return len(self.d)
+
     def iterkeys(self):
         for k in self.d.keys():
             yield k.encode("latin-1")
 
+    __iter__ = iterkeys
+
     def keys(self):
         return list(self.iterkeys())
 
diff --git a/Lib/test/test_userdict.py b/Lib/test/test_userdict.py
index 039ed65..ac33be7 100644
--- a/Lib/test/test_userdict.py
+++ b/Lib/test/test_userdict.py
@@ -194,150 +194,11 @@
         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.items():
-            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.items():
-            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
-
-        # __contains__
-        self.assert_(10 in s)
-        self.assert_(20 not in s)
-
-        # __iter__
-        self.assertEqual([k for k in s], [10, 30])
-
-        # __len__
-        self.assertEqual(len(s), 2)
-
-        # iteritems
-        self.assertEqual(list(s.items()), [(10,'ten'), (30, 'thirty')])
-
-        # iterkeys
-        self.assertEqual(list(s.keys()), [10, 30])
-
-        # itervalues
-        self.assertEqual(list(s.values()), ['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.assert_(10 not in 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.assert_(k not in 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__":
diff --git a/Misc/NEWS b/Misc/NEWS
index a9da8b6..921b2a9 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -70,6 +70,8 @@
 Library
 -------
 
+- Removed UserDict.DictMixin.  Replaced all its uses with collections.MutableMapping.
+
 - Issue #1703: getpass() should flush after writing prompt.
 
 - Issue #1585: IDLE uses non-existent xrange() function.