mirror of
https://github.com/python/cpython.git
synced 2025-11-25 21:11:09 +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.
|
||||
|
||||
|
||||
.. 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
|
||||
==================================================
|
||||
|
||||
|
|
|
|||
100
Lib/UserDict.py
100
Lib/UserDict.py
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue