SF patch #520382: Expand shelve.py to have a full dictionary interface
and add a mixin to UserDict.py to make it easier to implement a full dictionary interface.
This commit is contained in:
parent
3a7f405f5b
commit
7994716b6b
|
@ -33,6 +33,10 @@ list = d.keys() # a list of all existing keys (slow!)
|
|||
d.close() # close it
|
||||
\end{verbatim}
|
||||
|
||||
In addition to the above, shelve supports all methods that are
|
||||
supported by dictionaries. This eases the transition from dictionary
|
||||
based scripts to those requiring persistent storage.
|
||||
|
||||
Restrictions:
|
||||
|
||||
\begin{itemize}
|
||||
|
|
|
@ -15,7 +15,13 @@ your own dictionary-like classes, which can inherit from
|
|||
them and override existing methods or add new ones. In this way one
|
||||
can add new behaviors to dictionaries.
|
||||
|
||||
The \module{UserDict} module defines the \class{UserDict} class:
|
||||
The module also defines a mixin defining all dictionary methods for
|
||||
classes that already have a minimum mapping interface. This greatly
|
||||
simplifies writing classes that need to be substitutable for
|
||||
dictionaries (such as the shelve module).
|
||||
|
||||
The \module{UserDict} module defines the \class{UserDict} class
|
||||
and \class{DictMixin}:
|
||||
|
||||
\begin{classdesc}{UserDict}{\optional{initialdata}}
|
||||
Class that simulates a dictionary. The instance's
|
||||
|
@ -35,6 +41,23 @@ A real dictionary used to store the contents of the \class{UserDict}
|
|||
class.
|
||||
\end{memberdesc}
|
||||
|
||||
\begin{classdesc}{DictMixin}{}
|
||||
Mixin defining all dictionary methods for classes that already have
|
||||
a minimum dictionary interface including\method{__getitem__},
|
||||
\method{__setitem__}, \method{__delitem__}, and \method{keys}.
|
||||
|
||||
This mixin should be used as a superclass. Adding each of the
|
||||
above methods adds progressively more functionality. For instance,
|
||||
the absence of \method{__delitem__} precludes only \method{pop}
|
||||
and \method{popitem}.
|
||||
|
||||
While the four methods listed above are sufficient to support the
|
||||
entire dictionary interface, progessively more efficiency comes
|
||||
with defining \method{__contains__}, \method{__iter__}, and
|
||||
\method{iteritems}.
|
||||
|
||||
\end{classdesc}
|
||||
|
||||
|
||||
\section{\module{UserList} ---
|
||||
Class wrapper for list objects}
|
||||
|
|
|
@ -60,3 +60,67 @@ 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 '''
|
||||
|
||||
# first level provided by subclass: getitem, setitem, delitem, and keys
|
||||
|
||||
# second level definitions which assume only getitem and keys
|
||||
def has_key(self, key):
|
||||
try:
|
||||
value = self[key]
|
||||
except KeyError:
|
||||
return False
|
||||
return True
|
||||
__contains__ = has_key
|
||||
def __iter__(self):
|
||||
for k in self.keys():
|
||||
yield k
|
||||
def __len__(self):
|
||||
return len(self.keys())
|
||||
|
||||
# third level uses second level instead of first
|
||||
def iteritems(self):
|
||||
for k in self:
|
||||
yield (k, self[k])
|
||||
iterkeys = __iter__
|
||||
|
||||
# fourth level uses second and third levels instead of first
|
||||
def itervalues(self):
|
||||
for _, v in self.iteritems():
|
||||
yield v
|
||||
def values(self):
|
||||
return [self[key] for key in self.keys()]
|
||||
def items(self):
|
||||
return list(self.iteritems())
|
||||
def clear(self):
|
||||
for key in self.keys():
|
||||
del self[key]
|
||||
def setdefault(self, key, default):
|
||||
if key not in self:
|
||||
self[key] = default
|
||||
return default
|
||||
return self[key]
|
||||
def pop(self, key):
|
||||
value = self[key]
|
||||
del self[key]
|
||||
return value
|
||||
def popitem(self):
|
||||
try:
|
||||
k, v = self.iteritems().next()
|
||||
except StopIteration:
|
||||
raise KeyError, 'dictionary is empty'
|
||||
del self[k]
|
||||
return (k, v)
|
||||
def update(self, other):
|
||||
for key in other.keys():
|
||||
self[key] = other[key]
|
||||
def get(self, key, default=None):
|
||||
if key in self:
|
||||
return self[key]
|
||||
return default
|
||||
def __repr__(self):
|
||||
return repr(dict(self.items()))
|
||||
|
|
|
@ -40,9 +40,11 @@ try:
|
|||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
|
||||
import UserDict
|
||||
|
||||
__all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"]
|
||||
|
||||
class Shelf:
|
||||
class Shelf(UserDict.DictMixin):
|
||||
"""Base class for shelf implementations.
|
||||
|
||||
This is initialized with a dictionary-like object.
|
||||
|
|
|
@ -381,6 +381,15 @@ Extension modules
|
|||
Library
|
||||
-------
|
||||
|
||||
- UserDict.py now defines a DictMixin class which defines all dictionary
|
||||
methods for classes that already have a minimum mapping interface.
|
||||
This greatly simplifies writing classes that need to be substitutable
|
||||
for dictionaries (such as the shelve module).
|
||||
|
||||
- shelve.py now subclasses from UserDict.DictMixin. Now shelve supports
|
||||
all dictionary methods. This eases the transition to persistent
|
||||
storage for scripts originally written with dictionaries in mind.
|
||||
|
||||
- A new package, logging, implements the logging API defined by PEP
|
||||
282. The code is written by Vinay Sajip.
|
||||
|
||||
|
|
Loading…
Reference in New Issue