]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix documentation bugs.
authorRaymond Hettinger <python@rcn.com>
Tue, 16 Sep 2003 21:42:13 +0000 (21:42 +0000)
committerRaymond Hettinger <python@rcn.com>
Tue, 16 Sep 2003 21:42:13 +0000 (21:42 +0000)
Add support for iterators and other mapping methods.
Convert tests to unittest format and expand their coverage.

Doc/lib/libbsddb.tex
Doc/lib/libdbhash.tex
Lib/bsddb/__init__.py
Lib/test/test_bsddb.py
Misc/NEWS

index 7fb8f76e01b4c8b4f939a9c433e0a14d805ec5cf..8c6b392846690c3c0b620391675262ea0fca65ff 100644 (file)
@@ -100,8 +100,10 @@ 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 methods listed below.
+\versionchanged[Added mapping methods]{2.3.1}
 
 \begin{methoddesc}{close}{}
 Close the underlying file.  The object can no longer be accessed.  Since
@@ -177,6 +179,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}
index 00a6d080bfdebfb16e1cea3ba1e7c2308ce7ca94..f5f98eae19c71924ee150e66441ccb727923e6e9 100644 (file)
@@ -51,35 +51,35 @@ 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:
 
 \begin{verbatim}
 print db.first()
-for i in xrange(1, len(d)):
+for i in xrange(1, len(db)):
     print db.next()
 \end{verbatim}
 \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}
index 1ec6adc195f22e38a5d1b7abfc3f4febc162e73a..2910236b3d7441e272322350e9fad92c58fe35ae 100644 (file)
@@ -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,23 @@ 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
+
+    def iteritems(self):
+        try:
+            yield self.first()
+            next = self.next
+            while 1:
+                yield next()
+        except _bsddb.DBNotFoundError:
+            return
 
 #----------------------------------------------------------------------
 # Compatibility object factory functions
index aa58ef8ef7f6af0afd389d30a99095082011c8c4..73a2d966057f606aa2fb6f0f9493fa8d66671900 100755 (executable)
 #! /usr/bin/env python
