Code

A few big changes in this commit:
[roundup.git] / roundup / backends / back_anydbm.py
index 7091d19bd218995e1bd78a529f6c06b49bb207eb..6fb115d5ae1da2555e7cec64177affc3060259cf 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-#$Id: back_anydbm.py,v 1.138 2004-03-18 01:58:45 richard Exp $
+#$Id: back_anydbm.py,v 1.139 2004-03-19 04:47:59 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
@@ -37,7 +37,7 @@ import whichdb, os, marshal, re, weakref, string, copy
 from roundup import hyperdb, date, password, roundupdb, security
 from blobfiles import FileStorage
 from sessions_dbm import Sessions, OneTimeKeys
-from roundup.indexer import Indexer
+from indexer_dbm import Indexer
 from roundup.backends import locking
 from roundup.hyperdb import String, Password, Date, Interval, Link, \
     Multilink, DatabaseError, Boolean, Number, Node
@@ -882,6 +882,7 @@ class Class(hyperdb.Class):
             elif isinstance(prop, String):
                 if type(value) != type('') and type(value) != type(u''):
                     raise TypeError, 'new property "%s" not a string'%key
+                self.db.indexer.add_text((self.classname, newid, key), value)
 
             elif isinstance(prop, Password):
                 if not isinstance(value, password.Password):
@@ -1143,6 +1144,15 @@ class Class(hyperdb.Class):
         These operations trigger detectors and can be vetoed.  Attempts
         to modify the "creation" or "activity" properties cause a KeyError.
         '''
+        self.fireAuditors('set', nodeid, propvalues)
+        oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid))
+        propvalues = self.set_inner(nodeid, **propvalues)
+        self.fireReactors('set', nodeid, oldvalues)
+        return propvalues        
+
+    def set_inner(self, nodeid, **propvalues):
+        ''' Called by set, in-between the audit and react calls.
+        '''
         if not propvalues:
             return propvalues
 
@@ -1155,11 +1165,6 @@ class Class(hyperdb.Class):
         if self.db.journaltag is None:
             raise DatabaseError, 'Database open read-only'
 
-        self.fireAuditors('set', nodeid, propvalues)
-        # Take a copy of the node dict so that the subsequent set
-        # operation doesn't modify the oldvalues structure.
-        oldvalues = copy.deepcopy(self.db.getnode(self.classname, nodeid))
-
         node = self.db.getnode(self.classname, nodeid)
         if node.has_key(self.db.RETIRED_FLAG):
             raise IndexError
@@ -1290,6 +1295,8 @@ class Class(hyperdb.Class):
             elif isinstance(prop, String):
                 if value is not None and type(value) != type('') and type(value) != type(u''):
                     raise TypeError, 'new property "%s" not a string'%propname
+                self.db.indexer.add_text((self.classname, nodeid, propname),
+                    value)
 
             elif isinstance(prop, Password):
                 if not isinstance(value, password.Password):
@@ -1331,9 +1338,7 @@ class Class(hyperdb.Class):
         if self.do_journal:
             self.db.addjournal(self.classname, nodeid, 'set', journalvalues)
 
-        self.fireReactors('set', nodeid, oldvalues)
-
-        return propvalues        
+        return propvalues
 
     def retire(self, nodeid):
         '''Retire a node.
@@ -1946,20 +1951,18 @@ class Class(hyperdb.Class):
         self.properties.update(properties)
 
     def index(self, nodeid):
-        '''Add (or refresh) the node to search indexes
-        '''
+        ''' Add (or refresh) the node to search indexes '''
         # find all the String properties that have indexme
         for prop, propclass in self.getprops().items():
-            if isinstance(propclass, String) and propclass.indexme:
+            if isinstance(propclass, hyperdb.String) and propclass.indexme:
+                # index them under (classname, nodeid, property)
                 try:
                     value = str(self.get(nodeid, prop))
                 except IndexError:
-                    # node no longer exists - entry should be removed
-                    self.db.indexer.purge_entry((self.classname, nodeid, prop))
-                else:
-                    # and index them under (classname, nodeid, property)
-                    self.db.indexer.add_text((self.classname, nodeid, prop),
-                        value)
+                    # node has been destroyed
+                    continue
+                self.db.indexer.add_text((self.classname, nodeid, prop), value)
+
 
     #
     # Detector interface
@@ -2012,8 +2015,15 @@ class FileClass(Class, hyperdb.FileClass):
         content = propvalues['content']
         del propvalues['content']
 
+        # make sure we have a MIME type
+        mime_type = propvalues.get('type', self.default_mime_type)
+
         # do the database create
-        newid = Class.create_inner(self, **propvalues)
+        newid = self.create_inner(**propvalues)
+
+        # and index!
+        self.db.indexer.add_text((self.classname, newid, 'content'), content,
+            mime_type)
 
         # fire reactors
         self.fireReactors('create', newid, None)
@@ -2059,6 +2069,35 @@ class FileClass(Class, hyperdb.FileClass):
         else:
             return Class.get(self, nodeid, propname)
 
+    def set(self, itemid, **propvalues):
+        ''' Snarf the "content" propvalue and update it in a file
+        '''
+        self.fireAuditors('set', itemid, propvalues)
+        oldvalues = copy.deepcopy(self.db.getnode(self.classname, itemid))
+
+        # now remove the content property so it's not stored in the db
+        content = None
+        if propvalues.has_key('content'):
+            content = propvalues['content']
+            del propvalues['content']
+
+        # do the database create
+        propvalues = self.set_inner(itemid, **propvalues)
+
+        # do content?
+        if content:
+            # store and index
+            self.db.storefile(self.classname, itemid, None, content)
+            mime_type = propvalues.get('type', self.get(itemid, 'type'))
+            if not mime_type:
+                mime_type = self.default_mime_type
+            self.db.indexer.add_text((self.classname, itemid, 'content'),
+                content, mime_type)
+
+        # fire reactors
+        self.fireReactors('set', itemid, oldvalues)
+        return propvalues
+
     def getprops(self, protected=1):
         ''' In addition to the actual properties on the node, these methods
             provide the "content" property. If the "protected" flag is true,
@@ -2069,27 +2108,6 @@ class FileClass(Class, hyperdb.FileClass):
         d['content'] = hyperdb.String()
         return d
 
-    def index(self, nodeid):
-        ''' Index the node in the search index.
-
-            We want to index the content in addition to the normal String
-            property indexing.
-        '''
-        # perform normal indexing
-        Class.index(self, nodeid)
-
-        # get the content to index
-        content = self.get(nodeid, 'content')
-
-        # figure the mime type
-        if self.properties.has_key('type'):
-            mime_type = self.get(nodeid, 'type')
-        else:
-            mime_type = self.default_mime_type
-
-        # and index!
-        self.db.indexer.add_text((self.classname, nodeid, 'content'), content,
-            mime_type)
 
 # deviation from spec - was called ItemClass
 class IssueClass(Class, roundupdb.IssueClass):