Code

Enabled transaction support in the bsddb backend. It uses the anydbm code
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 10 Dec 2001 22:20:01 +0000 (22:20 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 10 Dec 2001 22:20:01 +0000 (22:20 +0000)
where possible, only replacing methods where the db is opened (it uses the
btree opener specifically.)
Also cleaned up some change note generation.
Made the backends package work with pydoc too.

git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@452 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
roundup/backends/__init__.py
roundup/backends/back_anydbm.py
roundup/backends/back_bsddb.py
roundup/cgi_client.py
roundup/roundupdb.py

index 50ea6fa29d7c8a85be05b4b46eed47224990ff4d..3114b4536392166bb0ec8ee6c9fc04cf80e80687 100644 (file)
@@ -11,8 +11,9 @@ Feature:
  . Login now takes you to the page you back to the were denied access to.
  . Admin user now can has a user index link on their web interface.
  . We now have basic transaction support. Information is only written to
-   the database when the commit() method is called. Only the anydbm backend
-   is modified in this way - neither of the bsddb backends have been.
+   the database when the commit() method is called. Only the anydbm and
+   bsddb3 backends are modified in this way - the bsddb3 backend needs a
+   lot more work anyway...
     - the CGI and mailgw automatically commit() at the end of processing a
       single transaction
     - the admin tool requires an explicit "commit" - it will prompt at exit
@@ -20,7 +21,6 @@ Feature:
       during the session (up to the last commit).
  . Added the "display" command to the admin tool - displays a node's values
 
-
 Fixed:
  . Lots of bugs, thanks Roché and others on the devel mailing list!
  . login_action and newuser_action return values were being ignored
@@ -34,6 +34,8 @@ Fixed:
  . #487476 ] INSTALL.txt
  . #489760 ] [issue] only subject
  . fixed doc/index.html to include the quoting in the mail alias.
+ . fixed the backends __init__ so we can pydoc the backend modules
+ . web i/f reports "note added" if there are no changes but a note is entered
 
 
 2001-11-23 - 0.3.0 
index cb01a567c64ebf2b2bf50060a47c1ca52e9d1cbe..2c181a2e3d1f55e727c08b42ba4e83ffc28a74b1 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: __init__.py,v 1.7 2001-12-10 00:57:38 richard Exp $
+# $Id: __init__.py,v 1.8 2001-12-10 22:20:01 richard Exp $
 
 __all__ = []
 
@@ -27,15 +27,15 @@ try:
     del dumbdbm
     import back_anydbm
     anydbm = back_anydbm
-    del back_anydbm
     __all__.append('anydbm')
+except AssertionError:
+    del back_anydbm
 except:
     pass
 
 try:
     import back_bsddb
     bsddb = back_bsddb
-    del back_bsddb
     __all__.append('bsddb')
 except:
     pass
@@ -43,14 +43,22 @@ except:
 try:
     import back_bsddb3
     bsddb3 = back_bsddb3
-    del back_bsddb3
     __all__.append('bsddb3')
 except:
     pass
 
-
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.7  2001/12/10 00:57:38  richard
+# From CHANGES:
+#  . Added the "display" command to the admin tool - displays a node's values
+#  . #489760 ] [issue] only subject
+#  . fixed the doc/index.html to include the quoting in the mail alias.
+#
+# Also:
+#  . fixed roundup-admin so it works with transactions
+#  . disabled the back_anydbm module if anydbm tries to use dumbdbm
+#
 # Revision 1.6  2001/08/07 00:24:42  richard
 # stupid typo
 #
index 156857e1bd9af090e196b1b9d220bf4d68debf09..6a90a1d9404b5c0a24c8d1cc240c04c1f6251342 100644 (file)
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-#$Id: back_anydbm.py,v 1.13 2001-12-02 05:06:16 richard Exp $
+#$Id: back_anydbm.py,v 1.14 2001-12-10 22:20:01 richard Exp $
+'''
+This module defines a backend that saves the hyperdatabase in a database
+chosen by anydbm. It is guaranteed to always be available in python
+versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several
+serious bugs, and is not available)
+'''
 
 import anydbm, os, marshal
 from roundup import hyperdb, date, password
@@ -32,7 +38,6 @@ class Database(hyperdb.Database):
         . perhaps detect write collisions (related to above)?
 
     """
-
     def __init__(self, storagelocator, journaltag=None):
         """Open a hyperdatabase given a specifier to some storage.
 
@@ -52,6 +57,7 @@ class Database(hyperdb.Database):
         self.dirtynodes = {}    # keep track of the dirty nodes by class
         self.newnodes = {}      # keep track of the new nodes by class
         self.transactions = []
+
     #
     # Classes
     #
@@ -248,6 +254,20 @@ class Database(hyperdb.Database):
 
 #
 #$Log: not supported by cvs2svn $
+#Revision 1.13  2001/12/02 05:06:16  richard
+#. We now use weakrefs in the Classes to keep the database reference, so
+#  the close() method on the database is no longer needed.
+#  I bumped the minimum python requirement up to 2.1 accordingly.
+#. #487480 ] roundup-server
+#. #487476 ] INSTALL.txt
+#
+#I also cleaned up the change message / post-edit stuff in the cgi client.
+#There's now a clearly marked "TODO: append the change note" where I believe
+#the change note should be added there. The "changes" list will obviously
+#have to be modified to be a dict of the changes, or somesuch.
+#
+#More testing needed.
+#
 #Revision 1.12  2001/12/01 07:17:50  richard
 #. We now have basic transaction support! Information is only written to
 #  the database when the commit() method is called. Only the anydbm
index baa80703bff0dc997658300d9c24b7fc87a242b5..9f62f572ea3d55d964942a9bd27682f679e45aa0 100644 (file)
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-#$Id: back_bsddb.py,v 1.12 2001-11-21 02:34:18 richard Exp $
+#$Id: back_bsddb.py,v 1.13 2001-12-10 22:20:01 richard Exp $
+'''
+This module defines a backend that saves the hyperdatabase in BSDDB.
+'''
 
 import bsddb, os, marshal
 from roundup import hyperdb, date, password
 
+# these classes are so similar, we just use the anydbm methods
+import back_anydbm
+
 #
 # Now the database
 #
-class Database(hyperdb.Database):
+class Database(back_anydbm.Database):
     """A database for storing records containing flexible data types."""
-
-    def __init__(self, storagelocator, journaltag=None):
-        """Open a hyperdatabase given a specifier to some storage.
-
-        The meaning of 'storagelocator' depends on the particular
-        implementation of the hyperdatabase.  It could be a file name,
-        a directory path, a socket descriptor for a connection to a
-        database over the network, etc.
-
-        The 'journaltag' is a token that will be attached to the journal
-        entries for any edits done on the database.  If 'journaltag' is
-        None, the database is opened in read-only mode: the Class.create(),
-        Class.set(), and Class.retire() methods are disabled.
-        """
-        self.dir, self.journaltag = storagelocator, journaltag
-        self.classes = {}
-
-    #
-    # Classes
-    #
-    def __getattr__(self, classname):
-        """A convenient way of calling self.getclass(classname)."""
-        return self.classes[classname]
-
-    def addclass(self, cl):
-        cn = cl.classname
-        if self.classes.has_key(cn):
-            raise ValueError, cn
-        self.classes[cn] = cl
-
-    def getclasses(self):
-        """Return a list of the names of all existing classes."""
-        l = self.classes.keys()
-        l.sort()
-        return l
-
-    def getclass(self, classname):
-        """Get the Class object representing a particular class.
-
-        If 'classname' is not a valid class name, a KeyError is raised.
-        """
-        return self.classes[classname]
-
     #
     # Class DBs
     #
@@ -88,70 +51,9 @@ class Database(hyperdb.Database):
         else:
             return bsddb.btopen(path, 'n')
 
-    #
-    # Nodes
-    #
-    def addnode(self, classname, nodeid, node):
-        ''' add the specified node to its class's db
-        '''
-        db = self.getclassdb(classname, 'c')
-        db[nodeid] = marshal.dumps(node)
-        db.close()
-    setnode = addnode
-
-    def getnode(self, classname, nodeid, cldb=None):
-        ''' add the specified node to its class's db
-        '''
-        db = cldb or self.getclassdb(classname)
-        if not db.has_key(nodeid):
-            raise IndexError, nodeid
-        res = marshal.loads(db[nodeid])
-        if not cldb: db.close()
-        return res
-
-    def hasnode(self, classname, nodeid, cldb=None):
-        ''' add the specified node to its class's db
-        '''
-        db = cldb or self.getclassdb(classname)
-        res = db.has_key(nodeid)
-        if not cldb: db.close()
-        return res
-
-    def countnodes(self, classname, cldb=None):
-        db = cldb or self.getclassdb(classname)
-        return len(db.keys())
-        if not cldb: db.close()
-        return res
-
-    def getnodeids(self, classname, cldb=None):
-        db = cldb or self.getclassdb(classname)
-        res = db.keys()
-        if not cldb: db.close()
-        return res
-
     #
     # Journal
     #
-    def addjournal(self, classname, nodeid, action, params):
-        ''' Journal the Action
-        'action' may be:
-
-            'create' or 'set' -- 'params' is a dictionary of property values
-            'link' or 'unlink' -- 'params' is (classname, nodeid, propname)
-            'retire' -- 'params' is None
-        '''
-        entry = (nodeid, date.Date().get_tuple(), self.journaltag, action,
-            params)
-        db = bsddb.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'c')
-        if db.has_key(nodeid):
-            s = db[nodeid]
-            l = marshal.loads(db[nodeid])
-            l.append(entry)
-        else:
-            l = [entry]
-        db[nodeid] = marshal.dumps(l)
-        db.close()
-
     def getjournal(self, classname, nodeid):
         ''' get the journal for id
         '''
@@ -174,32 +76,24 @@ class Database(hyperdb.Database):
         db.close()
         return res
 
-    def close(self):
-        ''' Close the Database - we must release the circular refs so that
-            we can be del'ed and the underlying bsddb connections closed
-            cleanly.
-        '''
-        self.classes = {}
-
-
-    #
-    # Basic transaction support
-    #
-    # TODO: well, write these methods (and then use them in other code)
-    def register_action(self):
-        ''' Register an action to the transaction undo log
-        '''
-
-    def commit(self):
-        ''' Commit the current transaction, start a new one
-        '''
-
-    def rollback(self):
-        ''' Reverse all actions from the current transaction
-        '''
+    def _doSaveJournal(self, classname, nodeid, action, params):
+        entry = (nodeid, date.Date().get_tuple(), self.journaltag, action,
+            params)
+        db = bsddb.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'c')
+        if db.has_key(nodeid):
+            s = db[nodeid]
+            l = marshal.loads(db[nodeid])
+            l.append(entry)
+        else:
+            l = [entry]
+        db[nodeid] = marshal.dumps(l)
+        db.close()
 
 #
 #$Log: not supported by cvs2svn $
+#Revision 1.12  2001/11/21 02:34:18  richard
+#Added a target version field to the extended issue schema
+#
 #Revision 1.11  2001/10/09 23:58:10  richard
 #Moved the data stringification up into the hyperdb.Class class' get, set
 #and create methods. This means that the data is also stringified for the
