From f35bea25b82f05df7a48f9f06617f32f75a060c7 Mon Sep 17 00:00:00 2001 From: richard Date: Fri, 20 Feb 2004 03:48:16 +0000 Subject: [PATCH] fixes to some unit tests, and a cleanup git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@2101 57a73879-2fb5-44c3-a270-3262357dd7e2 --- roundup/cgi/actions.py | 52 +++++++++++++++++++++--------------------- roundup/cgi/client.py | 8 +++---- test/test_actions.py | 35 ++++++++++++++++------------ 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/roundup/cgi/actions.py b/roundup/cgi/actions.py index 43346c2..36a4d9d 100755 --- a/roundup/cgi/actions.py +++ b/roundup/cgi/actions.py @@ -14,7 +14,7 @@ __all__ = ['Action', 'ShowAction', 'RetireAction', 'SearchAction', # used by a couple of routines chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' -class Action: +class Action: def __init__(self, client): self.client = client self.form = client.form @@ -25,7 +25,7 @@ class Action: self.userid = client.userid self.base = client.base self.user = client.user - + def execute(self): """Execute the action specified by this object.""" self.permission() @@ -40,20 +40,20 @@ class Action: a simple permission, check whether the user has that permission. Subclasses must also define the name attribute if they define permissionType. - + Despite having this permission, users may still be unauthorised to - perform parts of actions. It is up to the subclasses to detect this. + perform parts of actions. It is up to the subclasses to detect this. """ if (self.permissionType and - not self.hasPermission(self.permissionType)): - - raise Unauthorised, _('You do not have permission to %s the %s class.' % - (self.name, self.classname)) + not self.hasPermission(self.permissionType)): + info = {'action': self.name, 'classname': self.classname} + raise Unauthorised, _('You do not have permission to ' + '%(action)s the %(classname)s class.')%info def hasPermission(self, permission): """Check whether the user has 'permission' on the current class.""" return self.db.security.hasPermission(permission, self.client.userid, - self.client.classname) + self.client.classname) class ShowAction(Action): def handle(self, typere=re.compile('[@:]type'), @@ -75,7 +75,7 @@ class RetireAction(Action): permissionType = 'Edit' def handle(self): - """Retire the context item.""" + """Retire the context item.""" # if we want to view the index template now, then unset the nodeid # context info (a special-case for retire actions on the index page) nodeid = self.nodeid @@ -98,7 +98,7 @@ class RetireAction(Action): class SearchAction(Action): name = 'search' permissionType = 'View' - + def handle(self, wcre=re.compile(r'[\s,]+')): """Mangle some of the form variables. @@ -113,7 +113,7 @@ class SearchAction(Action): """ self.fakeFilterVars() - queryname = self.getQueryName() + queryname = self.getQueryName() # handle saving the query params if queryname: @@ -165,7 +165,7 @@ class SearchAction(Action): # replace the single value with the split list for v in l: self.form.value.append(cgi.MiniFieldStorage(key, v)) - + self.form.value.append(cgi.MiniFieldStorage('@filter', key)) FV_QUERYNAME = re.compile(r'[@:]queryname') @@ -178,7 +178,7 @@ class SearchAction(Action): class EditCSVAction(Action): name = 'edit' permissionType = 'Edit' - + def handle(self): """Performs an edit of all of a class' items in one go. @@ -270,13 +270,13 @@ class EditCSVAction(Action): self.db.commit() self.client.ok_message.append(_('Items edited OK')) - + class _EditAction(Action): def isEditingSelf(self): """Check whether a user is editing his/her own details.""" return (self.nodeid == self.userid and self.db.user.get(self.nodeid, 'username') != 'anonymous') - + def editItemPermission(self, props): """Determine whether the user has permission to edit this item. @@ -444,12 +444,12 @@ class EditItemAction(_EditAction): def handleCollision(self): self.client.template = 'collision' - + def handle(self): """Perform an edit of an item in the database. See parsePropsFromForm and _editnodes for special variables. - + """ if self.detectCollision(self.lastUserActivity(), self.lastNodeActivity()): self.handleCollision() @@ -480,7 +480,7 @@ class EditItemAction(_EditAction): req = templating.HTMLRequest(self) url += '&' + req.indexargs_href('', {})[1:] raise Redirect, url - + class NewItemAction(_EditAction): def handle(self): ''' Add a new item to the database. @@ -512,14 +512,14 @@ class NewItemAction(_EditAction): raise Redirect, '%s%s%s?@ok_message=%s&@template=%s'%(self.base, self.classname, self.nodeid, urllib.quote(messages), urllib.quote(self.template)) - + class PassResetAction(Action): def handle(self): """Handle password reset requests. - + Presence of either "name" or "address" generates email. Presence of "otk" performs the reset. - + """ if self.form.has_key('otk'): # pull the rego information out of the otk database @@ -621,7 +621,7 @@ class ConfRegoAction(Action): except (ValueError, KeyError), message: self.client.error_message.append(str(message)) return - + # log the new user in self.client.user = self.db.user.get(self.userid, 'username') # re-open the database for real, using the user @@ -645,19 +645,19 @@ class ConfRegoAction(Action): class RegisterAction(Action): name = 'register' permissionType = 'Web Registration' - + def handle(self): """Attempt to create a new user based on the contents of the form and then set the cookie. Return 1 on successful login. - """ + """ props = self.client.parsePropsFromForm(create=1)[0][('user', None)] # registration isn't allowed to supply roles if props.has_key('roles'): raise Unauthorised, _("It is not permitted to supply roles " - "at registration.") + "at registration.") username = props['username'] try: diff --git a/roundup/cgi/client.py b/roundup/cgi/client.py index e095de1..4a2a78d 100644 --- a/roundup/cgi/client.py +++ b/roundup/cgi/client.py @@ -1,4 +1,4 @@ -# $Id: client.py,v 1.161 2004-02-15 10:08:20 jlgijsbers Exp $ +# $Id: client.py,v 1.162 2004-02-20 03:48:16 richard Exp $ """WWW request handler (also used in the stand-alone server). """ @@ -239,7 +239,7 @@ class Client: def clean_sessions(self): """Age sessions, remove when they haven't been used for a week. - + Do it only once an hour. Note: also cleans One Time Keys, and other "session" based stuff. @@ -558,8 +558,8 @@ class Client: # old way of specifying actions getattr(self, action_klass)() else: - action_klass(self).handle() - + action_klass(self).execute() + except ValueError, err: self.error_message.append(str(err)) diff --git a/test/test_actions.py b/test/test_actions.py index 2c807c1..ebf39df 100755 --- a/test/test_actions.py +++ b/test/test_actions.py @@ -20,11 +20,11 @@ class MockNull: # # For example (with just 'client' defined): # - # client.db.config.TRACKER_WEB = 'BASE/' + # client.db.config.TRACKER_WEB = 'BASE/' setattr(self, name, MockNull()) return getattr(self, name) - def __getitem__(self, key): return self + def __getitem__(self, key): return self def __nonzero__(self): return 0 def __str__(self): return '' @@ -36,7 +36,7 @@ class ActionTestCase(unittest.TestCase): self.form = FieldStorage() self.client = MockNull() self.client.form = self.form - + class ShowActionTestCase(ActionTestCase): def assertRaisesMessage(self, exception, callable, message, *args, **kwargs): try: @@ -47,7 +47,7 @@ class ShowActionTestCase(ActionTestCase): if hasattr(excClass,'__name__'): excName = excClass.__name__ else: excName = str(excClass) raise self.failureException, excName - + def testShowAction(self): self.client.db.config.TRACKER_WEB = 'BASE/' @@ -56,7 +56,7 @@ class ShowActionTestCase(ActionTestCase): self.form.value.append(MiniFieldStorage('@type', 'issue')) self.assertRaisesMessage(Redirect, action.handle, 'BASE/issue') - + self.form.value.append(MiniFieldStorage('@number', '1')) self.assertRaisesMessage(Redirect, action.handle, 'BASE/issue1') @@ -68,13 +68,18 @@ class RetireActionTestCase(ActionTestCase): self.assert_(len(self.client.ok_message) == 1) def testNoPermission(self): - self.assertRaises(Unauthorised, RetireAction(self.client).handle) + self.assertRaises(Unauthorised, RetireAction(self.client).execute) def testDontRetireAdminOrAnonymous(self): self.client.db.security.hasPermission=true - self.client.classname = 'user' + # look up the user class + self.client.classname = 'user' + # but always look up admin, regardless of nodeid self.client.db.user.get = lambda a,b: 'admin' self.assertRaises(ValueError, RetireAction(self.client).handle) + # .. or anonymous + self.client.db.user.get = lambda a,b: 'anonymous' + self.assertRaises(ValueError, RetireAction(self.client).handle) class SearchActionTestCase(ActionTestCase): def setUp(self): @@ -83,8 +88,8 @@ class SearchActionTestCase(ActionTestCase): class StandardSearchActionTestCase(SearchActionTestCase): def testNoPermission(self): - self.assertRaises(Unauthorised, self.action.handle) - + self.assertRaises(Unauthorised, self.action.execute) + def testQueryName(self): self.assertEqual(self.action.getQueryName(), '') @@ -99,7 +104,7 @@ class FakeFilterVarsTestCase(SearchActionTestCase): def assertFilterEquals(self, expected): self.action.fakeFilterVars() self.assertEqual(self.form.getvalue('@filter'), expected) - + def testEmptyMultilink(self): self.form.value.append(MiniFieldStorage('foo', '')) self.form.value.append(MiniFieldStorage('foo', '')) @@ -128,7 +133,7 @@ class FakeFilterVarsTestCase(SearchActionTestCase): def testTokenizedStringKey(self): self.client.db.classes.getprops = lambda: {'foo': hyperdb.String()} self.form.value.append(MiniFieldStorage('foo', 'hello world')) - + self.assertFilterEquals('foo') # The single value gets replaced with the tokenized list. @@ -139,11 +144,11 @@ class CollisionDetectionTestCase(ActionTestCase): ActionTestCase.setUp(self) self.action = EditItemAction(self.client) self.now = Date('.') - + def testLastUserActivity(self): self.assertEqual(self.action.lastUserActivity(), None) - self.client.form.value.append(MiniFieldStorage('@lastactivity', str(self.now))) + self.client.form.value.append(MiniFieldStorage('@lastactivity', str(self.now))) self.assertEqual(self.action.lastUserActivity(), self.now) def testLastNodeActivity(self): @@ -161,8 +166,8 @@ class CollisionDetectionTestCase(ActionTestCase): def testCollision(self): self.failUnless(self.action.detectCollision(self.now, self.now + Interval("1d"))) self.failIf(self.action.detectCollision(self.now, self.now - Interval("1d"))) - self.failIf(self.action.detectCollision(None, self.now)) - + self.failIf(self.action.detectCollision(None, self.now)) + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(RetireActionTestCase)) -- 2.30.2