Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added op as init param for JsonPatchException #126

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 29 additions & 20 deletions jsonpatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@
class JsonPatchException(Exception):
"""Base Json Patch exception"""

def __init__(self, op=None):
"""
Initialize a new instance of a JsonPatchException
:param op: The operation that failed. Attach to exception if you
desire to catch and modify the original patch operations.
:type op: Type[PatchOperation]
"""
self.op = op


class InvalidJsonPatch(JsonPatchException):
""" Raised if an invalid JSON Patch is created """
Expand Down Expand Up @@ -238,7 +247,7 @@ def apply(self, obj):
del subobj[part]
except (KeyError, IndexError) as ex:
msg = "can't remove a non-existent object '{0}'".format(part)
raise JsonPatchConflict(msg)
raise JsonPatchConflict(msg, op=self)

return obj

Expand Down Expand Up @@ -267,7 +276,7 @@ def apply(self, obj):
value = self.operation["value"]
except KeyError as ex:
raise InvalidJsonPatch(
"The operation does not contain a 'value' member")
"The operation does not contain a 'value' member", op=self)

subobj, part = self.pointer.to_last(obj)

Expand All @@ -276,7 +285,7 @@ def apply(self, obj):
subobj.append(value) # pylint: disable=E1103

elif part > len(subobj) or part < 0:
raise JsonPatchConflict("can't insert outside of list")
raise JsonPatchConflict("can't insert outside of list", op=self)

else:
subobj.insert(part, value) # pylint: disable=E1103
Expand All @@ -291,7 +300,7 @@ def apply(self, obj):
if part is None:
raise TypeError("invalid document type {0}".format(type(subobj)))
else:
raise JsonPatchConflict("unable to fully resolve json pointer {0}, part {1}".format(self.location, part))
raise JsonPatchConflict("unable to fully resolve json pointer {0}, part {1}".format(self.location, part), op=self)
return obj

def _on_undo_remove(self, path, key):
Expand Down Expand Up @@ -319,29 +328,29 @@ def apply(self, obj):
value = self.operation["value"]
except KeyError as ex:
raise InvalidJsonPatch(
"The operation does not contain a 'value' member")
"The operation does not contain a 'value' member", op=self)

subobj, part = self.pointer.to_last(obj)

if part is None:
return value

if part == "-":
raise InvalidJsonPatch("'path' with '-' can't be applied to 'replace' operation")
raise InvalidJsonPatch("'path' with '-' can't be applied to 'replace' operation", op=self)

if isinstance(subobj, MutableSequence):
if part >= len(subobj) or part < 0:
raise JsonPatchConflict("can't replace outside of list")
raise JsonPatchConflict("can't replace outside of list", op=self)

elif isinstance(subobj, MutableMapping):
if part not in subobj:
msg = "can't replace a non-existent object '{0}'".format(part)
raise JsonPatchConflict(msg)
raise JsonPatchConflict(msg, op=self)
else:
if part is None:
raise TypeError("invalid document type {0}".format(type(subobj)))
else:
raise JsonPatchConflict("unable to fully resolve json pointer {0}, part {1}".format(self.location, part))
raise JsonPatchConflict("unable to fully resolve json pointer {0}, part {1}".format(self.location, part), op=self)

subobj[part] = value
return obj
Expand All @@ -364,21 +373,21 @@ def apply(self, obj):
from_ptr = self.pointer_cls(self.operation['from'])
except KeyError as ex:
raise InvalidJsonPatch(
"The operation does not contain a 'from' member")
"The operation does not contain a 'from' member", op=self)

subobj, part = from_ptr.to_last(obj)
try:
value = subobj[part]
except (KeyError, IndexError) as ex:
raise JsonPatchConflict(str(ex))
raise JsonPatchConflict(str(ex), op=self)

# If source and target are equal, this is a no-op
if self.pointer == from_ptr:
return obj

if isinstance(subobj, MutableMapping) and \
self.pointer.contains(from_ptr):
raise JsonPatchConflict('Cannot move values into their own children')
raise JsonPatchConflict('Cannot move values into their own children', op=self)

obj = RemoveOperation({
'op': 'remove',
Expand Down Expand Up @@ -450,18 +459,18 @@ def apply(self, obj):
else:
val = self.pointer.walk(subobj, part)
except JsonPointerException as ex:
raise JsonPatchTestFailed(str(ex))
raise JsonPatchTestFailed(str(ex), op=self)

try:
value = self.operation['value']
except KeyError as ex:
raise InvalidJsonPatch(
"The operation does not contain a 'value' member")
"The operation does not contain a 'value' member", op=self)

if val != value:
msg = '{0} ({1}) is not equal to tested value {2} ({3})'
raise JsonPatchTestFailed(msg.format(val, type(val),
value, type(value)))
value, type(value)), op=self)

return obj

Expand All @@ -474,13 +483,13 @@ def apply(self, obj):
from_ptr = self.pointer_cls(self.operation['from'])
except KeyError as ex:
raise InvalidJsonPatch(
"The operation does not contain a 'from' member")
"The operation does not contain a 'from' member", op=self)

subobj, part = from_ptr.to_last(obj)
try:
value = copy.deepcopy(subobj[part])
except (KeyError, IndexError) as ex:
raise JsonPatchConflict(str(ex))
raise JsonPatchConflict(str(ex), op=self)

obj = AddOperation({
'op': 'add',
Expand Down Expand Up @@ -672,15 +681,15 @@ def apply(self, obj, in_place=False):

def _get_operation(self, operation):
if 'op' not in operation:
raise InvalidJsonPatch("Operation does not contain 'op' member")
raise InvalidJsonPatch("Operation does not contain 'op' member", op=operation)

op = operation['op']

if not isinstance(op, basestring):
raise InvalidJsonPatch("Operation must be a string")
raise InvalidJsonPatch("Operation must be a string", op=operation)

if op not in self.operations:
raise InvalidJsonPatch("Unknown operation {0!r}".format(op))
raise InvalidJsonPatch("Unknown operation {0!r}".format(op), op=operation)

cls = self.operations[op]
return cls(operation, pointer_cls=self.pointer_cls)
Expand Down