Mercurial > p > roundup > code
comparison roundup/rest.py @ 5595:65caddd54da2 REST-rebased
Handle operation for patch separately
Patch remove operation is now able to remove element from list and dict,
Added more test on new changes
committer: Ralf Schlatterbeck <rsc@runtux.com>
| author | Chau Nguyen <dangchau1991@yahoo.com> |
|---|---|
| date | Wed, 30 Jan 2019 10:26:35 +0100 |
| parents | 864cf6cb5790 |
| children | 55fa81de6a57 |
comparison
equal
deleted
inserted
replaced
| 5594:864cf6cb5790 | 5595:65caddd54da2 |
|---|---|
| 10 import json | 10 import json |
| 11 import pprint | 11 import pprint |
| 12 import sys | 12 import sys |
| 13 import time | 13 import time |
| 14 import traceback | 14 import traceback |
| 15 import xml | |
| 15 from roundup import hyperdb | 16 from roundup import hyperdb |
| 16 from roundup.exceptions import * | 17 from roundup.exceptions import * |
| 17 | 18 |
| 18 | 19 |
| 19 def _data_decorator(func): | 20 def _data_decorator(func): |
| 221 if source is not None: | 222 if source is not None: |
| 222 result['error']['source'] = source | 223 result['error']['source'] = source |
| 223 | 224 |
| 224 return result | 225 return result |
| 225 | 226 |
| 227 def patch_data(self, op, old_val, new_val): | |
| 228 """Perform patch operation based on old_val and new_val | |
| 229 | |
| 230 Args: | |
| 231 op (string): PATCH operation: add, replace, remove | |
| 232 old_val: old value of the property | |
| 233 new_val: new value of the property | |
| 234 | |
| 235 Returns: | |
| 236 result (string): value after performed the operation | |
| 237 """ | |
| 238 # add operation: If neither of the value is None, use the other one | |
| 239 # Otherwise, concat those 2 value | |
| 240 if op == 'add': | |
| 241 if old_val is None: | |
| 242 result = new_val | |
| 243 elif new_val is None: | |
| 244 result = old_val | |
| 245 else: | |
| 246 result = old_val + new_val | |
| 247 # Replace operation: new value is returned | |
| 248 elif op == 'replace': | |
| 249 result = new_val | |
| 250 # Remove operation: | |
| 251 # if old_val is not a list/dict, change it to None | |
| 252 # if old_val is a list/dict, but the parameter is empty, | |
| 253 # change it to none | |
| 254 # if old_val is a list/dict, and parameter is not empty | |
| 255 # proceed to remove the values from parameter from the list/dict | |
| 256 elif op == 'remove': | |
| 257 if isinstance(old_val, list): | |
| 258 if new_val is None: | |
| 259 result = [] | |
| 260 elif isinstance(new_val, list): | |
| 261 result = [x for x in old_val if x not in new_val] | |
| 262 else: | |
| 263 if new_val in old_val: | |
| 264 old_val.remove(new_val) | |
| 265 elif isinstance(old_val, dict): | |
| 266 if new_val is None: | |
| 267 result = {} | |
| 268 elif isinstance(new_val, dict): | |
| 269 for x in new_val: | |
| 270 old_val.pop(x, None) | |
| 271 else: | |
| 272 old_val.pop(new_val, None) | |
| 273 else: | |
| 274 result = None | |
| 275 else: | |
| 276 raise UsageError('PATCH Operation %s is not allowed' % op) | |
| 277 | |
| 278 return result | |
| 279 | |
| 226 @_data_decorator | 280 @_data_decorator |
| 227 def get_collection(self, class_name, input): | 281 def get_collection(self, class_name, input): |
| 228 """GET resource from class URI. | 282 """GET resource from class URI. |
| 229 | 283 |
| 230 This function returns only items have View permission | 284 This function returns only items have View permission |
| 702 raise Unauthorised( | 756 raise Unauthorised( |
| 703 'Permission to edit %s of %s%s denied' % | 757 'Permission to edit %s of %s%s denied' % |
| 704 (prop, class_name, item_id) | 758 (prop, class_name, item_id) |
| 705 ) | 759 ) |
| 706 | 760 |
| 707 if op == 'add': | 761 props[prop] = self.patch_data( |
| 708 props[prop] = class_obj.get(item_id, prop) + props[prop] | 762 op, class_obj.get(item_id, prop), props[prop] |
| 709 elif op == 'replace': | 763 ) |
| 710 pass | |
| 711 elif op == 'remove': | |
| 712 current_prop = class_obj.get(item_id, prop) | |
| 713 if isinstance(current_prop, list): | |
| 714 props[prop] = [] | |
| 715 else: | |
| 716 props[prop] = None | |
| 717 else: | |
| 718 raise UsageError('PATCH Operation %s is not allowed' % op) | |
| 719 | 764 |
| 720 try: | 765 try: |
| 721 result = class_obj.set(item_id, **props) | 766 result = class_obj.set(item_id, **props) |
| 722 self.db.commit() | 767 self.db.commit() |
| 723 except (TypeError, IndexError, ValueError), message: | 768 except (TypeError, IndexError, ValueError), message: |
| 774 prop: self.prop_from_arg( | 819 prop: self.prop_from_arg( |
| 775 class_obj, prop, input['data'].value, item_id | 820 class_obj, prop, input['data'].value, item_id |
| 776 ) | 821 ) |
| 777 } | 822 } |
| 778 | 823 |
| 779 if op == 'add': | 824 props[prop] = self.patch_data( |
| 780 props[prop] = class_obj.get(item_id, prop) + props[prop] | 825 op, class_obj.get(item_id, prop), props[prop] |
| 781 elif op == 'replace': | 826 ) |
| 782 pass | |
| 783 elif op == 'remove': | |
| 784 current_prop = class_obj.get(item_id, prop) | |
| 785 if isinstance(current_prop, list): | |
| 786 props[prop] = [] | |
| 787 else: | |
| 788 props[prop] = None | |
| 789 else: | |
| 790 raise UsageError('PATCH Operation %s is not allowed' % op) | |
| 791 | 827 |
| 792 try: | 828 try: |
| 793 result = class_obj.set(item_id, **props) | 829 result = class_obj.set(item_id, **props) |
| 794 self.db.commit() | 830 self.db.commit() |
| 795 except (TypeError, IndexError, ValueError), message: | 831 except (TypeError, IndexError, ValueError), message: |
