From c265073862706e48965b0e6312e281fcb726d8fa Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Mon, 26 Nov 2012 11:41:14 -0500 Subject: [PATCH] Use jsonpatch to provide a JSON patch document The attribute "patch" of a model now returns a string representing all of the operations that have occurred on the model since it was created in JSON patch form. --- requirements.txt | 1 + test/test_core.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ warlock/core.py | 7 +++++++ 3 files changed, 52 insertions(+) diff --git a/requirements.txt b/requirements.txt index 35c7022..bd9b4f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ jsonschema>=0.7,<1 +jsonpatch==0.10 diff --git a/test/test_core.py b/test/test_core.py index b4e1627..5226794 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -142,3 +142,47 @@ class TestCore(unittest.TestCase): self.assertEqual(sweden.changes, {'name': 'Finland'}) sweden['name'] = 'Norway' self.assertEqual(sweden.changes, {'name': 'Norway'}) + + def test_patch_no_changes(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + self.assertEqual(sweden.patch, '[]') + + def test_patch_alter_value(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + sweden['name'] = 'Finland' + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Finland", "op": "replace"}]') + + def test_patch_drop_attribute(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + del sweden['name'] + self.assertEqual(sweden.patch, '[{"path": "/name", "op": "remove"}]') + + def test_patch_reduce_operations(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + + sweden['name'] = 'Finland' + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Finland", "op": "replace"}]') + + sweden['name'] = 'Norway' + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Norway", "op": "replace"}]') + + def test_patch_multiple_operations(self): + Country = warlock.model_factory(fixture) + sweden = Country(name='Sweden', population=9379116) + + sweden['name'] = 'Finland' + sweden['population'] = 5387000 + self.assertEqual( + sweden.patch, + '[{"path": "/name", "value": "Finland", "op": "replace"}, ' + '{"path": "/population", "value": 5387000, "op": "replace"}]') diff --git a/warlock/core.py b/warlock/core.py index 38cb854..9c3cdf7 100644 --- a/warlock/core.py +++ b/warlock/core.py @@ -3,6 +3,7 @@ import copy import jsonschema +import jsonpatch class InvalidOperation(RuntimeError): @@ -43,6 +44,7 @@ def model_factory(schema): dict.__init__(self, d) self.__dict__['changes'] = {} + self.__dict__['__original__'] = copy.deepcopy(d) def __getattr__(self, key): try: @@ -118,5 +120,10 @@ def model_factory(schema): def changes(self): return copy.deepcopy(self.__dict__['changes']) + @property + def patch(self): + original = self.__dict__['__original__'] + return jsonpatch.make_patch(original, dict(self)).to_string() + Model.__name__ = str(schema['name']) return Model