summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 4dfd83a)
raw | patch | inline | side by side (parent: 4dfd83a)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Fri, 19 Jul 2002 03:36:34 +0000 (03:36 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Fri, 19 Jul 2002 03:36:34 +0000 (03:36 +0000) |
others). At the same time, I removed the leading underscores from the hyperdb
methods that Really Didn't Need Them.
The journal also raises IndexError now for all situations where there is a
request for the journal of a node that doesn't have one. It used to return
[] in _some_ situations, but not all. This _may_ break code, but the tests
pass...
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@903 57a73879-2fb5-44c3-a270-3262357dd7e2
methods that Really Didn't Need Them.
The journal also raises IndexError now for all situations where there is a
request for the journal of a node that doesn't have one. It used to return
[] in _some_ situations, but not all. This _may_ break code, but the tests
pass...
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@903 57a73879-2fb5-44c3-a270-3262357dd7e2
index dbdd21bc93fb1bc05863a8bfa727ebfca67142ff..933738dbc6d6a436c398502f4d574fb6fefc4a9c 100644 (file)
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-#$Id: back_anydbm.py,v 1.51 2002-07-18 23:07:08 richard Exp $
+#$Id: back_anydbm.py,v 1.52 2002-07-19 03:36:34 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
self.cache = {} # cache of nodes loaded or created
self.dirtynodes = {} # keep track of the dirty nodes by class
self.newnodes = {} # keep track of the new nodes by class
+ self.destroyednodes = {}# keep track of the destroyed nodes by class
self.transactions = []
self.indexer = Indexer(self.dir)
# ensure files are group readable and writable
'''
if __debug__:
print >>hyperdb.DEBUG, 'getclassdb', (self, classname, mode)
- return self._opendb('nodes.%s'%classname, mode)
+ return self.opendb('nodes.%s'%classname, mode)
def determine_db_type(self, path):
''' determine which DB wrote the class file
db_type = 'dbm'
return db_type
- def _opendb(self, name, mode):
+ def opendb(self, name, mode):
'''Low-level database opener that gets around anydbm/dbm
eccentricities.
'''
if __debug__:
- print >>hyperdb.DEBUG, '_opendb', (self, name, mode)
+ print >>hyperdb.DEBUG, 'opendb', (self, name, mode)
# figure the class db type
path = os.path.join(os.getcwd(), self.dir, name)
# new database? let anydbm pick the best dbm
if not db_type:
if __debug__:
- print >>hyperdb.DEBUG, "_opendb anydbm.open(%r, 'n')"%path
+ print >>hyperdb.DEBUG, "opendb anydbm.open(%r, 'n')"%path
return anydbm.open(path, 'n')
# open the database with the correct module
"Couldn't open database - the required module '%s'"\
" is not available"%db_type
if __debug__:
- print >>hyperdb.DEBUG, "_opendb %r.open(%r, %r)"%(db_type, path,
+ print >>hyperdb.DEBUG, "opendb %r.open(%r, %r)"%(db_type, path,
mode)
return dbm.open(path, mode)
- def _lockdb(self, name):
+ def lockdb(self, name):
''' Lock a database file
'''
path = os.path.join(os.getcwd(), self.dir, '%s.lock'%name)
''' Generate a new id for the given class
'''
# open the ids DB - create if if doesn't exist
- lock = self._lockdb('_ids')
- db = self._opendb('_ids', 'c')
+ lock = self.lockdb('_ids')
+ db = self.opendb('_ids', 'c')
if db.has_key(classname):
newid = db[classname] = str(int(db[classname]) + 1)
else:
'''
if __debug__:
print >>hyperdb.DEBUG, 'savenode', (self, classname, nodeid, node)
- self.transactions.append((self._doSaveNode, (classname, nodeid, node)))
+ self.transactions.append((self.doSaveNode, (classname, nodeid, node)))
def getnode(self, classname, nodeid, db=None, cache=1):
''' get a node from the database
if not db.has_key(nodeid):
raise IndexError, "no such %s %s"%(classname, nodeid)
+ # check the uncommitted, destroyed nodes
+ if (self.destroyednodes.has_key(classname) and
+ self.destroyednodes[classname].has_key(nodeid)):
+ raise IndexError, "no such %s %s"%(classname, nodeid)
+
# decode
res = marshal.loads(db[nodeid])
return res
+ def destroynode(self, classname, nodeid):
+ '''Remove a node from the database. Called exclusively by the
+ destroy() method on Class.
+ '''
+ if __debug__:
+ print >>hyperdb.DEBUG, 'destroynode', (self, classname, nodeid)
+
+ # remove from cache and newnodes if it's there
+ if (self.cache.has_key(classname) and
+ self.cache[classname].has_key(nodeid)):
+ del self.cache[classname][nodeid]
+ if (self.newnodes.has_key(classname) and
+ self.newnodes[classname].has_key(nodeid)):
+ del self.newnodes[classname][nodeid]
+
+ # see if there's any obvious commit actions that we should get rid of
+ for entry in self.transactions[:]:
+ if entry[1][:2] == (classname, nodeid):
+ self.transactions.remove(entry)
+
+ # add to the destroyednodes map
+ self.destroyednodes.setdefault(classname, {})[nodeid] = 1
+
+ # add the destroy commit action
+ self.transactions.append((self.doDestroyNode, (classname, nodeid)))
+
def serialise(self, classname, node):
'''Copy the node contents, converting non-marshallable data into
marshallable data.
def countnodes(self, classname, db=None):
if __debug__:
print >>hyperdb.DEBUG, 'countnodes', (self, classname, db)
- # include the new nodes not saved to the DB yet
- count = len(self.newnodes.get(classname, {}))
+
+ count = 0
+
+ # include the uncommitted nodes
+ if self.newnodes.has_key(classname):
+ count += len(self.newnodes[classname])
+ if self.destroyednodes.has_key(classname):
+ count -= len(self.destroyednodes[classname])
# and count those in the DB
if db is None:
def getnodeids(self, classname, db=None):
if __debug__:
print >>hyperdb.DEBUG, 'getnodeids', (self, classname, db)
+
+ res = []
+
# start off with the new nodes
- res = self.newnodes.get(classname, {}).keys()
+ if self.newnodes.has_key(classname):
+ res += self.newnodes[classname].keys()
if db is None:
db = self.getclassdb(classname)
res = res + db.keys()
+
+ # remove the uncommitted, destroyed nodes
+ if self.destroyednodes.has_key(classname):
+ for nodeid in self.destroyednodes[classname].keys():
+ if db.has_key(nodeid):
+ res.remove(nodeid)
+
return res
if __debug__:
print >>hyperdb.DEBUG, 'addjournal', (self, classname, nodeid,
action, params)
- self.transactions.append((self._doSaveJournal, (classname, nodeid,
+ self.transactions.append((self.doSaveJournal, (classname, nodeid,
action, params)))
def getjournal(self, classname, nodeid):
''' get the journal for id
+
+ Raise IndexError if the node doesn't exist (as per history()'s
+ API)
'''
if __debug__:
print >>hyperdb.DEBUG, 'getjournal', (self, classname, nodeid)
# attempt to open the journal - in some rare cases, the journal may
# not exist
try:
- db = self._opendb('journals.%s'%classname, 'r')
+ db = self.opendb('journals.%s'%classname, 'r')
except anydbm.error, error:
- if str(error) == "need 'c' or 'n' flag to open new db": return []
- elif error.args[0] != 2: raise
- return []
+ if str(error) == "need 'c' or 'n' flag to open new db":
+ raise IndexError, 'no such %s %s'%(classname, nodeid)
+ elif error.args[0] != 2:
+ raise
+ raise IndexError, 'no such %s %s'%(classname, nodeid)
try:
journal = marshal.loads(db[nodeid])
except KeyError:
db.close()
- raise KeyError, 'no such %s %s'%(classname, nodeid)
+ raise IndexError, 'no such %s %s'%(classname, nodeid)
db.close()
res = []
- for entry in journal:
- (nodeid, date_stamp, user, action, params) = entry
- date_obj = date.Date(date_stamp)
- res.append((nodeid, date_obj, user, action, params))
+ for nodeid, date_stamp, user, action, params in journal:
+ res.append((nodeid, date.Date(date_stamp), user, action, params))
return res
def pack(self, pack_before):
db_name = 'journals.%s'%classname
path = os.path.join(os.getcwd(), self.dir, classname)
db_type = self.determine_db_type(path)
- db = self._opendb(db_name, 'w')
+ db = self.opendb(db_name, 'w')
for key in db.keys():
journal = marshal.loads(db[key])
self.cache = {}
self.dirtynodes = {}
self.newnodes = {}
+ self.destroyednodes = {}
self.transactions = []
- def _doSaveNode(self, classname, nodeid, node):
+ def getCachedClassDB(self, classname):
+ ''' get the class db, looking in our cache of databases for commit
+ '''
+ # get the database handle
+ db_name = 'nodes.%s'%classname
+ if not self.databases.has_key(db_name):
+ self.databases[db_name] = self.getclassdb(classname, 'c')
+ return self.databases[db_name]
+
+ def doSaveNode(self, classname, nodeid, node):
if __debug__:
- print >>hyperdb.DEBUG, '_doSaveNode', (self, classname, nodeid,
+ print >>hyperdb.DEBUG, 'doSaveNode', (self, classname, nodeid,
node)
- # get the database handle
- db_name = 'nodes.%s'%classname
- if self.databases.has_key(db_name):
- db = self.databases[db_name]
- else:
- db = self.databases[db_name] = self.getclassdb(classname, 'c')
+ db = self.getCachedClassDB(classname)
# now save the marshalled data
db[nodeid] = marshal.dumps(self.serialise(classname, node))
# return the classname, nodeid so we reindex this content
return (classname, nodeid)
- def _doSaveJournal(self, classname, nodeid, action, params):
+ def getCachedJournalDB(self, classname):
+ ''' get the journal db, looking in our cache of databases for commit
+ '''
+ # get the database handle
+ db_name = 'journals.%s'%classname
+ if not self.databases.has_key(db_name):
+ self.databases[db_name] = self.opendb(db_name, 'c')
+ return self.databases[db_name]
+
+ def doSaveJournal(self, classname, nodeid, action, params):
# serialise first
if action in ('set', 'create'):
params = self.serialise(classname, params)
params)
if __debug__:
- print >>hyperdb.DEBUG, '_doSaveJournal', entry
+ print >>hyperdb.DEBUG, 'doSaveJournal', entry
- # get the database handle
- db_name = 'journals.%s'%classname
- if self.databases.has_key(db_name):
- db = self.databases[db_name]
- else:
- db = self.databases[db_name] = self._opendb(db_name, 'c')
+ db = self.getCachedJournalDB(classname)
# now insert the journal entry
if db.has_key(nodeid):
db[nodeid] = marshal.dumps(l)
+ def doDestroyNode(self, classname, nodeid):
+ if __debug__:
+ print >>hyperdb.DEBUG, 'doDestroyNode', (self, classname, nodeid)
+
+ # delete from the class database
+ db = self.getCachedClassDB(classname)
+ if db.has_key(nodeid):
+ del db[nodeid]
+
+ # delete from the database
+ db = self.getCachedJournalDB(classname)
+ if db.has_key(nodeid):
+ del db[nodeid]
+
+ # return the classname, nodeid so we reindex this content
+ return (classname, nodeid)
+
def rollback(self):
''' Reverse all actions from the current transaction.
'''
print >>hyperdb.DEBUG, 'rollback', (self, )
for method, args in self.transactions:
# delete temporary files
- if method == self._doStoreFile:
- self._rollbackStoreFile(*args)
+ if method == self.doStoreFile:
+ self.rollbackStoreFile(*args)
self.cache = {}
self.dirtynodes = {}
self.newnodes = {}
+ self.destroyednodes = {}
self.transactions = []
_marker = []
self.fireReactors('retire', nodeid, None)
+ def destroy(self, nodeid):
+ """Destroy a node.
+
+ WARNING: this method should never be used except in extremely rare
+ situations where there could never be links to the node being
+ deleted
+ WARNING: use retire() instead
+ WARNING: the properties of this node will not be available ever again
+ WARNING: really, use retire() instead
+
+ Well, I think that's enough warnings. This method exists mostly to
+ support the session storage of the cgi interface.
+ """
+ if self.db.journaltag is None:
+ raise DatabaseError, 'Database open read-only'
+ self.db.destroynode(self.classname, nodeid)
+
def history(self, nodeid):
"""Retrieve the journal of edits on a particular node.
# find all the String properties that have indexme
for prop, propclass in self.getprops().items():
if isinstance(propclass, String) and propclass.indexme:
- # and index them under (classname, nodeid, property)
- self.db.indexer.add_text((self.classname, nodeid, prop),
- str(self.get(nodeid, prop)))
+ 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)
#
# Detector interface
#
#$Log: not supported by cvs2svn $
+#Revision 1.51 2002/07/18 23:07:08 richard
+#Unit tests and a few fixes.
+#
#Revision 1.50 2002/07/18 11:50:58 richard
#added tests for number type too
#
index 530a691a80a6d135933c3c4bca0f276d97ebbe2f..6e14a6e5ee24882b50ddcc7effee56f6e0354ad9 100644 (file)
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-#$Id: back_bsddb.py,v 1.19 2002-07-14 02:05:53 richard Exp $
+#$Id: back_bsddb.py,v 1.20 2002-07-19 03:36:34 richard Exp $
'''
This module defines a backend that saves the hyperdatabase in BSDDB.
'''
else:
return bsddb.btopen(path, 'n')
- def _opendb(self, name, mode):
+ def opendb(self, name, mode):
'''Low-level database opener that gets around anydbm/dbm
eccentricities.
'''
if __debug__:
- print >>hyperdb.DEBUG, self, '_opendb', (self, name, mode)
+ print >>hyperdb.DEBUG, self, 'opendb', (self, name, mode)
# determine which DB wrote the class file
path = os.path.join(os.getcwd(), self.dir, name)
if not os.path.exists(path):
if __debug__:
- print >>hyperdb.DEBUG, "_opendb bsddb.open(%r, 'n')"%path
+ print >>hyperdb.DEBUG, "opendb bsddb.open(%r, 'n')"%path
return bsddb.btopen(path, 'n')
# open the database with the correct module
if __debug__:
- print >>hyperdb.DEBUG, "_opendb bsddb.open(%r, %r)"%(path, mode)
+ print >>hyperdb.DEBUG, "opendb bsddb.open(%r, %r)"%(path, mode)
return bsddb.btopen(path, mode)
#
'r')
except bsddb.error, error:
if error.args[0] != 2: raise
- return []
- # mor handling of bad journals
- if not db.has_key(nodeid): return []
+ raise IndexError, 'no such %s %s'%(classname, nodeid)
+ # more handling of bad journals
+ if not db.has_key(nodeid):
+ raise IndexError, 'no such %s %s'%(classname, nodeid)
journal = marshal.loads(db[nodeid])
res = []
for entry in journal:
db.close()
return res
- def _doSaveJournal(self, classname, nodeid, action, params):
+ def getCachedJournalDB(self, classname):
+ ''' get the journal db, looking in our cache of databases for commit
+ '''
+ # get the database handle
+ db_name = 'journals.%s'%classname
+ if self.databases.has_key(db_name):
+ return self.databases[db_name]
+ else:
+ db = bsddb.btopen(os.path.join(self.dir, db_name), 'c')
+ self.databases[db_name] = db
+ return db
+
+ def doSaveJournal(self, classname, nodeid, action, params):
# serialise first
if action in ('set', 'create'):
params = self.serialise(classname, params)
params)
if __debug__:
- print >>hyperdb.DEBUG, '_doSaveJournal', entry
+ print >>hyperdb.DEBUG, 'doSaveJournal', entry
- db = bsddb.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'c')
+ db = self.getCachedJournalDB(classname)
if db.has_key(nodeid):
s = db[nodeid]
l = [entry]
db[nodeid] = marshal.dumps(l)
- db.close()
#
#$Log: not supported by cvs2svn $
+#Revision 1.19 2002/07/14 02:05:53 richard
+#. all storage-specific code (ie. backend) is now implemented by the backends
+#
#Revision 1.18 2002/05/15 06:21:21 richard
# . node caching now works, and gives a small boost in performance
#
index bce357a1e0e22cfb31a0a96cc32eeb98d07ed131..cb1034d2837f024925815070e9800e497b1e4934 100644 (file)
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-#$Id: back_bsddb3.py,v 1.14 2002-07-14 02:05:54 richard Exp $
+#$Id: back_bsddb3.py,v 1.15 2002-07-19 03:36:34 richard Exp $
import bsddb3, os, marshal
from roundup import hyperdb, date
else:
return bsddb3.btopen(path, 'c')
- def _opendb(self, name, mode):
+ def opendb(self, name, mode):
'''Low-level database opener that gets around anydbm/dbm
eccentricities.
'''
if __debug__:
- print >>hyperdb.DEBUG, self, '_opendb', (self, name, mode)
+ print >>hyperdb.DEBUG, self, 'opendb', (self, name, mode)
# determine which DB wrote the class file
path = os.path.join(os.getcwd(), self.dir, name)
if not os.path.exists(path):
if __debug__:
- print >>hyperdb.DEBUG, "_opendb bsddb3.open(%r, 'c')"%path
+ print >>hyperdb.DEBUG, "opendb bsddb3.open(%r, 'c')"%path
return bsddb3.btopen(path, 'c')
# open the database with the correct module
if __debug__:
- print >>hyperdb.DEBUG, "_opendb bsddb3.open(%r, %r)"%(path, mode)
+ print >>hyperdb.DEBUG, "opendb bsddb3.open(%r, %r)"%(path, mode)
return bsddb3.btopen(path, mode)
#
try:
db = bsddb3.btopen(os.path.join(self.dir, 'journals.%s'%classname),
'r')
- except bsddb3.NoSuchFileError:
- return []
- # mor handling of bad journals
- if not db.has_key(nodeid): return []
+ except bsddb3._db.DBNoSuchFileError:
+ raise IndexError, 'no such %s %s'%(classname, nodeid)
+ # more handling of bad journals
+ if not db.has_key(nodeid):
+ raise IndexError, 'no such %s %s'%(classname, nodeid)
journal = marshal.loads(db[nodeid])
res = []
for entry in journal:
db.close()
return res
- def _doSaveJournal(self, classname, nodeid, action, params):
+ def getCachedJournalDB(self, classname):
+ ''' get the journal db, looking in our cache of databases for commit
+ '''
+ # get the database handle
+ db_name = 'journals.%s'%classname
+ if self.databases.has_key(db_name):
+ return self.databases[db_name]
+ else:
+ db = bsddb3.btopen(os.path.join(self.dir, db_name), 'c')
+ self.databases[db_name] = db
+ return db
+
+ def doSaveJournal(self, classname, nodeid, action, params):
# serialise first
if action in ('set', 'create'):
params = self.serialise(classname, params)
params)
if __debug__:
- print >>hyperdb.DEBUG, '_doSaveJournal', entry
+ print >>hyperdb.DEBUG, 'doSaveJournal', entry
- db = bsddb3.btopen(os.path.join(self.dir, 'journals.%s'%classname), 'c')
+ db = self.getCachedJournalDB(classname)
if db.has_key(nodeid):
s = db[nodeid]
l = [entry]
db[nodeid] = marshal.dumps(l)
- db.close()
#
#$Log: not supported by cvs2svn $
+#Revision 1.14 2002/07/14 02:05:54 richard
+#. all storage-specific code (ie. backend) is now implemented by the backends
+#
#Revision 1.13 2002/07/08 06:41:03 richard
#Was reopening the database with 'n'.
#
index e74f05c854da1d1fb25ddfe50a4b8049c2d78a3a..e099a97cfe4da8ebc0b1911beec6c0036e3e99ce 100644 (file)
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-#$Id: blobfiles.py,v 1.7 2002-07-14 06:14:40 richard Exp $
+#$Id: blobfiles.py,v 1.8 2002-07-19 03:36:34 richard Exp $
'''
This module exports file storage for roundup backends.
Files are stored into a directory hierarchy.
open(name + '.tmp', 'wb').write(content)
# save off the commit action
- self.transactions.append((self._doStoreFile, (classname, nodeid,
+ self.transactions.append((self.doStoreFile, (classname, nodeid,
property)))
def getfile(self, classname, nodeid, property):
files_dir = os.path.join(self.dir, 'files')
return files_in_dir(files_dir)
- def _doStoreFile(self, classname, nodeid, property, **databases):
+ def doStoreFile(self, classname, nodeid, property, **databases):
'''Store the file as part of a transaction commit.
'''
# determine the name of the file to write to
# return the classname, nodeid so we reindex this content
return (classname, nodeid)
- def _rollbackStoreFile(self, classname, nodeid, property, **databases):
+ def rollbackStoreFile(self, classname, nodeid, property, **databases):
'''Remove the temp file as a part of a rollback
'''
# determine the name of the file to delete
os.remove(name+".tmp")
# $Log: not supported by cvs2svn $
+# Revision 1.7 2002/07/14 06:14:40 richard
+# Some more TODOs
+#
# Revision 1.6 2002/07/09 03:02:52 richard
# More indexer work:
# - all String properties may now be indexed too. Currently there's a bit of
diff --git a/roundup/indexer.py b/roundup/indexer.py
index 35e5a2990ba0f6da40b5171fcb977d4bc3f9ecfa..74bfcafb9e3176ed17e632e75866354b82d18049 100644 (file)
--- a/roundup/indexer.py
+++ b/roundup/indexer.py
# that promote freedom, but obviously am giving up any rights
# to compel such.
#
-#$Id: indexer.py,v 1.11 2002-07-18 11:17:30 gmcm Exp $
+#$Id: indexer.py,v 1.12 2002-07-19 03:36:33 richard Exp $
'''
This module provides an indexer class, RoundupIndexer, that stores text
indices in a roundup instance. This class makes searching the content of
def purge_entry(self, identifier):
''' Remove a file from file index and word index
'''
+ self.load_index()
+
if not self.files.has_key(identifier):
return
#
#$Log: not supported by cvs2svn $
+#Revision 1.11 2002/07/18 11:17:30 gmcm
+#Add Number and Boolean types to hyperdb.
+#Add conversion cases to web, mail & admin interfaces.
+#Add storage/serialization cases to back_anydbm & back_metakit.
+#
#Revision 1.10 2002/07/14 23:17:24 richard
#oops
#
diff --git a/test/test_db.py b/test/test_db.py
index fc97d18462a51f0b8901d1bd30dfc1fb63842e9d..47a1bbadb93bda06f8901be6b0d432ee5d050e34 100644 (file)
--- a/test/test_db.py
+++ b/test/test_db.py
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#
-# $Id: test_db.py,v 1.35 2002-07-18 23:07:08 richard Exp $
+# $Id: test_db.py,v 1.36 2002-07-19 03:36:34 richard Exp $
import unittest, os, shutil, time
issue = module.IssueClass(db, "issue", title=String(indexme="yes"),
status=Link("status"), nosy=Multilink("user"), deadline=Date(),
foo=Interval(), files=Multilink("file"))
+ session = module.Class(db, 'session', title=String())
+ session.disableJournalling()
db.post_init()
if create:
status.create(name="unread")
self.assertNotEqual(num_files, self.db.numfiles())
self.assertEqual(num_files2, self.db.numfiles())
+ def testDestroyNoJournalling(self):
+ ' test destroy on a class with no journalling '
+ self.innerTestDestroy(klass=self.db.session)
+
+ def testDestroyJournalling(self):
+ ' test destroy on a class with journalling '
+ self.innerTestDestroy(klass=self.db.issue)
+
+ def innerTestDestroy(self, klass):
+ newid = klass.create(title='Mr Friendly')
+ n = len(klass.list())
+ self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
+ klass.destroy(newid)
+ self.assertRaises(IndexError, klass.get, newid, 'title')
+ self.assertNotEqual(len(klass.list()), n)
+ if klass.do_journal:
+ self.assertRaises(IndexError, klass.history, newid)
+
+ # now with a commit
+ newid = klass.create(title='Mr Friendly')
+ n = len(klass.list())
+ self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
+ self.db.commit()
+ klass.destroy(newid)
+ self.assertRaises(IndexError, klass.get, newid, 'title')
+ self.db.commit()
+ self.assertRaises(IndexError, klass.get, newid, 'title')
+ self.assertNotEqual(len(klass.list()), n)
+ if klass.do_journal:
+ self.assertRaises(IndexError, klass.history, newid)
+
+ # now with a rollback
+ newid = klass.create(title='Mr Friendly')
+ n = len(klass.list())
+ self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
+ self.db.commit()
+ klass.destroy(newid)
+ self.assertNotEqual(len(klass.list()), n)
+ self.assertRaises(IndexError, klass.get, newid, 'title')
+ self.db.rollback()
+ self.assertEqual(klass.get(newid, 'title'), 'Mr Friendly')
+ self.assertEqual(len(klass.list()), n)
+ if klass.do_journal:
+ self.assertNotEqual(klass.history(newid), [])
+
def testExceptions(self):
# this tests the exceptions that should be raised
ar = self.assertRaises
#
# $Log: not supported by cvs2svn $
+# Revision 1.35 2002/07/18 23:07:08 richard
+# Unit tests and a few fixes.
+#
# Revision 1.34 2002/07/18 11:52:00 richard
# oops
#