mirror of
https://github.com/python/cpython.git
synced 2025-11-27 05:44:16 +00:00
Remove DictMixin which is superceded by collections.MutableMapping
This commit is contained in:
parent
d190f9c45e
commit
edf3b734c0
6 changed files with 10 additions and 261 deletions
|
|
@ -52,24 +52,6 @@ provide the following attribute:
|
||||||
A real dictionary used to store the contents of the :class:`UserDict` class.
|
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
|
:mod:`UserList` --- Class wrapper for list objects
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
|
|
|
||||||
100
Lib/UserDict.py
100
Lib/UserDict.py
|
|
@ -79,103 +79,3 @@ class UserDict:
|
||||||
class IterableUserDict(UserDict):
|
class IterableUserDict(UserDict):
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self.data)
|
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 pickle
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
#At version 2.3 cPickle switched to using protocol instead of bin and
|
#At version 2.3 cPickle switched to using protocol instead of bin
|
||||||
#DictMixin was added
|
|
||||||
if sys.version_info[:3] >= (2, 3, 0):
|
if sys.version_info[:3] >= (2, 3, 0):
|
||||||
HIGHEST_PROTOCOL = pickle.HIGHEST_PROTOCOL
|
HIGHEST_PROTOCOL = pickle.HIGHEST_PROTOCOL
|
||||||
def _dumps(object, protocol):
|
def _dumps(object, protocol):
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ import unittest
|
||||||
import shelve
|
import shelve
|
||||||
import glob
|
import glob
|
||||||
from test import test_support
|
from test import test_support
|
||||||
from UserDict import DictMixin
|
from collections import MutableMapping
|
||||||
from test.test_anydbm import dbm_iterator
|
from test.test_anydbm import dbm_iterator
|
||||||
|
|
||||||
def L1(s):
|
def L1(s):
|
||||||
return s.decode("latin-1")
|
return s.decode("latin-1")
|
||||||
|
|
||||||
class byteskeydict(DictMixin):
|
class byteskeydict(MutableMapping):
|
||||||
"Mapping that supports bytes keys"
|
"Mapping that supports bytes keys"
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -23,10 +23,15 @@ class byteskeydict(DictMixin):
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
del self.d[L1(key)]
|
del self.d[L1(key)]
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.d)
|
||||||
|
|
||||||
def iterkeys(self):
|
def iterkeys(self):
|
||||||
for k in self.d.keys():
|
for k in self.d.keys():
|
||||||
yield k.encode("latin-1")
|
yield k.encode("latin-1")
|
||||||
|
|
||||||
|
__iter__ = iterkeys
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return list(self.iterkeys())
|
return list(self.iterkeys())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -194,150 +194,11 @@ class UserDictTest(mapping_tests.TestHashMappingProtocol):
|
||||||
else:
|
else:
|
||||||
self.fail("g[42] didn't raise KeyError")
|
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():
|
def test_main():
|
||||||
test_support.run_unittest(
|
test_support.run_unittest(
|
||||||
UserDictTest,
|
UserDictTest,
|
||||||
UserDictMixinTest
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Removed UserDict.DictMixin. Replaced all its uses with collections.MutableMapping.
|
||||||
|
|
||||||
- Issue #1703: getpass() should flush after writing prompt.
|
- Issue #1703: getpass() should flush after writing prompt.
|
||||||
|
|
||||||
- Issue #1585: IDLE uses non-existent xrange() function.
|
- Issue #1585: IDLE uses non-existent xrange() function.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue