Code

Storing only marshallable data in the db - no nasty pickled class references.
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 23 Jul 2001 07:56:05 +0000 (07:56 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 23 Jul 2001 07:56:05 +0000 (07:56 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@51 57a73879-2fb5-44c3-a270-3262357dd7e2

roundup/backends/back_bsddb.py
roundup/date.py

index 3533b91c4802eb33aa7d70bf7e8043652482b883..7b4f96e47df01d1ad089d19eb3f15cf56432e3af 100644 (file)
@@ -1,6 +1,8 @@
-#$Id: back_bsddb.py,v 1.1 2001-07-23 07:22:13 richard Exp $
+#$Id: back_bsddb.py,v 1.2 2001-07-23 07:56:05 richard Exp $
 
-import bsddb, os, cPickle
+import bsddb, os, marshal
+# handle the older cPickle'd data
+import cPickle
 from roundup import hyperdb, date
 
 #
@@ -68,11 +70,21 @@ class Database(hyperdb.Database):
         path = os.path.join(os.getcwd(), self.dir, 'nodes.%s'%classname)
         return bsddb.btopen(path, mode)
 
+    #
+    # Nodes
+    #
     def addnode(self, classname, nodeid, node):
         ''' add the specified node to its class's db
         '''
         db = self.getclassdb(classname, 'c')
-        db[nodeid] = cPickle.dumps(node, 1)
+        # convert the instance data to builtin types
+        properties = self.classes[classname].properties
+        for key in res.keys():
+            if properties[key].isDateType:
+                res[key] = res[key].get_tuple()
+            elif properties[key].isIntervalType:
+                res[key] = res[key].get_tuple()
+        db[nodeid] = marshal.dumps(node, 1)
         db.close()
     setnode = addnode
 
@@ -82,7 +94,21 @@ class Database(hyperdb.Database):
         db = cldb or self.getclassdb(classname)
         if not db.has_key(nodeid):
             raise IndexError, nodeid
-        res = cPickle.loads(db[nodeid])
+        try:
+            res = marshal.loads(db[nodeid])
+            # convert the marshalled data to instances
+            properties = self.classes[classname].properties
+            for key in res.keys():
+                if properties[key].isDateType:
+                    res[key] = date.Date(res[key])
+                elif properties[key].isIntervalType:
+                    res[key] = date.Interval(res[key])
+        except ValueError, message:
+            if str(message) != 'bad marshal data':
+                raise
+            # handle the older cPickle'd data
+            res = cPickle.loads(db[nodeid])
+
         if not cldb: db.close()
         return res
 
@@ -117,15 +143,16 @@ class Database(hyperdb.Database):
             'link' or 'unlink' -- 'params' is (classname, nodeid, propname)
             'retire' -- 'params' is None
         '''
-        entry = (nodeid, date.Date(), self.journaltag, action, params)
+        entry = (nodeid, date.Date().journal_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 = cPickle.loads(db[nodeid])
+            l = marshal.loads(db[nodeid])
             l.append(entry)
         else:
             l = [entry]
-        db[nodeid] = cPickle.dumps(l)
+        db[nodeid] = marshal.dumps(l)
         db.close()
 
     def getjournal(self, classname, nodeid):
@@ -139,7 +166,12 @@ class Database(hyperdb.Database):
         except bsddb.error, error:
             if error.args[0] != 2: raise
             return []
-        res = cPickle.loads(db[nodeid])
+        journal = marshal.loads(db[nodeid])
+        res = []
+        for entry in journal:
+            (nodeid, date_stamp, self.journaltag, action, params) = entry
+            date_obj = date.Date(set=date_stamp)
+            res.append((nodeid, date_obj, self.journaltag, action, params))
         db.close()
         return res
 
@@ -169,6 +201,10 @@ class Database(hyperdb.Database):
 
 #
 #$Log: not supported by cvs2svn $
+#Revision 1.1  2001/07/23 07:22:13  richard
+#*sigh* some databases have _foo.so as their underlying implementation.
+#This time for sure, Rocky.
+#
 #Revision 1.1  2001/07/23 07:15:57  richard
 #Moved the backends into the backends package. Anydbm hasn't been tested at all.
 #
index e7002aec0bec76fa258f4ef83c2263ee54b46996..d66c17479586b860acc9b04b893edb5b045b01b1 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: date.py,v 1.2 2001-07-22 12:09:32 richard Exp $
+# $Id: date.py,v 1.3 2001-07-23 07:56:05 richard Exp $
 
 import time, re, calendar
 
@@ -56,18 +56,18 @@ class Date:
     '''
     isDate = 1
 
-    def __init__(self, spec='.', offset=0, set=None):
+    def __init__(self, spec='.', offset=0):
         """Construct a date given a specification and a time zone offset.
 
           'spec' is a full date or a partial form, with an optional
-                 added or subtracted interval.
+                 added or subtracted interval. Or a date 9-tuple.
         'offset' is the local time zone offset from GMT in hours.
         """
-        if set is None:
+        if type(spec) == type(''):
             self.set(spec, offset=offset)
         else:
             self.year, self.month, self.day, self.hour, self.minute, \
-                self.second, x, x, x = set
+                self.second, x, x, x = spec
         self.offset = offset
 
     def applyInterval(self, interval):
@@ -90,7 +90,7 @@ class Date:
             self.hour + other.sign * other.hour,
             self.minute + other.sign * other.minute,
             self.second + other.sign * other.second, 0, 0, 0)
-        return Date(set = time.gmtime(calendar.timegm(t)))
+        return Date(time.gmtime(calendar.timegm(t)))
 
     # XXX deviates from spec to allow subtraction of dates as well
     def __sub__(self, other):
@@ -128,7 +128,7 @@ class Date:
              self.hour - other.sign * other.hour,
              self.minute - other.sign * other.minute,
              self.second - other.sign * other.second, 0, 0, 0)
-        return Date(set = time.gmtime(calendar.timegm(t)))
+        return Date(time.gmtime(calendar.timegm(t)))
 
     def __cmp__(self, other):
         """Compare this date to another date."""
@@ -193,6 +193,9 @@ class Date:
         self.year, self.month, self.day, self.hour, self.minute, \
             self.second, x, x, x = time.gmtime(calendar.timegm(t))
 
+    def get_tuple(self):
+        return (self.year, self.month, self.day, self.hour, self.minute,
+            self.second, 0, 0, 0)
 
 class Interval:
     '''
@@ -321,6 +324,10 @@ class Interval:
             return '1/2 an hour'
         return '%s/4 hour'%quart
 
+    def get_tuple(self):
+        return (self.year, self.month, self.day, self.hour, self.minute,
+            self.second)
+
 
 def test():
     intervals = ("  3w  1  d  2:00", " + 2d", "3w")
@@ -344,6 +351,9 @@ if __name__ == '__main__':
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.2  2001/07/22 12:09:32  richard
+# Final commit of Grande Splite
+#
 # Revision 1.1  2001/07/22 11:58:35  richard
 # More Grande Splite
 #