From b8975b6ff071ed1b95fc3d2b5edfcfd16cf848cc Mon Sep 17 00:00:00 2001 From: richard Date: Mon, 20 Jan 2003 23:03:41 +0000 Subject: [PATCH] - fixed bug in metakit unlink journalling - metakit now handles "unset" for most types (not Number and Boolean) - fixed bug in metakit search-by-ID Metakit now passes all unit tests! w00t! (except the Number/Boolean unset) git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1469 57a73879-2fb5-44c3-a270-3262357dd7e2 --- roundup/backends/back_metakit.py | 58 +++++++++++++++++++++++++++++--- test/test_db.py | 46 ++++++++++++++++++------- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/roundup/backends/back_metakit.py b/roundup/backends/back_metakit.py index d2bc6fb..4d1fd4c 100755 --- a/roundup/backends/back_metakit.py +++ b/roundup/backends/back_metakit.py @@ -1,3 +1,33 @@ +''' + Metakit backend for Roundup, originally by Gordon McMillan. + + Notes by Richard: + + This backend has some behaviour specific to metakit: + + - there's no concept of an explicit "unset" in metakit, so all types + have some "unset" value: + + ========= ===== ==================================================== + Type Value Action when fetching from mk + ========= ===== ==================================================== + Strings '' convert to None + Date 0 (seconds since 1970-01-01.00:00:00) convert to None + Interval '' convert to None + Number 0 ambiguious :( - do nothing + Boolean 0 ambiguious :( - do nothing + Link '' convert to None + Multilink [] actually, mk can handle this one ;) + Passowrd '' convert to None + ========= ===== ==================================================== + + The get/set routines handle these values accordingly by converting + to/from None where they can. The Number/Boolean types are not able + to handle an "unset" at all, so they default the "unset" to 0. + + - probably a bunch of stuff that I'm not aware of yet because I haven't + fully read through the source. One of these days.... +''' from roundup import hyperdb, date, password, roundupdb, security import metakit from sessions import Sessions @@ -422,7 +452,7 @@ class Class: if self.do_journal and prop.do_journal: # register the unlink with the old linked node if oldvalue: - self.db.addjournal(link_class, value, _UNLINK, + self.db.addjournal(link_class, oldvalue, _UNLINK, (self.classname, str(row.id), key)) # register the link with the newly linked node @@ -869,7 +899,7 @@ class Class: if regexes: def ff(row, r=regexes): for propname, regex in r.items(): - val = getattr(row, propname) + val = str(getattr(row, propname)) if not regex.search(val): return 0 return 1 @@ -1109,25 +1139,45 @@ def _fetchML(sv): return l def _fetchPW(s): + ''' Convert to a password.Password unless the password is '' which is + our sentinel for "unset". + ''' + if s == '': + return None p = password.Password() p.unpack(s) return p def _fetchLink(n): + ''' Return None if the string is empty ?otherwise ensure it's a string? + ''' return n and str(n) or None def _fetchDate(n): + ''' Convert the timestamp to a date.Date instance - unless it's 0 which + is our sentinel for "unset". + ''' + if n == 0: + return None return date.Date(time.gmtime(n)) +def _fetchInterval(n): + ''' Convert to a date.Interval unless the interval is '' which is our + sentinel for "unset". + ''' + if n == '': + return None + return date.Interval(n) + _converters = { hyperdb.Date : _fetchDate, hyperdb.Link : _fetchLink, hyperdb.Multilink : _fetchML, - hyperdb.Interval : date.Interval, + hyperdb.Interval : _fetchInterval, hyperdb.Password : _fetchPW, hyperdb.Boolean : lambda n: n, hyperdb.Number : lambda n: n, - hyperdb.String : str, + hyperdb.String : lambda s: s and str(s) or None, } class FileName(hyperdb.String): diff --git a/test/test_db.py b/test/test_db.py index 7687cdc..7f2a209 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_db.py,v 1.67 2003-01-14 10:52:05 richard Exp $ +# $Id: test_db.py,v 1.68 2003-01-20 23:03:41 richard Exp $ import unittest, os, shutil, time @@ -185,17 +185,23 @@ class anydbmDBTestCase(MyTestCase): self.assertEqual(1, self.db.user.get(userid, 'assignable')) self.db.user.set(userid, assignable=0) self.assertEqual(self.db.user.get(userid, 'assignable'), 0) - self.db.user.set(userid, assignable=None) - self.assertEqual(self.db.user.get('1', "assignable"), None) + + def testBooleanUnset(self): + nid = self.db.user.create(username='foo', assignable=1) + self.db.user.set(nid, assignable=None) + self.assertEqual(self.db.user.get(nid, "assignable"), None) def testNumberChange(self): nid = self.db.user.create(username='foo', age=1) self.assertEqual(1, self.db.user.get(nid, 'age')) - self.db.user.set('1', age=3) - self.assertNotEqual(self.db.user.get('1', 'age'), 1) - self.db.user.set('1', age=1.0) - self.db.user.set('1', age=None) - self.assertEqual(self.db.user.get('1', "age"), None) + self.db.user.set(nid, age=3) + self.assertNotEqual(self.db.user.get(nid, 'age'), 1) + self.db.user.set(nid, age=1.0) + + def testNumberUnset(self): + nid = self.db.user.create(username='foo', age=1) + self.db.user.set(nid, age=None) + self.assertEqual(self.db.user.get(nid, "age"), None) def testKeyValue(self): newid = self.db.user.create(username="spam") @@ -386,15 +392,19 @@ class anydbmDBTestCase(MyTestCase): # invalid multilink index ar(IndexError, self.db.issue.set, id, title='foo', status='1', nosy=['10']) + # NOTE: the following increment the username to avoid problems + # within metakit's backend (it creates the node, and then sets the + # info, so the create (and by a fluke the username set) go through + # before the age/assignable/etc. set, which raises the exception) # invalid number value ar(TypeError, self.db.user.create, username='foo', age='a') # invalid boolean value - ar(TypeError, self.db.user.create, username='foo', assignable='true') - nid = self.db.user.create(username='foo') + ar(TypeError, self.db.user.create, username='foo2', assignable='true') + nid = self.db.user.create(username='foo3') # invalid number value - ar(TypeError, self.db.user.set, nid, username='foo', age='a') + ar(TypeError, self.db.user.set, nid, age='a') # invalid boolean value - ar(TypeError, self.db.user.set, nid, username='foo', assignable='true') + ar(TypeError, self.db.user.set, nid, assignable='true') def testJournals(self): self.db.user.create(username="mary") @@ -808,6 +818,18 @@ class metakitDBTestCase(anydbmDBTestCase): self.assertEqual(num_files2, len(self.db.file.list())) self.assertEqual(num_rfiles2, num_rfiles-1) + def testBooleanUnset(self): + # XXX: metakit can't unset Booleans :( + nid = self.db.user.create(username='foo', assignable=1) + self.db.user.set(nid, assignable=None) + self.assertEqual(self.db.user.get(nid, "assignable"), 0) + + def testNumberUnset(self): + # XXX: metakit can't unset Numbers :( + nid = self.db.user.create(username='foo', age=1) + self.db.user.set(nid, age=None) + self.assertEqual(self.db.user.get(nid, "age"), 0) + class metakitReadOnlyDBTestCase(anydbmReadOnlyDBTestCase): def setUp(self): from roundup.backends import metakit -- 2.30.2