-"""Test script for the bsddb C module
-   Roger E. Masse
+"""Test script for the bsddb C module by Roger E. Masse
+   Adapted to unittest format and expanded scope by Raymond Hettinger
 """
 import os
 import bsddb
 import dbhash # Just so we know it's imported
-from test.test_support import verbose, verify, TESTFN
-
-def test(openmethod, what, ondisk=1):
-
-    if verbose:
-        print '\nTesting: ', what, (ondisk and "on disk" or "in memory")
-
-    if ondisk:
-        fname = TESTFN
-    else:
-        fname = None
-    f = openmethod(fname, 'c')
-    verify(f.keys() == [])
-    if verbose:
-        print 'creation...'
-    f['0'] = ''
-    f['a'] = 'Guido'
-    f['b'] = 'van'
-    f['c'] = 'Rossum'
-    f['d'] = 'invented'
-    f['f'] = 'Python'
-    if verbose:
-        print '%s %s %s' % (f['a'], f['b'], f['c'])
-
-    if what == 'BTree' :
-        if verbose:
-            print 'key ordering...'
-        f.set_location(f.first()[0])
-        while 1:
-            try:
-                rec = f.next()
-            except KeyError:
-                if rec != f.last():
-                    print 'Error, last != last!'
-                f.previous()
-                break
-            if verbose:
-                print rec
-        if not f.has_key('a'):
-            print 'Error, missing key!'
-
-    f.sync()
-    f.close()
-    if ondisk:
-        # if we're using an in-memory only db, we can't reopen it
-        # so finish here.
-        if verbose:
-            print 'modification...'
-        f = openmethod(fname, 'w')
-        f['d'] = 'discovered'
-
-        if verbose:
-            print 'access...'
-        for key in f.keys():
-            word = f[key]
-            if verbose:
-                print word
-
-        f.close()
+import unittest
+from test import test_support
+from sets import Set
+
+class TestBSDDB(unittest.TestCase):
+
+    def setUp(self):
+        self.f = self.openmethod[0](self.fname, 'c')
+        self.d = dict(q='Guido', w='van', e='Rossum', r='invented', t='Python', y='')
+        for k, v in self.d.iteritems():
+            self.f[k] = v
+
+    def tearDown(self):
+        self.f.sync()
+        self.f.close()
+        if self.fname is None:
+            return
         try:
-            os.remove(fname)
+            os.remove(self.fname)
         except os.error:
             pass
 
-types = [(bsddb.btopen, 'BTree'),
-         (bsddb.hashopen, 'Hash Table'),
-         (bsddb.btopen, 'BTree', 0),
-         (bsddb.hashopen, 'Hash Table', 0),
-         # (bsddb.rnopen,'Record Numbers'), 'put' for RECNO for bsddb 1.85
-         #                                   appears broken... at least on
-         #                                   Solaris Intel - rmasse 1/97
-         ]
-
-for type in types:
-    test(*type)
+    def test_getitem(self):
+        for k, v in self.d.iteritems():
+            self.assertEqual(self.f[k], v)
+
+    def test_len(self):
+        self.assertEqual(len(self.f), len(self.d))
+
+    def test_change(self):
+        self.f['r'] = 'discovered'
+        self.assertEqual(self.f['r'], 'discovered')
+        self.assert_('r' in self.f.keys())
+        self.assert_('discovered' in self.f.values())
+
+    def test_close_and_reopen(self):
+        if self.fname is None:
+            # if we're using an in-memory only db, we can't reopen it
+            # so finish here.
+            return
+        self.f.close()
+        self.f = self.openmethod[0](self.fname, 'w')
+        for k, v in self.d.iteritems():
+            self.assertEqual(self.f[k], v)
+
+    def assertSetEquals(self, seqn1, seqn2):
+        self.assertEqual(Set(seqn1), Set(seqn2))
+
+    def test_mapping_iteration_methods(self):
+        f = self.f
+        d = self.d
+        self.assertSetEquals(d, f)
+        self.assertSetEquals(d.keys(), f.keys())
+        self.assertSetEquals(d.values(), f.values())
+        self.assertSetEquals(d.items(), f.items())
+        self.assertSetEquals(d.iterkeys(), f.iterkeys())
+        self.assertSetEquals(d.itervalues(), f.itervalues())
+        self.assertSetEquals(d.iteritems(), f.iteritems())
+
+    def test_first_next_looping(self):
+        items = [self.f.first()]
+        for i in xrange(1, len(self.f)):
+            items.append(self.f.next())
+        self.assertSetEquals(items, self.d.items())
+
+    def test_previous_last_looping(self):
+        items = [self.f.last()]
+        for i in xrange(1, len(self.f)):
+            items.append(self.f.previous())
+        self.assertSetEquals(items, self.d.items())
+
+    def test_set_location(self):
+        self.assertEqual(self.f.set_location('e'), ('e', self.d['e']))
+
+    def test_contains(self):
+        for k in self.d:
+            self.assert_(k in self.f)
+        self.assert_('not here' not in self.f)
+
+    def test_has_key(self):
+        for k in self.d:
+            self.assert_(self.f.has_key(k))
+        self.assert_(not self.f.has_key('not here'))
+
+    def test_clear(self):
+        self.f.clear()
+        self.assertEqual(len(self.f), 0)
+
+    def test_popitem(self):
+        k, v = self.f.popitem()
+        self.assert_(k in self.d)
+        self.assert_(v in self.d.values())
+        self.assert_(k not in self.f)
+        self.assertEqual(len(self.d)-1, len(self.f))
+
+    def test_pop(self):
+        k = 'w'
+        v = self.f.pop(k)
+        self.assertEqual(v, self.d[k])
+        self.assert_(k not in self.f)
+        self.assert_(v not in self.f.values())
+        self.assertEqual(len(self.d)-1, len(self.f))
+
+    def test_get(self):
+        self.assertEqual(self.f.get('NotHere'), None)
+        self.assertEqual(self.f.get('NotHere', 'Default'), 'Default')
+        self.assertEqual(self.f.get('q', 'Default'), self.d['q'])
+
+    def test_setdefault(self):
+        self.assertEqual(self.f.setdefault('new', 'dog'), 'dog')
+        self.assertEqual(self.f.setdefault('r', 'cat'), self.d['r'])
+
+    def test_update(self):
+        new = dict(y='life', u='of', i='brian')
+        self.f.update(new)
+        self.d.update(new)
+        for k, v in self.d.iteritems():
+            self.assertEqual(self.f[k], v)
+
+    def test_keyordering(self):
+        if self.openmethod[0] is not bsddb.btopen:
+            return
+        keys = self.d.keys()
+        keys.sort()
+        self.assertEqual(self.f.first()[0], keys[0])
+        self.assertEqual(self.f.next()[0], keys[1])
+        self.assertEqual(self.f.last()[0], keys[-1])
+        self.assertEqual(self.f.previous()[0], keys[-2])
+        self.assertEqual(list(self.f), keys)
+
+class TestBTree(TestBSDDB):
+    fname = test_support.TESTFN
+    openmethod = [bsddb.btopen]
+
+class TestBTree_InMemory(TestBSDDB):
+    fname = None
+    openmethod = [bsddb.btopen]
+
+class TestHashTable(TestBSDDB):
+    fname = test_support.TESTFN
+    openmethod = [bsddb.hashopen]
+
+class TestHashTable_InMemory(TestBSDDB):
+    fname = None
+    openmethod = [bsddb.hashopen]
+
+##         # (bsddb.rnopen,'Record Numbers'), 'put' for RECNO for bsddb 1.85
+##         #                                   appears broken... at least on
+##         #                                   Solaris Intel - rmasse 1/97
+
+def test_main(verbose=None):
+    test_support.run_unittest(
+        TestBTree,
+        TestHashTable,
+        TestBTree_InMemory,
+        TestHashTable_InMemory,
+    )
+
+if __name__ == "__main__":
+    test_main(verbose=True)
index 79bd3ffff13242ea4d4f37ec985f40a8ff7d36f2..b25698c6fd7dc05701b88ccc612229ae880018e9 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -59,6 +59,9 @@ Extension modules
 Library
 -------
 
+- The bsddb module and dbhash module now support the iterator and
+  mapping protocols. 
+
 - Bug #711632: Reset all state members in HTMLParser.reset.
 
 - Bug #792649:  logging.ConfigStreamHandler had an uninitialized variable