summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/libshelve.tex4
-rw-r--r--Doc/lib/libuserdict.tex25
-rw-r--r--Lib/UserDict.py64
-rw-r--r--Lib/shelve.py4
-rw-r--r--Misc/NEWS9
5 files changed, 104 insertions, 2 deletions
diff --git a/Doc/lib/libshelve.tex b/Doc/lib/libshelve.tex
index 76eaaf4..1e02c7b 100644
--- a/Doc/lib/libshelve.tex
+++ b/Doc/lib/libshelve.tex
@@ -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}
diff --git a/Doc/lib/libuserdict.tex b/Doc/lib/libuserdict.tex
index d665686..e01c546 100644
--- a/Doc/lib/libuserdict.tex
+++ b/Doc/lib/libuserdict.tex
@@ -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}
diff --git a/Lib/UserDict.py b/Lib/UserDict.py
index 91af83c..b6b36b2 100644
--- a/Lib/UserDict.py
+++ b/Lib/UserDict.py
@@ -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()))
diff --git a/Lib/shelve.py b/Lib/shelve.py
index ae8df3f..7a318a6 100644
--- a/Lib/shelve.py
+++ b/Lib/shelve.py
@@ -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.
diff --git a/Misc/NEWS b/Misc/NEWS
index 34f70b7..7a6b780 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.