Skip to content

Commit 98e272e

Browse files
committed
raise JsonPatchException on missing patch attributes
1 parent 3f2f609 commit 98e272e

File tree

2 files changed

+44
-14
lines changed

2 files changed

+44
-14
lines changed

jsonpatch.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class JsonPatchException(Exception):
6060
"""Base Json Patch exception"""
6161

6262

63+
class InvalidJsonPatch(JsonPatchException):
64+
""" Raised if an invalid JSON Patch is created """
65+
66+
6367
class JsonPatchConflict(JsonPatchException):
6468
"""Raised if patch could not be applied due to conflict situation such as:
6569
- attempt to add object key then it already exists;
@@ -341,15 +345,15 @@ def apply(self, obj, in_place=False):
341345

342346
def _get_operation(self, operation):
343347
if 'op' not in operation:
344-
raise JsonPatchException("Operation does not contain 'op' member")
348+
raise InvalidJsonPatch("Operation does not contain 'op' member")
345349

346350
op = operation['op']
347351

348352
if not isinstance(op, basestring):
349-
raise JsonPatchException("Operation must be a string")
353+
raise InvalidJsonPatch("Operation must be a string")
350354

351355
if op not in self.operations:
352-
raise JsonPatchException("Unknown operation {0!r}".format(op))
356+
raise InvalidJsonPatch("Unknown operation {0!r}".format(op))
353357

354358
cls = self.operations[op]
355359
return cls(operation)
@@ -397,7 +401,12 @@ class AddOperation(PatchOperation):
397401
"""Adds an object property or an array element."""
398402

399403
def apply(self, obj):
400-
value = self.operation["value"]
404+
try:
405+
value = self.operation["value"]
406+
except KeyError as ex:
407+
raise InvalidJsonPatch(
408+
"The operation does not contain a 'value' member")
409+
401410
subobj, part = self.pointer.to_last(obj)
402411

403412
if isinstance(subobj, list):
@@ -426,7 +435,12 @@ class ReplaceOperation(PatchOperation):
426435
"""Replaces an object property or an array element by new value."""
427436

428437
def apply(self, obj):
429-
value = self.operation["value"]
438+
try:
439+
value = self.operation["value"]
440+
except KeyError as ex:
441+
raise InvalidJsonPatch(
442+
"The operation does not contain a 'value' member")
443+
430444
subobj, part = self.pointer.to_last(obj)
431445

432446
if part is None:
@@ -451,15 +465,20 @@ class MoveOperation(PatchOperation):
451465
"""Moves an object property or an array element to new location."""
452466

453467
def apply(self, obj):
454-
from_ptr = JsonPointer(self.operation['from'])
468+
try:
469+
from_ptr = JsonPointer(self.operation['from'])
470+
except KeyError as ex:
471+
raise InvalidJsonPatch(
472+
"The operation does not contain a 'from' member")
473+
455474
subobj, part = from_ptr.to_last(obj)
456475
try:
457476
value = subobj[part]
458477
except (KeyError, IndexError) as ex:
459478
raise JsonPatchConflict(str(ex))
460479

461480
if isinstance(subobj, dict) and self.pointer.contains(from_ptr):
462-
raise JsonPatchException('Cannot move values into its own children')
481+
raise JsonPatchConflict('Cannot move values into its own children')
463482

464483
obj = RemoveOperation({
465484
'op': 'remove',
@@ -488,12 +507,16 @@ def apply(self, obj):
488507
except JsonPointerException as ex:
489508
raise JsonPatchTestFailed(str(ex))
490509

491-
if 'value' in self.operation:
510+
try:
492511
value = self.operation['value']
493-
if val != value:
494-
msg = '{0} ({1}) is not equal to tested value {2} ({3})'
495-
raise JsonPatchTestFailed(msg.format(val, type(val),
496-
value, type(value)))
512+
except KeyError as ex:
513+
raise InvalidJsonPatch(
514+
"The operation does not contain a 'value' member")
515+
516+
if val != value:
517+
msg = '{0} ({1}) is not equal to tested value {2} ({3})'
518+
raise JsonPatchTestFailed(msg.format(val, type(val),
519+
value, type(value)))
497520

498521
return obj
499522

@@ -502,7 +525,12 @@ class CopyOperation(PatchOperation):
502525
""" Copies an object property or an array element to a new location """
503526

504527
def apply(self, obj):
505-
from_ptr = JsonPointer(self.operation['from'])
528+
try:
529+
from_ptr = JsonPointer(self.operation['from'])
530+
except KeyError as ex:
531+
raise InvalidJsonPatch(
532+
"The operation does not contain a 'from' member")
533+
506534
subobj, part = from_ptr.to_last(obj)
507535
try:
508536
value = copy.deepcopy(subobj[part])

tests.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ def test_test_not_existing(self):
158158

159159
def test_test_noval_existing(self):
160160
obj = {'bar': 'qux'}
161-
jsonpatch.apply_patch(obj, [{'op': 'test', 'path': '/bar'}])
161+
self.assertRaises(jsonpatch.InvalidJsonPatch,
162+
jsonpatch.apply_patch,
163+
obj, [{'op': 'test', 'path': '/bar'}])
162164

163165

164166
def test_test_noval_not_existing(self):

0 commit comments

Comments
 (0)