Hello community,
here is the log from the commit of package python-jsonpatch for openSUSE:Factory checked in at 2013-11-04 13:26:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jsonpatch (Old)
and /work/SRC/openSUSE:Factory/.python-jsonpatch.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jsonpatch"
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-jsonpatch/python-jsonpatch.changes 2013-07-22 13:48:20.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-jsonpatch.new/python-jsonpatch.changes 2013-11-04 13:26:28.000000000 +0100
@@ -1,0 +2,7 @@
+Mon Oct 21 13:18:40 UTC 2013 - dmueller@suse.com
+
+- update to 1.3:
+ * Improved Tests, add command line utilities
+- add update-alternatives
+
+-------------------------------------------------------------------
Old:
----
jsonpatch-1.1.tar.gz
New:
----
jsonpatch-1.3.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-jsonpatch.spec ++++++
--- /var/tmp/diff_new_pack.Dt77Z6/_old 2013-11-04 13:26:30.000000000 +0100
+++ /var/tmp/diff_new_pack.Dt77Z6/_new 2013-11-04 13:26:30.000000000 +0100
@@ -17,9 +17,9 @@
Name: python-jsonpatch
-Version: 1.1
+Version: 1.3
Release: 0
-Summary: Apply JSON-Patches (according to draft 08)
+Summary: Python - JSON-Patches
License: BSD-3-Clause
Group: Development/Languages/Python
Url: https://github.com/stefankoegl/python-json-patch
@@ -27,6 +27,8 @@
BuildRequires: python-devel
BuildRequires: python-jsonpointer
Requires: python-jsonpointer >= 1.0
+Requires(post): update-alternatives
+Requires(postun): update-alternatives
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%if 0%{?suse_version} && 0%{?suse_version} <= 1110
%{!?python_sitelib: %global python_sitelib %(python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
@@ -35,7 +37,7 @@
%endif
%description
-Apply JSON-Patches (according to draft 08)
+Python module to apply JSON-Patches (according to RFC 6902).
%prep
%setup -q -n jsonpatch-%{version}
@@ -45,9 +47,30 @@
%install
python setup.py install --prefix=%{_prefix} --root=%{buildroot}
+for i in patch diff; do
+ mv %{buildroot}%{_bindir}/json$i %{buildroot}%{_bindir}/json$i-%{py_ver}
+done
+
+%pre
+[[ ! -L %{_bindir}/jsonpatch ]] && rm -f %{_bindir}/jsonpatch || :
+[[ ! -L %{_bindir}/jsondiff ]] && rm -f %{_bindir}/jsondiff || :
+
+%post
+update-alternatives --install \
+ %{_bindir}/jsonpatch jsonpatch %{_bindir}/jsonpatch-%{py_ver} 20 \
+ --slave %{_bindir}/jsondiff jsondiff %{_bindir}/jsondiff-%{py_ver}
+
+%preun
+if [ $1 -eq 0 ] ; then
+ update-alternatives --remove jsonpatch %{_bindir}/jsonpatch-%{py_ver}
+fi
%files
%defattr(-,root,root,-)
+%ghost %{_bindir}/jsonpatch
+%{_bindir}/jsonpatch-%{py_ver}
+%ghost %{_bindir}/jsondiff
+%{_bindir}/jsondiff-%{py_ver}
%{python_sitelib}/*
%changelog
++++++ jsonpatch-1.1.tar.gz -> jsonpatch-1.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/AUTHORS new/jsonpatch-1.3/AUTHORS
--- old/jsonpatch-1.1/AUTHORS 1970-01-01 01:00:00.000000000 +0100
+++ new/jsonpatch-1.3/AUTHORS 2013-10-13 15:06:14.000000000 +0200
@@ -0,0 +1,4 @@
+Stefan Kögl
+Alexander Shorin
+Byron Ruth
+William Kral
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/COPYING new/jsonpatch-1.3/COPYING
--- old/jsonpatch-1.1/COPYING 1970-01-01 01:00:00.000000000 +0100
+++ new/jsonpatch-1.3/COPYING 2013-10-13 15:06:14.000000000 +0200
@@ -0,0 +1,26 @@
+Copyright (c) 2011 Stefan Kögl
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/MANIFEST.in new/jsonpatch-1.3/MANIFEST.in
--- old/jsonpatch-1.1/MANIFEST.in 2012-12-20 19:06:35.000000000 +0100
+++ new/jsonpatch-1.3/MANIFEST.in 2013-10-13 15:07:25.000000000 +0200
@@ -1 +1,6 @@
include requirements.txt
+include COPYING
+include README.md
+include tests.py
+include ext_tests.py
+include AUTHORS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/PKG-INFO new/jsonpatch-1.3/PKG-INFO
--- old/jsonpatch-1.1/PKG-INFO 2013-06-27 21:50:38.000000000 +0200
+++ new/jsonpatch-1.3/PKG-INFO 2013-10-13 15:14:53.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: jsonpatch
-Version: 1.1
+Version: 1.3
Summary: Apply JSON-Patches (RFC 6902)
Home-page: https://github.com/stefankoegl/python-json-patch
Author: Stefan Kögl
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/README.md new/jsonpatch-1.3/README.md
--- old/jsonpatch-1.1/README.md 1970-01-01 01:00:00.000000000 +0100
+++ new/jsonpatch-1.3/README.md 2013-10-13 15:06:14.000000000 +0200
@@ -0,0 +1,19 @@
+python-json-patch [![Build Status](https://secure.travis-ci.org/stefankoegl/python-json-patch.png?branch=master)](https://travis-ci.org/stefankoegl/python-json-patch) [![Coverage Status](https://coveralls.io/repos/stefankoegl/python-json-patch/badge.png?branch=master)](https://coveralls.io/r/stefankoegl/python-json-patch?branch=master) ![Downloads](https://pypip.in/d/jsonpatch/badge.png) ![Version](https://pypip.in/v/jsonpatch/badge.png)
+=================
+Applying JSON Patches in Python
+-------------------------------
+
+Library to apply JSON Patches according to
+[RFC 6902](http://tools.ietf.org/html/rfc6902)
+
+See Sourcecode for Examples
+
+* Website: https://github.com/stefankoegl/python-json-patch
+* Repository: https://github.com/stefankoegl/python-json-patch.git
+* Documentation: https://python-json-patch.readthedocs.org/
+
+Running external tests
+----------------------
+To run external tests (such as those from https://github.com/json-patch/json-patch-tests) use ext_test.py
+
+ ./ext_tests.py ../json-patch-tests/tests.json
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/bin/jsondiff new/jsonpatch-1.3/bin/jsondiff
--- old/jsonpatch-1.1/bin/jsondiff 1970-01-01 01:00:00.000000000 +0100
+++ new/jsonpatch-1.3/bin/jsondiff 2013-10-13 15:06:14.000000000 +0200
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import print_function
+
+import sys
+import os.path
+import json
+import jsonpatch
+import argparse
+
+
+parser = argparse.ArgumentParser(description='Diff two JSON files')
+parser.add_argument('FILE1', type=argparse.FileType('r'))
+parser.add_argument('FILE2', type=argparse.FileType('r'))
+parser.add_argument('--indent', type=int, default=None,
+ help='Indent output by n spaces')
+parser.add_argument('-v', '--version', action='version',
+ version='%(prog)s ' + jsonpatch.__version__)
+
+
+def main():
+ try:
+ diff_files()
+ except KeyboardInterrupt:
+ sys.exit(1)
+
+
+def diff_files():
+ """ Diffs two JSON files and prints a patch """
+ args = parser.parse_args()
+ doc1 = json.load(args.FILE1)
+ doc2 = json.load(args.FILE2)
+ patch = jsonpatch.make_patch(doc1, doc2)
+ print(json.dumps(patch.patch, indent=args.indent))
+
+
+if __name__ == "__main__":
+ main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/bin/jsonpatch new/jsonpatch-1.3/bin/jsonpatch
--- old/jsonpatch-1.1/bin/jsonpatch 1970-01-01 01:00:00.000000000 +0100
+++ new/jsonpatch-1.3/bin/jsonpatch 2013-10-13 15:06:14.000000000 +0200
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import print_function
+
+import sys
+import os.path
+import json
+import jsonpatch
+import argparse
+
+
+parser = argparse.ArgumentParser(
+ description='Apply a JSON patch on a JSON file')
+parser.add_argument('ORIGINAL', type=argparse.FileType('r'),
+ help='Original file')
+parser.add_argument('PATCH', type=argparse.FileType('r'),
+ help='Patch file')
+parser.add_argument('--indent', type=int, default=None,
+ help='Indent output by n spaces')
+parser.add_argument('-v', '--version', action='version',
+ version='%(prog)s ' + jsonpatch.__version__)
+
+
+def main():
+ try:
+ patch_files()
+ except KeyboardInterrupt:
+ sys.exit(1)
+
+
+def patch_files():
+ """ Diffs two JSON files and prints a patch """
+ args = parser.parse_args()
+ doc = json.load(args.ORIGINAL)
+ patch = json.load(args.PATCH)
+ result = jsonpatch.apply_patch(doc, patch)
+ print(json.dumps(result, indent=args.indent))
+
+
+if __name__ == "__main__":
+ main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/ext_tests.py new/jsonpatch-1.3/ext_tests.py
--- old/jsonpatch-1.1/ext_tests.py 1970-01-01 01:00:00.000000000 +0100
+++ new/jsonpatch-1.3/ext_tests.py 2013-10-13 15:06:14.000000000 +0200
@@ -0,0 +1,137 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# python-json-patch - An implementation of the JSON Patch format
+# https://github.com/stefankoegl/python-json-patch
+#
+# Copyright (c) 2011 Stefan Kögl
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+""" Script to run external tests, eg from
+https://github.com/json-patch/json-patch-tests """
+
+from functools import partial
+import doctest
+import unittest
+import jsonpatch
+import sys
+
+
+class TestCaseTemplate(unittest.TestCase):
+ """ A generic test case for running external tests """
+
+ def _test(self, test):
+ if not 'doc' in test or not 'patch' in test:
+ # incomplete
+ return
+
+ if test.get('disabled', False):
+ # test is disabled
+ return
+
+ if 'error' in test:
+ self.assertRaises(
+ (jsonpatch.JsonPatchException, jsonpatch.JsonPointerException),
+ jsonpatch.apply_patch, test['doc'], test['patch']
+ )
+
+ else:
+ res = jsonpatch.apply_patch(test['doc'], test['patch'])
+
+ # if there is no 'expected' we only verify that applying the patch
+ # does not raies an exception
+ if 'expected' in test:
+ self.assertEquals(res, test['expected'])
+
+
+def make_test_case(tests):
+
+ class MyTestCase(TestCaseTemplate):
+ pass
+
+ for n, test in enumerate(tests):
+ add_test_method(MyTestCase, 'test_%d' % n, test)
+
+ return MyTestCase
+
+
+def add_test_method(cls, name, test):
+ setattr(cls, name, lambda self: self._test(test))
+
+
+
+modules = ['jsonpatch']
+coverage_modules = []
+
+
+def get_suite(filenames):
+ suite = unittest.TestSuite()
+
+ for testfile in filenames:
+ with open(testfile) as f:
+ # we use the (potentially) patched version of json.load here
+ tests = jsonpatch.json.load(f)
+ cls = make_test_case(tests)
+ suite.addTest(unittest.makeSuite(cls))
+
+ return suite
+
+
+suite = get_suite(sys.argv[1:])
+
+for module in modules:
+ m = __import__(module, fromlist=[module])
+ coverage_modules.append(m)
+ suite.addTest(doctest.DocTestSuite(m))
+
+runner = unittest.TextTestRunner(verbosity=1)
+
+try:
+ import coverage
+except ImportError:
+ coverage = None
+
+if coverage is not None:
+ coverage.erase()
+ coverage.start()
+
+result = runner.run(suite)
+
+if not result.wasSuccessful():
+ sys.exit(1)
+
+if coverage is not None:
+ coverage.stop()
+ coverage.report(coverage_modules)
+ coverage.erase()
+
+if coverage is None:
+ sys.stderr.write("""
+No coverage reporting done (Python module "coverage" is missing)
+Please install the python-coverage package to get coverage reporting.
+""")
+ sys.stderr.flush()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/jsonpatch.egg-info/PKG-INFO new/jsonpatch-1.3/jsonpatch.egg-info/PKG-INFO
--- old/jsonpatch-1.1/jsonpatch.egg-info/PKG-INFO 2013-06-27 21:50:37.000000000 +0200
+++ new/jsonpatch-1.3/jsonpatch.egg-info/PKG-INFO 2013-10-13 15:14:53.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: jsonpatch
-Version: 1.1
+Version: 1.3
Summary: Apply JSON-Patches (RFC 6902)
Home-page: https://github.com/stefankoegl/python-json-patch
Author: Stefan Kögl
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/jsonpatch.egg-info/SOURCES.txt new/jsonpatch-1.3/jsonpatch.egg-info/SOURCES.txt
--- old/jsonpatch-1.1/jsonpatch.egg-info/SOURCES.txt 2013-06-27 21:50:38.000000000 +0200
+++ new/jsonpatch-1.3/jsonpatch.egg-info/SOURCES.txt 2013-10-13 15:14:53.000000000 +0200
@@ -1,7 +1,14 @@
+AUTHORS
+COPYING
MANIFEST.in
+README.md
+ext_tests.py
jsonpatch.py
requirements.txt
setup.py
+tests.py
+bin/jsondiff
+bin/jsonpatch
jsonpatch.egg-info/PKG-INFO
jsonpatch.egg-info/SOURCES.txt
jsonpatch.egg-info/dependency_links.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/jsonpatch.py new/jsonpatch-1.3/jsonpatch.py
--- old/jsonpatch-1.1/jsonpatch.py 2013-06-27 21:49:49.000000000 +0200
+++ new/jsonpatch-1.3/jsonpatch.py 2013-10-13 15:13:27.000000000 +0200
@@ -36,12 +36,14 @@
# Will be parsed by setup.py to determine package metadata
__author__ = 'Stefan Kögl '
-__version__ = '1.1'
+__version__ = '1.3'
__website__ = 'https://github.com/stefankoegl/python-json-patch'
__license__ = 'Modified BSD License'
import copy
import sys
+import operator
+import collections
import json
@@ -69,6 +71,41 @@
""" A Test operation failed """
+def multidict(ordered_pairs):
+ """Convert duplicate keys values to lists."""
+ # read all values into lists
+ d = collections.defaultdict(list)
+ for k, v in ordered_pairs:
+ d[k].append(v)
+
+ # unpack lists that have only 1 item
+ for k, v in d.items():
+ if len(v) == 1:
+ d[k] = v[0]
+ return dict(d)
+
+
+def get_loadjson():
+ """ adds the object_pairs_hook parameter to json.load when possible
+
+ The "object_pairs_hook" parameter is used to handle duplicate keys when
+ loading a JSON object. This parameter does not exist in Python 2.6. This
+ methods returns an unmodified json.load for Python 2.6 and a partial
+ function with object_pairs_hook set to multidict for Python versions that
+ support the parameter. """
+
+ import inspect
+ import functools
+
+ argspec = inspect.getargspec(json.load)
+ if 'object_pairs_hook' not in argspec.args:
+ return json.load
+
+ return functools.partial(json.load, object_pairs_hook=multidict)
+
+json.load = get_loadjson()
+
+
def apply_patch(doc, patch, in_place=False):
"""Apply list of patches to specified json document.
@@ -195,14 +232,15 @@
def __hash__(self):
- return hash(tuple(self._get_operation(op) for op in self.patch))
+ return hash(tuple(self._ops))
def __eq__(self, other):
if not isinstance(other, JsonPatch):
return False
- return self.patch == other.patch
+ return len(list(self._ops)) == len(list(other._ops)) and \
+ all(map(operator.eq, self._ops, other._ops))
@classmethod
@@ -282,6 +320,10 @@
"""Returns patch set as JSON string."""
return json.dumps(self.patch)
+ @property
+ def _ops(self):
+ return map(self._get_operation, self.patch)
+
def apply(self, obj, in_place=False):
"""Applies the patch to given object.
@@ -298,8 +340,7 @@
if not in_place:
obj = copy.deepcopy(obj)
- for operation in self.patch:
- operation = self._get_operation(operation)
+ for operation in self._ops:
obj = operation.apply(obj)
return obj
@@ -309,6 +350,10 @@
raise JsonPatchException("Operation does not contain 'op' member")
op = operation['op']
+
+ if not isinstance(op, basestring):
+ raise JsonPatchException("Operation must be a string")
+
if op not in self.operations:
raise JsonPatchException("Unknown operation '%s'" % op)
@@ -348,7 +393,7 @@
subobj, part = self.pointer.to_last(obj)
try:
del subobj[part]
- except KeyError as ex:
+ except IndexError as ex:
raise JsonPatchConflict(str(ex))
return obj
@@ -359,7 +404,12 @@
def apply(self, obj):
value = self.operation["value"]
- subobj, part = self.pointer.to_last(obj, None)
+ subobj, part = self.pointer.to_last(obj)
+
+ # type is already checked in to_last(), so we assert here
+ # for consistency
+ assert isinstance(subobj, list) or isinstance(subobj, dict), \
+ "invalid document type %s" (type(doc),)
if isinstance(subobj, list):
@@ -380,10 +430,6 @@
else:
subobj[part] = value
- else:
- raise JsonPatchConflict("can't add to type '%s'"
- "" % subobj.__class__.__name__)
-
return obj
@@ -394,6 +440,11 @@
value = self.operation["value"]
subobj, part = self.pointer.to_last(obj)
+ # type is already checked in to_last(), so we assert here
+ # for consistency
+ assert isinstance(subobj, list) or isinstance(subobj, dict), \
+ "invalid document type %s" (type(doc),)
+
if part is None:
return value
@@ -406,10 +457,6 @@
raise JsonPatchConflict("can't replace non-existant object '%s'"
"" % part)
- else:
- raise JsonPatchConflict("can't replace in type '%s'"
- "" % subobj.__class__.__name__)
-
subobj[part] = value
return obj
@@ -422,7 +469,7 @@
subobj, part = from_ptr.to_last(obj)
value = subobj[part]
- if from_ptr.contains(self.pointer):
+ if self.pointer.contains(from_ptr):
raise JsonPatchException('Cannot move values into its own children')
obj = RemoveOperation({'op': 'remove', 'path': self.operation['from']}).apply(obj)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/setup.py new/jsonpatch-1.3/setup.py
--- old/jsonpatch-1.1/setup.py 2013-03-26 12:54:25.000000000 +0100
+++ new/jsonpatch-1.3/setup.py 2013-10-13 15:06:14.000000000 +0200
@@ -52,5 +52,11 @@
url=WEBSITE,
py_modules=MODULES,
package_data={'': ['requirements.txt']},
+ scripts=['bin/jsondiff', 'bin/jsonpatch'],
+ entry_poimts = {
+ 'console_scripts': [
+ 'jsondiff = jsondiff:main',
+ 'jsonpatch = jsonpatch:main',
+ ]},
**OPTIONS
)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpatch-1.1/tests.py new/jsonpatch-1.3/tests.py
--- old/jsonpatch-1.1/tests.py 1970-01-01 01:00:00.000000000 +0100
+++ new/jsonpatch-1.3/tests.py 2013-10-13 15:06:14.000000000 +0200
@@ -0,0 +1,358 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from __future__ import unicode_literals
+
+import json
+import doctest
+import unittest
+import jsonpatch
+import jsonpointer
+import sys
+
+
+class ApplyPatchTestCase(unittest.TestCase):
+
+ def test_apply_patch_from_string(self):
+ obj = {'foo': 'bar'}
+ patch = '[{"op": "add", "path": "/baz", "value": "qux"}]'
+ res = jsonpatch.apply_patch(obj, patch)
+ self.assertTrue(obj is not res)
+ self.assertTrue('baz' in res)
+ self.assertEqual(res['baz'], 'qux')
+
+ def test_apply_patch_to_copy(self):
+ obj = {'foo': 'bar'}
+ res = jsonpatch.apply_patch(obj, [{'op': 'add', 'path': '/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, [{'op': 'add', 'path': '/baz', 'value': 'qux'}],
+ in_place=True)
+ self.assertTrue(obj is res)
+
+ def test_add_object_key(self):
+ obj = {'foo': 'bar'}
+ res = jsonpatch.apply_patch(obj, [{'op': 'add', 'path': '/baz', 'value': 'qux'}])
+ self.assertTrue('baz' in res)
+ self.assertEqual(res['baz'], 'qux')
+
+ def test_add_array_item(self):
+ obj = {'foo': ['bar', 'baz']}
+ res = jsonpatch.apply_patch(obj, [{'op': 'add', 'path': '/foo/1', 'value': 'qux'}])
+ self.assertEqual(res['foo'], ['bar', 'qux', 'baz'])
+
+ def test_remove_object_key(self):
+ obj = {'foo': 'bar', 'baz': 'qux'}
+ res = jsonpatch.apply_patch(obj, [{'op': 'remove', 'path': '/baz'}])
+ self.assertTrue('baz' not in res)
+
+ def test_remove_array_item(self):
+ obj = {'foo': ['bar', 'qux', 'baz']}
+ res = jsonpatch.apply_patch(obj, [{'op': 'remove', 'path': '/foo/1'}])
+ self.assertEqual(res['foo'], ['bar', 'baz'])
+
+ def test_replace_object_key(self):
+ obj = {'foo': 'bar', 'baz': 'qux'}
+ res = jsonpatch.apply_patch(obj, [{'op': 'replace', 'path': '/baz', 'value': 'boo'}])
+ self.assertTrue(res['baz'], 'boo')
+
+ def test_replace_whole_document(self):
+ obj = {'foo': 'bar'}
+ res = jsonpatch.apply_patch(obj, [{'op': 'replace', 'path': '', 'value': {'baz': 'qux'}}])
+ self.assertTrue(res['baz'], 'qux')
+
+ def test_add_replace_whole_document(self):
+ obj = {'foo': 'bar'}
+ new_obj = {'baz': 'qux'}
+ res = jsonpatch.apply_patch(obj, [{'op': 'add', 'path': '', 'value': new_obj}])
+ self.assertTrue(res, new_obj)
+
+ def test_replace_array_item(self):
+ obj = {'foo': ['bar', 'qux', 'baz']}
+ res = jsonpatch.apply_patch(obj, [{'op': 'replace', 'path': '/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'}}
+ res = jsonpatch.apply_patch(obj, [{'op': 'move', 'from': '/foo/waldo',
+ 'path': '/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']}
+ res = jsonpatch.apply_patch(obj, [{'op': 'move', 'from': '/foo/1', 'path': '/foo/3'}])
+ self.assertEqual(res, {'foo': ['all', 'cows', 'eat', 'grass']})
+
+ def test_copy_object_key(self):
+ obj = {'foo': {'bar': 'baz', 'waldo': 'fred'},
+ 'qux': {'corge': 'grault'}}
+ res = jsonpatch.apply_patch(obj, [{'op': 'copy', 'from': '/foo/waldo',
+ 'path': '/qux/thud'}])
+ self.assertEqual(res, {'qux': {'thud': 'fred', 'corge': 'grault'},
+ 'foo': {'bar': 'baz', 'waldo': 'fred'}})
+
+ def test_copy_array_item(self):
+ obj = {'foo': ['all', 'grass', 'cows', 'eat']}
+ res = jsonpatch.apply_patch(obj, [{'op': 'copy', 'from': '/foo/1', 'path': '/foo/3'}])
+ self.assertEqual(res, {'foo': ['all', 'grass', 'cows', 'grass', 'eat']})
+
+
+ def test_copy_mutable(self):
+ """ test if mutable objects (dicts and lists) are copied by value """
+ obj = {'foo': [{'bar': 42}, {'baz': 3.14}], 'boo': []}
+ # copy object somewhere
+ res = jsonpatch.apply_patch(obj, [{'op': 'copy', 'from': '/foo/0', 'path': '/boo/0' }])
+ self.assertEqual(res, {'foo': [{'bar': 42}, {'baz': 3.14}], 'boo': [{'bar': 42}]})
+ # modify original object
+ res = jsonpatch.apply_patch(res, [{'op': 'add', 'path': '/foo/0/zoo', 'value': 255}])
+ # check if that didn't modify the copied object
+ self.assertEqual(res['boo'], [{'bar': 42}])
+
+
+ def test_test_success(self):
+ obj = {'baz': 'qux', 'foo': ['a', 2, 'c']}
+ jsonpatch.apply_patch(obj, [{'op': 'test', 'path': '/baz', 'value': 'qux'},
+ {'op': 'test', 'path': '/foo/1', 'value': 2}])
+
+ def test_test_whole_obj(self):
+ obj = {'baz': 1}
+ jsonpatch.apply_patch(obj, [{'op': 'test', 'path': '', 'value': obj}])
+
+
+ def test_test_error(self):
+ obj = {'bar': 'qux'}
+ self.assertRaises(jsonpatch.JsonPatchTestFailed,
+ jsonpatch.apply_patch,
+ obj, [{'op': 'test', 'path': '/bar', 'value': 'bar'}])
+
+
+ def test_test_not_existing(self):
+ obj = {'bar': 'qux'}
+ self.assertRaises(jsonpatch.JsonPatchTestFailed,
+ jsonpatch.apply_patch,
+ obj, [{'op': 'test', 'path': '/baz', 'value': 'bar'}])
+
+
+ def test_test_noval_existing(self):
+ obj = {'bar': 'qux'}
+ jsonpatch.apply_patch(obj, [{'op': 'test', 'path': '/bar'}])
+
+
+ def test_test_noval_not_existing(self):
+ obj = {'bar': 'qux'}
+ self.assertRaises(jsonpatch.JsonPatchTestFailed,
+ jsonpatch.apply_patch,
+ obj, [{'op': 'test', 'path': '/baz'}])
+
+
+ def test_test_noval_not_existing_nested(self):
+ obj = {'bar': {'qux': 2}}
+ self.assertRaises(jsonpatch.JsonPatchTestFailed,
+ jsonpatch.apply_patch,
+ obj, [{'op': 'test', 'path': '/baz/qx'}])
+
+
+ def test_unrecognized_element(self):
+ obj = {'foo': 'bar', 'baz': 'qux'}
+ res = jsonpatch.apply_patch(obj, [{'op': 'replace', 'path': '/baz', 'value': 'boo', 'foo': 'ignore'}])
+ self.assertTrue(res['baz'], 'boo')
+
+
+ def test_append(self):
+ obj = {'foo': [1, 2]}
+ res = jsonpatch.apply_patch(obj, [
+ {'op': 'add', 'path': '/foo/-', 'value': 3},
+ {'op': 'add', 'path': '/foo/-', 'value': 4},
+ ])
+ self.assertEqual(res['foo'], [1, 2, 3, 4])
+
+
+
+class EqualityTestCase(unittest.TestCase):
+
+ def test_patch_equality(self):
+ patch1 = jsonpatch.JsonPatch([{ "op": "add", "path": "/a/b/c", "value": "foo" }])
+ patch2 = jsonpatch.JsonPatch([{ "path": "/a/b/c", "op": "add", "value": "foo" }])
+ self.assertEqual(patch1, patch2)
+
+
+ def test_patch_unequal(self):
+ patch1 = jsonpatch.JsonPatch([{'op': 'test', 'path': '/test'}])
+ patch2 = jsonpatch.JsonPatch([{'op': 'test', 'path': '/test1'}])
+ self.assertNotEqual(patch1, patch2)
+
+ def test_patch_hash_equality(self):
+ patch1 = jsonpatch.JsonPatch([{ "op": "add", "path": "/a/b/c", "value": "foo" }])
+ patch2 = jsonpatch.JsonPatch([{ "path": "/a/b/c", "op": "add", "value": "foo" }])
+ self.assertEqual(hash(patch1), hash(patch2))
+
+
+ def test_patch_hash_unequal(self):
+ patch1 = jsonpatch.JsonPatch([{'op': 'test', 'path': '/test'}])
+ patch2 = jsonpatch.JsonPatch([{'op': 'test', 'path': '/test1'}])
+ self.assertNotEqual(hash(patch1), hash(patch2))
+
+
+ def test_patch_neq_other_objs(self):
+ p = [{'op': 'test', 'path': '/test'}]
+ patch = jsonpatch.JsonPatch(p)
+ # a patch will always compare not-equal to objects of other types
+ self.assertFalse(patch == p)
+ self.assertFalse(patch == None)
+
+ # also a patch operation will always compare
+ # not-equal to objects of other types
+ op = jsonpatch.PatchOperation(p[0])
+ self.assertFalse(op == p[0])
+ self.assertFalse(op == None)
+
+ def test_str(self):
+ patch_obj = [ { "op": "add", "path": "/child", "value": { "grandchild": { } } } ]
+ patch = jsonpatch.JsonPatch(patch_obj)
+
+ self.assertEqual(json.dumps(patch_obj), str(patch))
+ self.assertEqual(json.dumps(patch_obj), patch.to_string())
+
+
+
+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)
+ 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)
+ res = patch.apply(src)
+ self.assertEqual(res, dst)
+
+ def test_complex_object(self):
+ src = {'data': [
+ {'foo': 1}, {'bar': [1, 2, 3]}, {'baz': {'1': 1, '2': 2}}
+ ]}
+ dst = {'data': [
+ {'foo': [42]}, {'bar': []}, {'baz': {'boo': 'oom!'}}
+ ]}
+ patch = jsonpatch.make_patch(src, dst)
+ res = patch.apply(src)
+ self.assertEqual(res, dst)
+
+ def test_array_add_remove(self):
+ # see https://github.com/stefankoegl/python-json-patch/issues/4
+ src = {'numbers': [], 'other': [1, 5, 3, 4]}
+ dst = {'numbers': [1, 3, 4, 5], 'other': []}
+ patch = jsonpatch.make_patch(src, dst)
+ res = patch.apply(src)
+ self.assertEqual(res, dst)
+
+ def test_add_nested(self):
+ # see http://tools.ietf.org/html/draft-ietf-appsawg-json-patch-03#appendix-A.10
+ src = {"foo": "bar"}
+ patch_obj = [ { "op": "add", "path": "/child", "value": { "grandchild": { } } } ]
+ res = jsonpatch.apply_patch(src, patch_obj)
+ expected = { "foo": "bar",
+ "child": { "grandchild": { } }
+ }
+ self.assertEqual(expected, res)
+
+
+class InvalidInputTests(unittest.TestCase):
+
+ def test_missing_op(self):
+ # an "op" member is required
+ src = {"foo": "bar"}
+ patch_obj = [ { "path": "/child", "value": { "grandchild": { } } } ]
+ self.assertRaises(jsonpatch.JsonPatchException, jsonpatch.apply_patch, src, patch_obj)
+
+
+ def test_invalid_op(self):
+ # "invalid" is not a valid operation
+ src = {"foo": "bar"}
+ patch_obj = [ { "op": "invalid", "path": "/child", "value": { "grandchild": { } } } ]
+ self.assertRaises(jsonpatch.JsonPatchException, jsonpatch.apply_patch, src, patch_obj)
+
+
+class ConflictTests(unittest.TestCase):
+
+ def test_remove_indexerror(self):
+ src = {"foo": [1, 2]}
+ patch_obj = [ { "op": "remove", "path": "/foo/10"} ]
+ self.assertRaises(jsonpatch.JsonPatchConflict, jsonpatch.apply_patch, src, patch_obj)
+
+ def test_remove_keyerror(self):
+ src = {"foo": [1, 2]}
+ patch_obj = [ { "op": "remove", "path": "/foo/b"} ]
+ self.assertRaises(jsonpointer.JsonPointerException, jsonpatch.apply_patch, src, patch_obj)
+
+ def test_insert_oob(self):
+ src = {"foo": [1, 2]}
+ patch_obj = [ { "op": "add", "path": "/foo/10", "value": 1} ]
+ self.assertRaises(jsonpatch.JsonPatchConflict, jsonpatch.apply_patch, src, patch_obj)
+
+ def test_move_into_child(self):
+ src = {"foo": {"bar": {"baz": 1}}}
+ patch_obj = [ { "op": "move", "from": "/foo", "path": "/foo/bar" } ]
+ self.assertRaises(jsonpatch.JsonPatchException, jsonpatch.apply_patch, src, patch_obj)
+
+ def test_replace_oob(self):
+ src = {"foo": [1, 2]}
+ patch_obj = [ { "op": "replace", "path": "/foo/10", "value": 10} ]
+ self.assertRaises(jsonpatch.JsonPatchConflict, jsonpatch.apply_patch, src, patch_obj)
+
+ def test_replace_missing(self):
+ src = {"foo": 1}
+ patch_obj = [ { "op": "replace", "path": "/bar", "value": 10} ]
+ self.assertRaises(jsonpatch.JsonPatchConflict, jsonpatch.apply_patch, src, patch_obj)
+
+
+
+modules = ['jsonpatch']
+
+
+def get_suite():
+ suite = unittest.TestSuite()
+ suite.addTest(doctest.DocTestSuite(jsonpatch))
+ suite.addTest(unittest.makeSuite(ApplyPatchTestCase))
+ suite.addTest(unittest.makeSuite(EqualityTestCase))
+ suite.addTest(unittest.makeSuite(MakePatchTestCase))
+ suite.addTest(unittest.makeSuite(InvalidInputTests))
+ suite.addTest(unittest.makeSuite(ConflictTests))
+ return suite
+
+
+suite = get_suite()
+
+for module in modules:
+ m = __import__(module, fromlist=[module])
+ suite.addTest(doctest.DocTestSuite(m))
+
+runner = unittest.TextTestRunner(verbosity=1)
+
+result = runner.run(suite)
+
+if not result.wasSuccessful():
+ sys.exit(1)
--
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org