summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: b8975b6)
raw | patch | inline | side by side (parent: b8975b6)
author | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Mon, 20 Jan 2003 23:05:20 +0000 (23:05 +0000) | ||
committer | richard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2> | |
Mon, 20 Jan 2003 23:05:20 +0000 (23:05 +0000) |
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1470 57a73879-2fb5-44c3-a270-3262357dd7e2
CHANGES.txt | patch | blob | history | |
roundup/cgi/client.py | patch | blob | history | |
test/test_cgi.py | patch | blob | history |
diff --git a/CHANGES.txt b/CHANGES.txt
index 8c3cfed959c67d8a79e67eddab122b43775493fe..e9e5c5e5d7493b113171588f111388b7e79fd121 100644 (file)
--- a/CHANGES.txt
+++ b/CHANGES.txt
- added mysql backend
- fixes to CGI form handling
- switch metakit to use "compressed" multilink journal change representation
+- fixed bug in metakit unlink journalling
+- metakit now handles "unset" for most types (not Number and Boolean)
+- fixed bug in metakit search-by-ID
- applied unicode patch. All data is stored in utf-8. Incoming messages
converted from any encoding to utf-8, outgoing messages are encoded
according to rfc2822 (sf bug 568873)
diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py
index 83af24489351852ffe93d3b32c4ba4d9826dcca2..ce7327f01ad95ca9124780bd488d5abb5e9be499 100644 (file)
--- a/roundup/cgi/client.py
+++ b/roundup/cgi/client.py
-# $Id: client.py,v 1.71 2003-01-15 22:39:07 richard Exp $
+# $Id: client.py,v 1.72 2003-01-20 23:05:19 richard Exp $
__doc__ = """
WWW request handler (also used in the stand-alone server).
# surrounding whitespace
value = value.value.strip()
- if isinstance(proptype, hyperdb.String):
- # fix the CRLF/CR -> LF stuff
- value = fixNewlines(value)
- elif isinstance(proptype, hyperdb.Password):
+ # handle by type now
+ if isinstance(proptype, hyperdb.Password):
if not value:
# ignore empty password values
continue
if value != confirm.value:
raise ValueError, 'Password and confirmation text do not match'
value = password.Password(value)
- elif isinstance(proptype, hyperdb.Date):
- if value:
- value = date.Date(value)
- else:
- value = None
- elif isinstance(proptype, hyperdb.Interval):
- if value:
- value = date.Interval(value)
- else:
- value = None
+
elif isinstance(proptype, hyperdb.Link):
# see if it's the "no selection" choice
if value == '-1' or not value:
value = existing
value.sort()
- elif isinstance(proptype, hyperdb.Boolean):
- value = value.lower() in ('yes', 'true', 'on', '1')
- elif isinstance(proptype, hyperdb.Number):
- value = int(value)
-
- # register this as received if required?
- if propname in required and value is not None:
- required.remove(propname)
+ # other types should be None'd if there's no value
+ elif value:
+ if isinstance(proptype, hyperdb.String):
+ # fix the CRLF/CR -> LF stuff
+ value = fixNewlines(value)
+ elif isinstance(proptype, hyperdb.Date):
+ value = date.Date(value)
+ elif isinstance(proptype, hyperdb.Interval):
+ value = date.Interval(value)
+ elif isinstance(proptype, hyperdb.Boolean):
+ value = value.lower() in ('yes', 'true', 'on', '1')
+ elif isinstance(proptype, hyperdb.Number):
+ value = int(value)
+ else:
+ # if we're creating, just don't include this property
+ if not nodeid:
+ continue
+ value = None
# get the old value
if nodeid:
if not properties.has_key(propname):
raise
- # existing may be None, which won't equate to empty strings
- if not existing and not value:
- continue
-
- # existing will come out unsorted in some cases
+ # make sure the existing multilink is sorted
if isinstance(proptype, hyperdb.Multilink):
existing.sort()
+ # "missing" existing values may not be None
+ if not existing:
+ if isinstance(proptype, hyperdb.String) and not existing:
+ # some backends store "missing" Strings as empty strings
+ existing = None
+ elif isinstance(proptype, hyperdb.Number) and not existing:
+ # some backends store "missing" Numbers as 0 :(
+ existing = 0
+ elif isinstance(proptype, hyperdb.Boolean) and not existing:
+ # likewise Booleans
+ existing = 0
+
# if changed, set it
if value != existing:
props[propname] = value
else:
# don't bother setting empty/unset values
- if not value:
+ if value is None:
+ continue
+ elif isinstance(proptype, hyperdb.Multilink) and value == []:
continue
+ elif isinstance(proptype, hyperdb.String) and value == '':
+ continue
+
props[propname] = value
+ # register this as received if required?
+ if propname in required and value is not None:
+ required.remove(propname)
+
# see if all the required properties have been supplied
if required:
if len(required) > 1:
return props
-
diff --git a/test/test_cgi.py b/test/test_cgi.py
index 63ca4b39ab1fdb038d077cee40588551ebfa032f..cfa4192c9d4b32ba56b27d57468aad50469d3caa 100644 (file)
--- a/test/test_cgi.py
+++ b/test/test_cgi.py
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
-# $Id: test_cgi.py,v 1.5 2003-01-15 22:39:07 richard Exp $
+# $Id: test_cgi.py,v 1.6 2003-01-20 23:05:20 richard Exp $
import unittest, os, shutil, errno, sys, difflib, cgi
from roundup.cgi import client
-from roundup import init, instance, password
+from roundup import init, instance, password, hyperdb, date
def makeForm(args):
form = cgi.FieldStorage()
self.db.user.create(username='mary', address='mary@test',
roles='User', realname='Contrary, Mary')
+ test = self.instance.dbinit.Class(self.db, "test",
+ boolean=hyperdb.Boolean(), link=hyperdb.Link('test'),
+ multilink=hyperdb.Multilink('test'), date=hyperdb.Date(),
+ interval=hyperdb.Interval())
+
def tearDown(self):
self.db.close()
try:
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
self.db.issue, makeForm({':required': ['title','status'],
'status':'1'}))
+ self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
+ self.db.issue, makeForm({':required': 'status',
+ 'status':''}))
+ self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
+ self.db.issue, makeForm({':required': 'nosy',
+ 'nosy':''}))
+
+ #
+ # Nonexistant edit
+ #
+ def testEditNonexistant(self):
+ self.assertRaises(IndexError, client.parsePropsFromForm, self.db,
+ self.db.test, makeForm({'boolean': ''}), '1')
#
# String
makeForm({'title': 'foo'})), {'title': 'foo'})
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
makeForm({'title': 'a\r\nb\r\n'})), {'title': 'a\nb'})
+ nodeid = self.db.issue.create(title='foo')
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
+ makeForm({'title': 'foo'}), nodeid), {})
def testEmptyStringSet(self):
nodeid = self.db.issue.create(title='foo')
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
- makeForm({'title': ''}), nodeid), {'title': ''})
+ makeForm({'title': ''}), nodeid), {'title': None})
nodeid = self.db.issue.create(title='foo')
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
- makeForm({'title': ' '}), nodeid), {'title': ''})
+ makeForm({'title': ' '}), nodeid), {'title': None})
#
# Link
makeForm({'status': 'unread'})), {'status': '1'})
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
makeForm({'status': '1'})), {'status': '1'})
+ nodeid = self.db.issue.create(status='unread')
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
+ makeForm({'status': 'unread'}), nodeid), {})
def testUnsetLink(self):
nodeid = self.db.issue.create(status='unread')
# self.db.issue, makeForm({'status': '4'}))
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
self.db.issue, makeForm({'status': 'frozzle'}))
-# XXX need a test for the TypeError where the link class doesn't define a key?
+
+ self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
+ self.db.test, makeForm({'link': 'frozzle'}))
#
# Multilink
nodeid = self.db.issue.create(nosy=['1','2'])
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
makeForm({'nosy': ' '}), nodeid), {'nosy': []})
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
+ makeForm({'nosy': '1,2'}), nodeid), {})
def testInvalidMultilinkValue(self):
# XXX This is not the current behaviour - should we enforce this?
self.db.issue, makeForm({'nosy': 'frozzle'}))
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
self.db.issue, makeForm({'nosy': '1,frozzle'}))
-# XXX need a test for the TypeError (where the ML class doesn't define a key?
+
+ self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
+ self.db.test, makeForm({'multilink': 'frozzle'}))
def testMultilinkAdd(self):
nodeid = self.db.issue.create(nosy=['1'])
self.db.user, makeForm({'password': 'foo',
'password:confirm': 'bar'}))
- def testEmptyPasswordNOTSet(self):
- nodeid = self.db.user.create(username='1', password=password.Password('foo'))
+ def testEmptyPasswordNotSet(self):
+ nodeid = self.db.user.create(username='1',
+ password=password.Password('foo'))
self.assertEqual(client.parsePropsFromForm(self.db, self.db.user,
makeForm({'password': ''}), nodeid), {})
- nodeid = self.db.user.create(username='2', password=password.Password('foo'))
+ nodeid = self.db.user.create(username='2',
+ password=password.Password('foo'))
self.assertEqual(client.parsePropsFromForm(self.db, self.db.user,
makeForm({'password': '', 'password:confirm': ''}), nodeid), {})
#
# Boolean
#
-# XXX this needs a property to work on.
-# def testEmptyBoolean(self):
-# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
-# makeForm({'title': ''})), {})
-# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
-# makeForm({'title': ' '})), {})
-# self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
-# self.db.issue, makeForm({'title': ['', '']}))
-
-# def testSetBoolean(self):
-# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
-# makeForm({'title': 'foo'})), {'title': 'foo'})
-# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
-# makeForm({'title': 'a\r\nb\r\n'})), {'title': 'a\nb'})
-
-# def testEmptyBooleanSet(self):
-# nodeid = self.db.issue.create(title='foo')
-# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
-# makeForm({'title': ''}), nodeid), {'title': ''})
-# nodeid = self.db.issue.create(title='foo')
-# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
-# makeForm({'title': ' '}), nodeid), {'title': ''})
+ def testEmptyBoolean(self):
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': ''})), {})
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': ' '})), {})
+ self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
+ self.db.test, makeForm({'boolean': ['', '']}))
+
+ def testSetBoolean(self):
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': 'yes'})), {'boolean': 1})
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': 'a\r\nb\r\n'})), {'boolean': 0})
+ nodeid = self.db.test.create(boolean=1)
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': 'yes'}), nodeid), {})
+ nodeid = self.db.test.create(boolean=0)
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': 'no'}), nodeid), {})
+
+ def testEmptyBooleanSet(self):
+ nodeid = self.db.test.create(boolean=0)
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': ''}), nodeid), {'boolean': None})
+ nodeid = self.db.test.create(boolean=1)
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'boolean': ' '}), nodeid), {'boolean': None})
+ #
+ # Date
+ #
+ def testEmptyDate(self):
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'date': ''})), {})
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'date': ' '})), {})
+ self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
+ self.db.test, makeForm({'date': ['', '']}))
+
+ def testSetDate(self):
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'date': '2003-01-01'})),
+ {'date': date.Date('2003-01-01')})
+ nodeid = self.db.test.create(date=date.Date('2003-01-01'))
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'date': '2003-01-01'}), nodeid), {})
+
+ def testEmptyDateSet(self):
+ nodeid = self.db.test.create(date=date.Date('.'))
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'date': ''}), nodeid), {'date': None})
+ nodeid = self.db.test.create(date=date.Date('1970-01-01.00:00:00'))
+ self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
+ makeForm({'date': ' '}), nodeid), {'date': None})
def suite():
l = [unittest.makeSuite(FormTestCase),