Commit 43b2f784 authored by Raymond Hettinger's avatar Raymond Hettinger

Remove DictMixin which is superceded by collections.MutableMapping

parent d11eae7f
......@@ -52,24 +52,6 @@ provide the following attribute:
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
==================================================
......
......@@ -79,103 +79,3 @@ class UserDict:
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())
......@@ -32,8 +32,7 @@ storage.
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):
......
......@@ -2,13 +2,13 @@ import unittest
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 @@ class byteskeydict(DictMixin):
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())
......
......@@ -194,150 +194,11 @@ class UserDictTest(mapping_tests.TestHashMappingProtocol):
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__":
......
......@@ -70,6 +70,8 @@ Extension Modules
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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment