Revert to original apply_patch() behavior and make f3f3410 changes optional.

This commit is contained in:
Alexander Shorin
2012-01-05 14:35:40 +04:00
parent 30a61e17a1
commit 13a252dc70
2 changed files with 61 additions and 31 deletions

View File

@@ -39,6 +39,7 @@ __version__ = '0.1'
__website__ = 'https://github.com/stefankoegl/python-json-patch'
__license__ = 'Modified BSD License'
import copy
import sys
if sys.version_info < (2, 6):
@@ -60,19 +61,19 @@ class JsonPatchConflict(JsonPatchException):
"""
def apply_patch(doc, patch):
def apply_patch(doc, patch, in_place=False):
"""Apply list of patches to specified json document.
>>> doc = {'foo': 'bar'}
>>> other = apply_patch(doc, [{'add': '/baz', 'value': 'qux'}])
>>> doc is other
>>> doc is not other
True
>>> doc
>>> other
{'foo': 'bar', 'baz': 'qux'}
"""
patch = JsonPatch(patch)
return patch.apply(doc)
return patch.apply(doc, in_place)
def make_patch(src, dst):
"""Generates patch by comparing of two objects.
@@ -80,9 +81,8 @@ def make_patch(src, dst):
>>> src = {'foo': 'bar', 'numbers': [1, 3, 4, 8]}
>>> dst = {'baz': 'qux', 'numbers': [1, 4, 7]}
>>> patch = make_patch(src, dst)
>>> patch.apply(src) #doctest: +ELLIPSIS
{...}
>>> src == dst
>>> new = patch.apply(src)
>>> new == dst
True
"""
def compare_values(path, value, other):
@@ -164,9 +164,12 @@ class JsonPatch(object):
"""Returns patch set as JSON string."""
return json.dumps(self.patch)
def apply(self, obj):
def apply(self, obj, in_place=False):
"""Applies the patch to given object."""
if not in_place:
obj = copy.deepcopy(obj)
for operation in self.patch:
operation = self._get_operation(operation)
operation.apply(obj)

View File

@@ -8,48 +8,61 @@ import jsonpatch
class ApplyPatchTestCase(unittest.TestCase):
def test_apply_patch_to_copy(self):
obj = {'foo': 'bar'}
res = jsonpatch.apply_patch(obj, [{'add': '/baz', 'value': 'qux'}])
self.assertTrue(obj is not res)
def test_apply_patch_to_same_instance(self):
obj = {'foo': 'bar'}
res = jsonpatch.apply_patch(obj, [{'add': '/baz', 'value': 'qux'}],
in_place=True)
self.assertTrue(obj is res)
def test_add_object_key(self):
obj = {'foo': 'bar'}
jsonpatch.apply_patch(obj, [{'add': '/baz', 'value': 'qux'}])
self.assertTrue('baz' in obj)
self.assertEqual(obj['baz'], 'qux')
res = jsonpatch.apply_patch(obj, [{'add': '/baz', 'value': 'qux'}])
self.assertTrue('baz' in res)
self.assertEqual(res['baz'], 'qux')
def test_add_array_item(self):
obj = {'foo': ['bar', 'baz']}
jsonpatch.apply_patch(obj, [{'add': '/foo/1', 'value': 'qux'}])
self.assertEqual(obj['foo'], ['bar', 'qux', 'baz'])
res = jsonpatch.apply_patch(obj, [{'add': '/foo/1', 'value': 'qux'}])
self.assertEqual(res['foo'], ['bar', 'qux', 'baz'])
def test_remove_object_key(self):
obj = {'foo': 'bar', 'baz': 'qux'}
jsonpatch.apply_patch(obj, [{'remove': '/baz'}])
self.assertTrue('baz' not in obj)
res = jsonpatch.apply_patch(obj, [{'remove': '/baz'}])
self.assertTrue('baz' not in res)
def test_remove_array_item(self):
obj = {'foo': ['bar', 'qux', 'baz']}
jsonpatch.apply_patch(obj, [{'remove': '/foo/1'}])
self.assertEqual(obj['foo'], ['bar', 'baz'])
res = jsonpatch.apply_patch(obj, [{'remove': '/foo/1'}])
self.assertEqual(res['foo'], ['bar', 'baz'])
def test_replace_object_key(self):
obj = {'foo': 'bar', 'baz': 'qux'}
jsonpatch.apply_patch(obj, [{'replace': '/baz', 'value': 'boo'}])
self.assertTrue(obj['baz'], 'boo')
res = jsonpatch.apply_patch(obj, [{'replace': '/baz', 'value': 'boo'}])
self.assertTrue(res['baz'], 'boo')
def test_replace_array_item(self):
obj = {'foo': ['bar', 'qux', 'baz']}
jsonpatch.apply_patch(obj, [{'replace': '/foo/1', 'value': 'boo'}])
self.assertEqual(obj['foo'], ['bar', 'boo', 'baz'])
res = jsonpatch.apply_patch(obj, [{'replace': '/foo/1',
'value': 'boo'}])
self.assertEqual(res['foo'], ['bar', 'boo', 'baz'])
def test_move_object_key(self):
obj = {'foo': {'bar': 'baz', 'waldo': 'fred'},
'qux': {'corge': 'grault'}}
jsonpatch.apply_patch(obj, [{'move': '/foo/waldo', 'to': '/qux/thud'}])
self.assertEqual(obj, {'qux': {'thud': 'fred', 'corge': 'grault'},
res = jsonpatch.apply_patch(obj, [{'move': '/foo/waldo',
'to': '/qux/thud'}])
self.assertEqual(res, {'qux': {'thud': 'fred', 'corge': 'grault'},
'foo': {'bar': 'baz'}})
def test_move_array_item(self):
obj = {'foo': ['all', 'grass', 'cows', 'eat']}
jsonpatch.apply_patch(obj, [{'move': '/foo/1', 'to': '/foo/3'}])
self.assertEqual(obj, {'foo': ['all', 'cows', 'eat', 'grass']})
res = jsonpatch.apply_patch(obj, [{'move': '/foo/1', 'to': '/foo/3'}])
self.assertEqual(res, {'foo': ['all', 'cows', 'eat', 'grass']})
def test_test_success(self):
obj = {'baz': 'qux', 'foo': ['a', 2, 'c']}
@@ -65,19 +78,33 @@ class ApplyPatchTestCase(unittest.TestCase):
class MakePatchTestCase(unittest.TestCase):
def test_apply_patch_to_copy(self):
src = {'foo': 'bar', 'boo': 'qux'}
dst = {'baz': 'qux', 'foo': 'boo'}
patch = jsonpatch.make_patch(src, dst)
res = patch.apply(src)
self.assertTrue(src is not res)
def test_apply_patch_to_same_instance(self):
src = {'foo': 'bar', 'boo': 'qux'}
dst = {'baz': 'qux', 'foo': 'boo'}
patch = jsonpatch.make_patch(src, dst)
res = patch.apply(src, in_place=True)
self.assertTrue(src is res)
def test_objects(self):
src = {'foo': 'bar', 'boo': 'qux'}
dst = {'baz': 'qux', 'foo': 'boo'}
patch = jsonpatch.make_patch(src, dst)
patch.apply(src)
self.assertEqual(src, dst)
res = patch.apply(src)
self.assertEqual(res, dst)
def test_arrays(self):
src = {'numbers': [1, 2, 3], 'other': [1, 3, 4, 5]}
dst = {'numbers': [1, 3, 4, 5], 'other': [1, 3, 4]}
patch = jsonpatch.make_patch(src, dst)
patch.apply(src)
self.assertEqual(src, dst)
res = patch.apply(src)
self.assertEqual(res, dst)
def test_complex_object(self):
src = {'data': [
@@ -87,8 +114,8 @@ class MakePatchTestCase(unittest.TestCase):
{'foo': [42]}, {'bar': []}, {'baz': {'boo': 'oom!'}}
]}
patch = jsonpatch.make_patch(src, dst)
patch.apply(src)
self.assertEqual(src, dst)
res = patch.apply(src)
self.assertEqual(res, dst)
def suite():