index b98039f216bd89067bf191336be02d15ce748530..6fe8b288cede65e623c1c9d0baf8472655b55cd2 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: cgi_client.py,v 1.78 2001-12-07 05:59:27 rochecompaan Exp $
+# $Id: cgi_client.py,v 1.79 2001-12-10 22:20:01 richard Exp $
 
 __doc__ = """
 WWW request handler (also used in the stand-alone server).
@@ -341,6 +341,8 @@ class Client:
                 if changed:
                     message = _('%(changes)s edited ok')%{'changes':
                         ', '.join(changed.keys())}
+                elif self.form.has_key('__note') and self.form['__note'].value:
+                    message = _('note added')
                 else:
                     message = _('nothing changed')
             except:
@@ -452,7 +454,7 @@ class Client:
                 props['status'] = unread_id
         return cl.create(**props)
 
-    def _post_editnode(self, nid, change_note=None):
+    def _post_editnode(self, nid, change_note=''):
         ''' do the linking and message sending part of the node creation
         '''
         cn = self.classname
@@ -501,8 +503,7 @@ class Client:
         props = cl.getprops()
         note = None
         if self.form.has_key('__note'):
-            note = self.form['__note']
-            note = note.value
+            note = self.form['__note'].value
         if not props.has_key('messages'):
             return
         if not isinstance(props['messages'], hyperdb.Multilink):
@@ -616,6 +617,7 @@ class Client:
                 # and some nice feedback for the user
                 message = _('%(classname)s created ok')%{'classname': cn}
             except:
+                self.db.rollback()
                 s = StringIO.StringIO()
                 traceback.print_exc(None, s)
                 message = '<pre>%s</pre>'%cgi.escape(s.getvalue())
@@ -1085,6 +1087,9 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.78  2001/12/07 05:59:27  rochecompaan
+# Fixed small bug that prevented adding issues through the web.
+#
 # Revision 1.77  2001/12/06 22:48:29  richard
 # files multilink was being nuked in post_edit_node
 #
index 1d15ab4f6b13bcca5aff159f24bacdf06a5b0c7e..966f77db0cbc04c4df0a63fe9833fb74ab7a68ea 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: roundupdb.py,v 1.27 2001-12-10 21:02:53 richard Exp $
+# $Id: roundupdb.py,v 1.28 2001-12-10 22:20:01 richard Exp $
 
 __doc__ = """
 Extending hyperdb with types specific to issue-tracking.
@@ -439,6 +439,7 @@ class IssueClass(Class):
                 changed[key] = new_value
 
         # list the changes
+        m = []
         for propname, value in changed.items():
             prop = cl.properties[propname]
             oldvalue = cl.get(nodeid, propname, None)
@@ -490,6 +491,9 @@ class IssueClass(Class):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.27  2001/12/10 21:02:53  richard
+# only insert the -------- change note marker if there is a change note
+#
 # Revision 1.26  2001/12/05 14:26:44  rochecompaan
 # Removed generation of change note from "sendmessage" in roundupdb.py.
 # The change note is now generated when the message is created.