From deadbf50e4cc3c541e706d5bf1aa73624bed36a6 Mon Sep 17 00:00:00 2001
From: Raymond Hettinger <python@rcn.com>
Date: Fri, 12 Sep 2003 06:33:37 +0000
Subject: SF #662923

Add support for the iterator and mapping protocols.
For Py2.3, this was done for shelve, dumbdbm and other mapping objects, but
not for bsddb and dbhash which were inadvertently missed.
---
 Doc/lib/libbsddb.tex   | 19 +++++++++++++++++--
 Doc/lib/libdbhash.tex  | 14 +++++++-------
 Lib/bsddb/__init__.py  | 11 ++++++++++-
 Lib/test/test_bsddb.py | 24 ++++++++++++++++++------
 Misc/NEWS              |  4 ++++
 5 files changed, 56 insertions(+), 16 deletions(-)

diff --git a/Doc/lib/libbsddb.tex b/Doc/lib/libbsddb.tex
index 7fb8f76..719783b 100644
--- a/Doc/lib/libbsddb.tex
+++ b/Doc/lib/libbsddb.tex
@@ -100,8 +100,9 @@ systems which ship with the old Berkeley DB 1.85 database library.  The
 
 \subsection{Hash, BTree and Record Objects \label{bsddb-objects}}
 
-Once instantiated, hash, btree and record objects support the following
-methods:
+Once instantiated, hash, btree and record objects support
+the same methods as dictionaries.  In addition, they support
+the following methods:
 
 \begin{methoddesc}{close}{}
 Close the underlying file.  The object can no longer be accessed.  Since
@@ -177,6 +178,20 @@ Example:
 ('2', '4')
 >>> db.previous() 
 ('1', '1')
+>>> for k, v in db.iteritems():
+...     print k, v
+0 0
+1 1
+2 4
+3 9
+4 16
+5 25
+6 36
+7 49
+8 64
+9 81
+>>> 8 in db
+True
 >>> db.sync()
 0
 \end{verbatim}
diff --git a/Doc/lib/libdbhash.tex b/Doc/lib/libdbhash.tex
index 00a6d08..ecaa6c9 100644
--- a/Doc/lib/libdbhash.tex
+++ b/Doc/lib/libdbhash.tex
@@ -51,23 +51,23 @@ This module provides an exception and a function:
 \subsection{Database Objects \label{dbhash-objects}}
 
 The database objects returned by \function{open()} provide the methods 
-common to all the DBM-style databases.  The following methods are
-available in addition to the standard methods.
+common to all the DBM-style databases and mapping objects.  The following
+methods are available in addition to the standard methods.
 
 \begin{methoddesc}[dbhash]{first}{}
-  It's possible to loop over every key in the database using this method 
-  and the \method{next()} method.  The traversal is ordered by
+  It's possible to loop over every key/value pair in the database using
+  this method   and the \method{next()} method.  The traversal is ordered by
   the databases internal hash values, and won't be sorted by the key
   values.  This method returns the starting key.
 \end{methoddesc}
 
 \begin{methoddesc}[dbhash]{last}{}
-  Return the last key in a database traversal.  This may be used to
+  Return the last key/value pair in a database traversal.  This may be used to
   begin a reverse-order traversal; see \method{previous()}.
 \end{methoddesc}
 
 \begin{methoddesc}[dbhash]{next}{}
-  Returns the key next key in a database traversal.  The
+  Returns the key next key/value pair in a database traversal.  The
   following code prints every key in the database \code{db}, without
   having to create a list in memory that contains them all:
 
@@ -79,7 +79,7 @@ for i in xrange(1, len(d)):
 \end{methoddesc}
 
 \begin{methoddesc}[dbhash]{previous}{}
-  Returns the previous key in a forward-traversal of the database.
+  Returns the previous key/value pair in a forward-traversal of the database.
   In conjunction with \method{last()}, this may be used to implement
   a reverse-order traversal.
 \end{methoddesc}
diff --git a/Lib/bsddb/__init__.py b/Lib/bsddb/__init__.py
index 1ec6adc..5fc8a38 100644
--- a/Lib/bsddb/__init__.py
+++ b/Lib/bsddb/__init__.py
@@ -52,8 +52,9 @@ error = db.DBError  # So bsddb.error will mean something...
 
 #----------------------------------------------------------------------
 
+import UserDict
 
-class _DBWithCursor:
+class _DBWithCursor(UserDict.DictMixin):
     """
     A simple wrapper around DB that makes it look like the bsddbobject in
     the old module.  It uses a cursor as needed to provide DB traversal.
@@ -144,6 +145,14 @@ class _DBWithCursor:
         self._checkOpen()
         return self.db.sync()
 
+    def __iter__(self):
+        try:
+            yield self.first()[0]
+            next = self.next
+            while 1:
+                yield next()[0]
+        except _bsddb.DBNotFoundError:
+            return
 
 #----------------------------------------------------------------------
 # Compatibility object factory functions
diff --git a/Lib/test/test_bsddb.py b/Lib/test/test_bsddb.py
index aa58ef8..87145fb 100755
--- a/Lib/test/test_bsddb.py
+++ b/Lib/test/test_bsddb.py
@@ -20,12 +20,24 @@ def test(openmethod, what, ondisk=1):
     verify(f.keys() == [])
     if verbose:
         print 'creation...'
-    f['0'] = ''
-    f['a'] = 'Guido'
-    f['b'] = 'van'
-    f['c'] = 'Rossum'
-    f['d'] = 'invented'
-    f['f'] = 'Python'
+    keys = ['0', 'a', 'b', 'c', 'd', 'e', 'f']
+    values = ['', 'Guido', 'van', 'Rossum', 'invented', 'Python']
+    items = zip(keys, values)
+    for k, v in items:
+        f[k] = v
+
+    # test mapping iteration methods
+    from sets import Set
+    def verifyset(s1, s2):
+        verify(Set(s1) == Set(s2))
+    verify(keys, f.keys())
+    verify(values, f.values())
+    verify(items, f.items())
+    verify(keys, f)
+    verify(keys, f.iterkeys())
+    verify(values, f.itervalues())
+    verify(items, f.iteritems())
+
     if verbose:
         print '%s %s %s' % (f['a'], f['b'], f['c'])
 
diff --git a/Misc/NEWS b/Misc/NEWS
index 5cf8d72..6f9855c 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -35,6 +35,10 @@ Extension modules
 Library
 -------
 
+- The bsddb module and dbhash module now support the iterator and
+  mapping protocols which make them more substitutable for dictionaries
+  and shelves.
+
 - The csv module's DictReader and DictWriter classes now accept keyword
   arguments.  This was an omission in the initial implementation.
 
-- 
cgit v0.12

