diff roundup/backends/back_anydbm.py @ 2089:93f03c6714d8

A few big changes in this commit: 1. The current indexer has been moved to backends/indexer_dbm in anticipation of my writing an indexer_rdbms, 2. Changed indexer invocation during create / set to follow the pattern set by the metakit backend, which was much cleaner, and 3. The "content" property of FileClass is now mutable in all but the metakit backend. Metakit needs to be changed to support the editing of "content". Hey, and I learnt today that the metakit backend implements its own indexer. How about that... :)
author Richard Jones <richard@users.sourceforge.net>
date Fri, 19 Mar 2004 04:47:59 +0000
parents c091cacdc505
children 723098a10677
line wrap: on
line diff
--- a/roundup/backends/back_anydbm.py	Thu Mar 18 22:47:00 2004 +0000
+++ b/roundup/backends/back_anydbm.py	Fri Mar 19 04:47:59 2004 +0000
@@ -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 @@
 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 @@
             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 @@
         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 @@
         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 @@
             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 @@
         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 @@
         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 @@
         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 @@
         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 @@
         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):

Roundup Issue Tracker: http://roundup-tracker.org/