Skip to content

Commit

Permalink
SF patch #520382: Expand shelve.py to have a full dictionary interface
Browse files Browse the repository at this point in the history
and add a mixin to UserDict.py to make it easier to implement a full
dictionary interface.
  • Loading branch information
rhettinger committed Nov 15, 2002
1 parent 3a7f405 commit 7994716
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 2 deletions.
4 changes: 4 additions & 0 deletions Doc/lib/libshelve.tex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ \section{\module{shelve} ---
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}
Expand Down
25 changes: 24 additions & 1 deletion Doc/lib/libuserdict.tex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ \section{\module{UserDict} ---
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
Expand All @@ -35,6 +41,23 @@ \section{\module{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}
Expand Down
64 changes: 64 additions & 0 deletions Lib/UserDict.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,67 @@ def __contains__(self, key):
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()))
4 changes: 3 additions & 1 deletion Lib/shelve.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@
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.
Expand Down
9 changes: 9 additions & 0 deletions Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down

0 comments on commit 7994716

Please sign in to comment.