Skip to content

Commit 6ae023f

Browse files
author
Richard Jones
committed
more CGI fixes and tests
1 parent c381819 commit 6ae023f

File tree

3 files changed

+142
-61
lines changed

3 files changed

+142
-61
lines changed

CHANGES.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ are given with the most recent entry first.
1515
- added mysql backend
1616
- fixes to CGI form handling
1717
- switch metakit to use "compressed" multilink journal change representation
18+
- fixed bug in metakit unlink journalling
19+
- metakit now handles "unset" for most types (not Number and Boolean)
20+
- fixed bug in metakit search-by-ID
1821
- applied unicode patch. All data is stored in utf-8. Incoming messages
1922
converted from any encoding to utf-8, outgoing messages are encoded
2023
according to rfc2822 (sf bug 568873)

roundup/cgi/client.py

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: client.py,v 1.71 2003-01-15 22:39:07 richard Exp $
1+
# $Id: client.py,v 1.72 2003-01-20 23:05:19 richard Exp $
22

33
__doc__ = """
44
WWW request handler (also used in the stand-alone server).
@@ -1254,10 +1254,8 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
12541254
# surrounding whitespace
12551255
value = value.value.strip()
12561256

1257-
if isinstance(proptype, hyperdb.String):
1258-
# fix the CRLF/CR -> LF stuff
1259-
value = fixNewlines(value)
1260-
elif isinstance(proptype, hyperdb.Password):
1257+
# handle by type now
1258+
if isinstance(proptype, hyperdb.Password):
12611259
if not value:
12621260
# ignore empty password values
12631261
continue
@@ -1270,16 +1268,7 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
12701268
if value != confirm.value:
12711269
raise ValueError, 'Password and confirmation text do not match'
12721270
value = password.Password(value)
1273-
elif isinstance(proptype, hyperdb.Date):
1274-
if value:
1275-
value = date.Date(value)
1276-
else:
1277-
value = None
1278-
elif isinstance(proptype, hyperdb.Interval):
1279-
if value:
1280-
value = date.Interval(value)
1281-
else:
1282-
value = None
1271+
12831272
elif isinstance(proptype, hyperdb.Link):
12841273
# see if it's the "no selection" choice
12851274
if value == '-1' or not value:
@@ -1354,14 +1343,24 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
13541343
value = existing
13551344
value.sort()
13561345

1357-
elif isinstance(proptype, hyperdb.Boolean):
1358-
value = value.lower() in ('yes', 'true', 'on', '1')
1359-
elif isinstance(proptype, hyperdb.Number):
1360-
value = int(value)
1361-
1362-
# register this as received if required?
1363-
if propname in required and value is not None:
1364-
required.remove(propname)
1346+
# other types should be None'd if there's no value
1347+
elif value:
1348+
if isinstance(proptype, hyperdb.String):
1349+
# fix the CRLF/CR -> LF stuff
1350+
value = fixNewlines(value)
1351+
elif isinstance(proptype, hyperdb.Date):
1352+
value = date.Date(value)
1353+
elif isinstance(proptype, hyperdb.Interval):
1354+
value = date.Interval(value)
1355+
elif isinstance(proptype, hyperdb.Boolean):
1356+
value = value.lower() in ('yes', 'true', 'on', '1')
1357+
elif isinstance(proptype, hyperdb.Number):
1358+
value = int(value)
1359+
else:
1360+
# if we're creating, just don't include this property
1361+
if not nodeid:
1362+
continue
1363+
value = None
13651364

13661365
# get the old value
13671366
if nodeid:
@@ -1373,23 +1372,40 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
13731372
if not properties.has_key(propname):
13741373
raise
13751374

1376-
# existing may be None, which won't equate to empty strings
1377-
if not existing and not value:
1378-
continue
1379-
1380-
# existing will come out unsorted in some cases
1375+
# make sure the existing multilink is sorted
13811376
if isinstance(proptype, hyperdb.Multilink):
13821377
existing.sort()
13831378

1379+
# "missing" existing values may not be None
1380+
if not existing:
1381+
if isinstance(proptype, hyperdb.String) and not existing:
1382+
# some backends store "missing" Strings as empty strings
1383+
existing = None
1384+
elif isinstance(proptype, hyperdb.Number) and not existing:
1385+
# some backends store "missing" Numbers as 0 :(
1386+
existing = 0
1387+
elif isinstance(proptype, hyperdb.Boolean) and not existing:
1388+
# likewise Booleans
1389+
existing = 0
1390+
13841391
# if changed, set it
13851392
if value != existing:
13861393
props[propname] = value
13871394
else:
13881395
# don't bother setting empty/unset values
1389-
if not value:
1396+
if value is None:
1397+
continue
1398+
elif isinstance(proptype, hyperdb.Multilink) and value == []:
13901399
continue
1400+
elif isinstance(proptype, hyperdb.String) and value == '':
1401+
continue
1402+
13911403
props[propname] = value
13921404

1405+
# register this as received if required?
1406+
if propname in required and value is not None:
1407+
required.remove(propname)
1408+
13931409
# see if all the required properties have been supplied
13941410
if required:
13951411
if len(required) > 1:
@@ -1400,4 +1416,3 @@ def parsePropsFromForm(db, cl, form, nodeid=0, num_re=re.compile('^\d+$')):
14001416

14011417
return props
14021418

1403-

test/test_cgi.py

Lines changed: 94 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
# but WITHOUT ANY WARRANTY; without even the implied warranty of
99
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1010
#
11-
# $Id: test_cgi.py,v 1.5 2003-01-15 22:39:07 richard Exp $
11+
# $Id: test_cgi.py,v 1.6 2003-01-20 23:05:20 richard Exp $
1212

1313
import unittest, os, shutil, errno, sys, difflib, cgi
1414

1515
from roundup.cgi import client
16-
from roundup import init, instance, password
16+
from roundup import init, instance, password, hyperdb, date
1717

1818
def makeForm(args):
1919
form = cgi.FieldStorage()
@@ -43,6 +43,11 @@ def setUp(self):
4343
self.db.user.create(username='mary', address='mary@test',
4444
roles='User', realname='Contrary, Mary')
4545

46+
test = self.instance.dbinit.Class(self.db, "test",
47+
boolean=hyperdb.Boolean(), link=hyperdb.Link('test'),
48+
multilink=hyperdb.Multilink('test'), date=hyperdb.Date(),
49+
interval=hyperdb.Interval())
50+
4651
def tearDown(self):
4752
self.db.close()
4853
try:
@@ -66,6 +71,19 @@ def testNothingWithRequired(self):
6671
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
6772
self.db.issue, makeForm({':required': ['title','status'],
6873
'status':'1'}))
74+
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
75+
self.db.issue, makeForm({':required': 'status',
76+
'status':''}))
77+
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
78+
self.db.issue, makeForm({':required': 'nosy',
79+
'nosy':''}))
80+
81+
#
82+
# Nonexistant edit
83+
#
84+
def testEditNonexistant(self):
85+
self.assertRaises(IndexError, client.parsePropsFromForm, self.db,
86+
self.db.test, makeForm({'boolean': ''}), '1')
6987

7088
#
7189
# String
@@ -83,14 +101,17 @@ def testSetString(self):
83101
makeForm({'title': 'foo'})), {'title': 'foo'})
84102
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
85103
makeForm({'title': 'a\r\nb\r\n'})), {'title': 'a\nb'})
104+
nodeid = self.db.issue.create(title='foo')
105+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
106+
makeForm({'title': 'foo'}), nodeid), {})
86107

87108
def testEmptyStringSet(self):
88109
nodeid = self.db.issue.create(title='foo')
89110
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
90-
makeForm({'title': ''}), nodeid), {'title': ''})
111+
makeForm({'title': ''}), nodeid), {'title': None})
91112
nodeid = self.db.issue.create(title='foo')
92113
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
93-
makeForm({'title': ' '}), nodeid), {'title': ''})
114+
makeForm({'title': ' '}), nodeid), {'title': None})
94115

95116
#
96117
# Link
@@ -110,6 +131,9 @@ def testSetLink(self):
110131
makeForm({'status': 'unread'})), {'status': '1'})
111132
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
112133
makeForm({'status': '1'})), {'status': '1'})
134+
nodeid = self.db.issue.create(status='unread')
135+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
136+
makeForm({'status': 'unread'}), nodeid), {})
113137

114138
def testUnsetLink(self):
115139
nodeid = self.db.issue.create(status='unread')
@@ -122,7 +146,9 @@ def testInvalidLinkValue(self):
122146
# self.db.issue, makeForm({'status': '4'}))
123147
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
124148
self.db.issue, makeForm({'status': 'frozzle'}))
125-
# XXX need a test for the TypeError where the link class doesn't define a key?
149+
150+
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
151+
self.db.test, makeForm({'link': 'frozzle'}))
126152

127153
#
128154
# Multilink
@@ -152,6 +178,8 @@ def testEmptyMultilinkSet(self):
152178
nodeid = self.db.issue.create(nosy=['1','2'])
153179
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
154180
makeForm({'nosy': ' '}), nodeid), {'nosy': []})
181+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
182+
makeForm({'nosy': '1,2'}), nodeid), {})
155183

156184
def testInvalidMultilinkValue(self):
157185
# XXX This is not the current behaviour - should we enforce this?
@@ -161,7 +189,9 @@ def testInvalidMultilinkValue(self):
161189
self.db.issue, makeForm({'nosy': 'frozzle'}))
162190
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
163191
self.db.issue, makeForm({'nosy': '1,frozzle'}))
164-
# XXX need a test for the TypeError (where the ML class doesn't define a key?
192+
193+
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
194+
self.db.test, makeForm({'multilink': 'frozzle'}))
165195

166196
def testMultilinkAdd(self):
167197
nodeid = self.db.issue.create(nosy=['1'])
@@ -241,40 +271,73 @@ def testSetPasswordConfirmBad(self):
241271
self.db.user, makeForm({'password': 'foo',
242272
'password:confirm': 'bar'}))
243273

244-
def testEmptyPasswordNOTSet(self):
245-
nodeid = self.db.user.create(username='1', password=password.Password('foo'))
274+
def testEmptyPasswordNotSet(self):
275+
nodeid = self.db.user.create(username='1',
276+
password=password.Password('foo'))
246277
self.assertEqual(client.parsePropsFromForm(self.db, self.db.user,
247278
makeForm({'password': ''}), nodeid), {})
248-
nodeid = self.db.user.create(username='2', password=password.Password('foo'))
279+
nodeid = self.db.user.create(username='2',
280+
password=password.Password('foo'))
249281
self.assertEqual(client.parsePropsFromForm(self.db, self.db.user,
250282
makeForm({'password': '', 'password:confirm': ''}), nodeid), {})
251283

252284
#
253285
# Boolean
254286
#
255-
# XXX this needs a property to work on.
256-
# def testEmptyBoolean(self):
257-
# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
258-
# makeForm({'title': ''})), {})
259-
# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
260-
# makeForm({'title': ' '})), {})
261-
# self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
262-
# self.db.issue, makeForm({'title': ['', '']}))
263-
264-
# def testSetBoolean(self):
265-
# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
266-
# makeForm({'title': 'foo'})), {'title': 'foo'})
267-
# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
268-
# makeForm({'title': 'a\r\nb\r\n'})), {'title': 'a\nb'})
269-
270-
# def testEmptyBooleanSet(self):
271-
# nodeid = self.db.issue.create(title='foo')
272-
# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
273-
# makeForm({'title': ''}), nodeid), {'title': ''})
274-
# nodeid = self.db.issue.create(title='foo')
275-
# self.assertEqual(client.parsePropsFromForm(self.db, self.db.issue,
276-
# makeForm({'title': ' '}), nodeid), {'title': ''})
287+
def testEmptyBoolean(self):
288+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
289+
makeForm({'boolean': ''})), {})
290+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
291+
makeForm({'boolean': ' '})), {})
292+
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
293+
self.db.test, makeForm({'boolean': ['', '']}))
294+
295+
def testSetBoolean(self):
296+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
297+
makeForm({'boolean': 'yes'})), {'boolean': 1})
298+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
299+
makeForm({'boolean': 'a\r\nb\r\n'})), {'boolean': 0})
300+
nodeid = self.db.test.create(boolean=1)
301+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
302+
makeForm({'boolean': 'yes'}), nodeid), {})
303+
nodeid = self.db.test.create(boolean=0)
304+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
305+
makeForm({'boolean': 'no'}), nodeid), {})
306+
307+
def testEmptyBooleanSet(self):
308+
nodeid = self.db.test.create(boolean=0)
309+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
310+
makeForm({'boolean': ''}), nodeid), {'boolean': None})
311+
nodeid = self.db.test.create(boolean=1)
312+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
313+
makeForm({'boolean': ' '}), nodeid), {'boolean': None})
277314

315+
#
316+
# Date
317+
#
318+
def testEmptyDate(self):
319+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
320+
makeForm({'date': ''})), {})
321+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
322+
makeForm({'date': ' '})), {})
323+
self.assertRaises(ValueError, client.parsePropsFromForm, self.db,
324+
self.db.test, makeForm({'date': ['', '']}))
325+
326+
def testSetDate(self):
327+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
328+
makeForm({'date': '2003-01-01'})),
329+
{'date': date.Date('2003-01-01')})
330+
nodeid = self.db.test.create(date=date.Date('2003-01-01'))
331+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
332+
makeForm({'date': '2003-01-01'}), nodeid), {})
333+
334+
def testEmptyDateSet(self):
335+
nodeid = self.db.test.create(date=date.Date('.'))
336+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
337+
makeForm({'date': ''}), nodeid), {'date': None})
338+
nodeid = self.db.test.create(date=date.Date('1970-01-01.00:00:00'))
339+
self.assertEqual(client.parsePropsFromForm(self.db, self.db.test,
340+
makeForm({'date': ' '}), nodeid), {'date': None})
278341

279342
def suite():
280343
l = [unittest.makeSuite(FormTestCase),

0 commit comments

Comments
 (0)