|
12 | 12 | import sys |
13 | 13 | import time |
14 | 14 | import traceback |
| 15 | +import xml |
15 | 16 | from roundup import hyperdb |
16 | 17 | from roundup.exceptions import * |
17 | 18 |
|
@@ -223,6 +224,59 @@ def error_obj(self, status, msg, source=None): |
223 | 224 |
|
224 | 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 | 280 | @_data_decorator |
227 | 281 | def get_collection(self, class_name, input): |
228 | 282 | """GET resource from class URI. |
@@ -704,18 +758,9 @@ def patch_element(self, class_name, item_id, input): |
704 | 758 | (prop, class_name, item_id) |
705 | 759 | ) |
706 | 760 |
|
707 | | - if op == 'add': |
708 | | - props[prop] = class_obj.get(item_id, prop) + props[prop] |
709 | | - elif op == 'replace': |
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) |
| 761 | + props[prop] = self.patch_data( |
| 762 | + op, class_obj.get(item_id, prop), props[prop] |
| 763 | + ) |
719 | 764 |
|
720 | 765 | try: |
721 | 766 | result = class_obj.set(item_id, **props) |
@@ -776,18 +821,9 @@ def patch_attribute(self, class_name, item_id, attr_name, input): |
776 | 821 | ) |
777 | 822 | } |
778 | 823 |
|
779 | | - if op == 'add': |
780 | | - props[prop] = class_obj.get(item_id, prop) + props[prop] |
781 | | - elif op == 'replace': |
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) |
| 824 | + props[prop] = self.patch_data( |
| 825 | + op, class_obj.get(item_id, prop), props[prop] |
| 826 | + ) |
791 | 827 |
|
792 | 828 | try: |
793 | 829 | result = class_obj.set(item_id, **props) |
|
0 commit comments