Skip to content

Commit 6ab9865

Browse files
committed
Added Patch operator 'action'
.. to perform actions such as 'retire' committer: Ralf Schlatterbeck <[email protected]>
1 parent b96521c commit 6ab9865

File tree

2 files changed

+76
-23
lines changed

2 files changed

+76
-23
lines changed

roundup/rest.py

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from roundup import hyperdb
1818
from roundup import date
19+
from roundup import actions
1920
from roundup.exceptions import *
2021
from roundup.cgi.exceptions import *
2122

@@ -230,6 +231,9 @@ class RestfulInstance(object):
230231
def __init__(self, client, db):
231232
self.client = client
232233
self.db = db
234+
self.translator = client.translator
235+
self.actions = client.instance.actions.copy()
236+
self.actions.update({'retire': actions.Retire})
233237

234238
protocol = 'http'
235239
host = self.client.env['HTTP_HOST']
@@ -856,33 +860,63 @@ def patch_element(self, class_name, item_id, input):
856860
op = self.__default_patch_op
857861
class_obj = self.db.getclass(class_name)
858862

859-
props = self.props_from_args(class_obj, input.value, item_id)
860-
861-
for prop, value in props.iteritems():
862-
if not self.db.security.hasPermission(
863-
'Edit', self.db.getuid(), class_name, prop, item_id
864-
):
865-
raise Unauthorised(
866-
'Permission to edit %s of %s%s denied' %
867-
(prop, class_name, item_id)
863+
# if patch operation is action, call the action handler
864+
action_args = [class_name + item_id]
865+
if op == 'action':
866+
# extract action_name and action_args from form fields
867+
for form_field in input.value:
868+
key = form_field.name
869+
value = form_field.value
870+
if key == "action_name":
871+
name = value
872+
elif key.startswith('action_args'):
873+
action_args.append(value)
874+
875+
if name in self.actions:
876+
action_type = self.actions[name]
877+
else:
878+
raise UsageError(
879+
'action "%s" is not supported %s' %
880+
(name, ','.join(self.actions.keys()))
868881
)
882+
action = action_type(self.db, self.translator)
883+
result = action.execute(*action_args)
869884

870-
props[prop] = self.patch_data(
871-
op, class_obj.get(item_id, prop), props[prop]
872-
)
885+
result = {
886+
'id': item_id,
887+
'type': class_name,
888+
'link': self.base_path + class_name + item_id,
889+
'result': result
890+
}
891+
else:
892+
# else patch operation is processing data
893+
props = self.props_from_args(class_obj, input.value, item_id)
894+
895+
for prop, value in props.iteritems():
896+
if not self.db.security.hasPermission(
897+
'Edit', self.db.getuid(), class_name, prop, item_id
898+
):
899+
raise Unauthorised(
900+
'Permission to edit %s of %s%s denied' %
901+
(prop, class_name, item_id)
902+
)
903+
904+
props[prop] = self.patch_data(
905+
op, class_obj.get(item_id, prop), props[prop]
906+
)
873907

874-
try:
875-
result = class_obj.set(item_id, **props)
876-
self.db.commit()
877-
except (TypeError, IndexError, ValueError), message:
878-
raise ValueError(message)
908+
try:
909+
result = class_obj.set(item_id, **props)
910+
self.db.commit()
911+
except (TypeError, IndexError, ValueError), message:
912+
raise ValueError(message)
879913

880-
result = {
881-
'id': item_id,
882-
'type': class_name,
883-
'link': self.base_path + class_name + item_id,
884-
'attribute': result
885-
}
914+
result = {
915+
'id': item_id,
916+
'type': class_name,
917+
'link': self.base_path + class_name + item_id,
918+
'attribute': result
919+
}
886920
return 200, result
887921

888922
@Routing.route("/data/<:class_name>/<:item_id>/<:attr_name>", 'PATCH')

test/test_rest.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,25 @@ def testPatchRemoveAll(self):
461461
self.assertEqual(len(results['attributes']['nosy']), 0)
462462
self.assertEqual(results['attributes']['nosy'], [])
463463

464+
def testPatchAction(self):
465+
"""
466+
Test Patch Action 'Action'
467+
"""
468+
# create a new issue with userid 1 and 2 in the nosy list
469+
issue_id = self.db.issue.create(title='foo')
470+
471+
# execute action retire
472+
form = cgi.FieldStorage()
473+
form.list = [
474+
cgi.MiniFieldStorage('op', 'action'),
475+
cgi.MiniFieldStorage('action_name', 'retire')
476+
]
477+
results = self.server.patch_element('issue', issue_id, form)
478+
self.assertEqual(self.dummy_client.response_code, 200)
479+
480+
# verify the result
481+
self.assertTrue(self.db.issue.is_retired(issue_id))
482+
464483
def testPatchRemove(self):
465484
"""
466485
Test Patch Action 'Remove' only some element from a list

0 commit comments

Comments
 (0)