Hello community, here is the log from the commit of package python-jsonpointer for openSUSE:Factory checked in at 2017-11-16 14:00:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-jsonpointer (Old) and /work/SRC/openSUSE:Factory/.python-jsonpointer.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-jsonpointer" Thu Nov 16 14:00:02 2017 rev:12 rq:541911 version:1.14 Changes: -------- --- /work/SRC/openSUSE:Factory/python-jsonpointer/python-jsonpointer.changes 2017-08-14 12:36:49.342942945 +0200 +++ /work/SRC/openSUSE:Factory/.python-jsonpointer.new/python-jsonpointer.changes 2017-11-16 14:00:03.267712551 +0100 @@ -1,0 +2,6 @@ +Tue Nov 14 23:03:26 UTC 2017 - dmuel...@suse.com + +- update to 1.14: + * Support for python 3.6 + +------------------------------------------------------------------- Old: ---- jsonpointer-1.10.tar.gz New: ---- jsonpointer-1.14.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-jsonpointer.spec ++++++ --- /var/tmp/diff_new_pack.1pMgag/_old 2017-11-16 14:00:04.159680230 +0100 +++ /var/tmp/diff_new_pack.1pMgag/_new 2017-11-16 14:00:04.163680085 +0100 @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-jsonpointer -Version: 1.10 +Version: 1.14 Release: 0 Summary: Identify specific nodes in a JSON document License: BSD-3-Clause ++++++ jsonpointer-1.10.tar.gz -> jsonpointer-1.14.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/COPYING new/jsonpointer-1.14/COPYING --- old/jsonpointer-1.10/COPYING 2015-10-28 19:54:18.000000000 +0100 +++ new/jsonpointer-1.14/COPYING 1970-01-01 01:00:00.000000000 +0100 @@ -1,26 +0,0 @@ -Copyright (c) 2011 Stefan Kögl <ste...@skoegl.net> -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/jsonpointer-1.10/LICENSE.txt new/jsonpointer-1.14/LICENSE.txt --- old/jsonpointer-1.10/LICENSE.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/jsonpointer-1.14/LICENSE.txt 2017-10-30 20:49:19.000000000 +0100 @@ -0,0 +1,26 @@ +Copyright (c) 2011 Stefan Kögl <ste...@skoegl.net> +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/jsonpointer-1.10/MANIFEST.in new/jsonpointer-1.14/MANIFEST.in --- old/jsonpointer-1.10/MANIFEST.in 2015-10-28 19:54:18.000000000 +0100 +++ new/jsonpointer-1.14/MANIFEST.in 2017-10-30 20:49:19.000000000 +0100 @@ -1,4 +1,4 @@ include AUTHORS -include COPYING +include LICENSE.txt include README.md include tests.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/PKG-INFO new/jsonpointer-1.14/PKG-INFO --- old/jsonpointer-1.10/PKG-INFO 2015-10-28 20:12:49.000000000 +0100 +++ new/jsonpointer-1.14/PKG-INFO 2017-10-30 20:49:55.000000000 +0100 @@ -1,27 +1,34 @@ Metadata-Version: 1.1 Name: jsonpointer -Version: 1.10 +Version: 1.14 Summary: Identify specific nodes in a JSON document (RFC 6901) Home-page: https://github.com/stefankoegl/python-json-pointer Author: Stefan Kögl Author-email: ste...@skoegl.net License: Modified BSD License -Description: python-json-pointer [![Build Status](https://secure.travis-ci.org/stefankoegl/python-json-pointer.png?branch=master)](https://travis-ci.org/stefankoegl/python-json-pointer) [![Coverage Status](https://coveralls.io/repos/stefankoegl/python-json-pointer/badge.png?branch=master)](https://coveralls.io/r/stefankoegl/python-json-pointer?branch=master) ![Downloads](https://pypip.in/d/jsonpointer/badge.png) ![Version](https://pypip.in/v/jsonpointer/badge.png) - =================== +Description: python-json-pointer |Build Status| |Coverage Status| |Downloads| |Version| + ========================================================================== Resolve JSON Pointers in Python ------------------------------- - Library to resolve JSON Pointers according to - [RFC 6901](http://tools.ietf.org/html/rfc6901) + Library to resolve JSON Pointers according to `RFC + 6901 <http://tools.ietf.org/html/rfc6901>`__ - See Sourcecode for Examples - * Website: https://github.com/stefankoegl/python-json-pointer - * Repository: https://github.com/stefankoegl/python-json-pointer.git - * Documentation: https://python-json-pointer.readthedocs.org/ - * PyPI: https://pypi.python.org/pypi/jsonpointer - * Travis-CI: https://travis-ci.org/stefankoegl/python-json-pointer - * Coveralls: https://coveralls.io/r/stefankoegl/python-json-pointer + See Sourcecode for Examples \* Website: + https://github.com/stefankoegl/python-json-pointer \* Repository: + https://github.com/stefankoegl/python-json-pointer.git \* Documentation: + https://python-json-pointer.readthedocs.org/ \* PyPI: + https://pypi.python.org/pypi/jsonpointer \* Travis-CI: + https://travis-ci.org/stefankoegl/python-json-pointer \* Coveralls: + https://coveralls.io/r/stefankoegl/python-json-pointer + + .. |Build Status| image:: https://secure.travis-ci.org/stefankoegl/python-json-pointer.png?branch=master + :target: https://travis-ci.org/stefankoegl/python-json-pointer + .. |Coverage Status| image:: https://coveralls.io/repos/stefankoegl/python-json-pointer/badge.png?branch=master + :target: https://coveralls.io/r/stefankoegl/python-json-pointer?branch=master + .. |Downloads| image:: https://pypip.in/d/jsonpointer/badge.png + .. |Version| image:: https://pypip.in/v/jsonpointer/badge.png Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable @@ -37,6 +44,7 @@ Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Libraries diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/jsonpointer.egg-info/PKG-INFO new/jsonpointer-1.14/jsonpointer.egg-info/PKG-INFO --- old/jsonpointer-1.10/jsonpointer.egg-info/PKG-INFO 2015-10-28 20:12:49.000000000 +0100 +++ new/jsonpointer-1.14/jsonpointer.egg-info/PKG-INFO 2017-10-30 20:49:55.000000000 +0100 @@ -1,27 +1,34 @@ Metadata-Version: 1.1 Name: jsonpointer -Version: 1.10 +Version: 1.14 Summary: Identify specific nodes in a JSON document (RFC 6901) Home-page: https://github.com/stefankoegl/python-json-pointer Author: Stefan Kögl Author-email: ste...@skoegl.net License: Modified BSD License -Description: python-json-pointer [![Build Status](https://secure.travis-ci.org/stefankoegl/python-json-pointer.png?branch=master)](https://travis-ci.org/stefankoegl/python-json-pointer) [![Coverage Status](https://coveralls.io/repos/stefankoegl/python-json-pointer/badge.png?branch=master)](https://coveralls.io/r/stefankoegl/python-json-pointer?branch=master) ![Downloads](https://pypip.in/d/jsonpointer/badge.png) ![Version](https://pypip.in/v/jsonpointer/badge.png) - =================== +Description: python-json-pointer |Build Status| |Coverage Status| |Downloads| |Version| + ========================================================================== Resolve JSON Pointers in Python ------------------------------- - Library to resolve JSON Pointers according to - [RFC 6901](http://tools.ietf.org/html/rfc6901) + Library to resolve JSON Pointers according to `RFC + 6901 <http://tools.ietf.org/html/rfc6901>`__ - See Sourcecode for Examples - * Website: https://github.com/stefankoegl/python-json-pointer - * Repository: https://github.com/stefankoegl/python-json-pointer.git - * Documentation: https://python-json-pointer.readthedocs.org/ - * PyPI: https://pypi.python.org/pypi/jsonpointer - * Travis-CI: https://travis-ci.org/stefankoegl/python-json-pointer - * Coveralls: https://coveralls.io/r/stefankoegl/python-json-pointer + See Sourcecode for Examples \* Website: + https://github.com/stefankoegl/python-json-pointer \* Repository: + https://github.com/stefankoegl/python-json-pointer.git \* Documentation: + https://python-json-pointer.readthedocs.org/ \* PyPI: + https://pypi.python.org/pypi/jsonpointer \* Travis-CI: + https://travis-ci.org/stefankoegl/python-json-pointer \* Coveralls: + https://coveralls.io/r/stefankoegl/python-json-pointer + + .. |Build Status| image:: https://secure.travis-ci.org/stefankoegl/python-json-pointer.png?branch=master + :target: https://travis-ci.org/stefankoegl/python-json-pointer + .. |Coverage Status| image:: https://coveralls.io/repos/stefankoegl/python-json-pointer/badge.png?branch=master + :target: https://coveralls.io/r/stefankoegl/python-json-pointer?branch=master + .. |Downloads| image:: https://pypip.in/d/jsonpointer/badge.png + .. |Version| image:: https://pypip.in/v/jsonpointer/badge.png Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable @@ -37,6 +44,7 @@ Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Libraries diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/jsonpointer.egg-info/SOURCES.txt new/jsonpointer-1.14/jsonpointer.egg-info/SOURCES.txt --- old/jsonpointer-1.10/jsonpointer.egg-info/SOURCES.txt 2015-10-28 20:12:49.000000000 +0100 +++ new/jsonpointer-1.14/jsonpointer.egg-info/SOURCES.txt 2017-10-30 20:49:55.000000000 +0100 @@ -1,8 +1,9 @@ AUTHORS -COPYING +LICENSE.txt MANIFEST.in README.md jsonpointer.py +setup.cfg setup.py tests.py bin/jsonpointer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/jsonpointer.py new/jsonpointer-1.14/jsonpointer.py --- old/jsonpointer-1.10/jsonpointer.py 2015-10-28 20:06:33.000000000 +0100 +++ new/jsonpointer-1.14/jsonpointer.py 2017-10-30 20:49:19.000000000 +0100 @@ -11,12 +11,12 @@ # are met: # # 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. +# 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. +# 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. +# 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 @@ -30,63 +30,66 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -from __future__ import unicode_literals - """ Identify specific nodes in a JSON document (RFC 6901) """ -try: - from collections.abc import Mapping, Sequence -except ImportError: - from collections import Mapping, Sequence +from __future__ import unicode_literals # Will be parsed by setup.py to determine package metadata __author__ = 'Stefan Kögl <ste...@skoegl.net>' -__version__ = '1.10' +__version__ = '1.14' __website__ = 'https://github.com/stefankoegl/python-json-pointer' __license__ = 'Modified BSD License' try: - from urllib import unquote from itertools import izip str = unicode -except ImportError: # Python 3 - from urllib.parse import unquote +except ImportError: # Python 3 izip = zip +try: + from collections.abc import Mapping, Sequence +except ImportError: # Python 3 + from collections import Mapping, Sequence + from itertools import tee import re import copy -# array indices must not contain leading zeros, signs, spaces, decimals, etc -RE_ARRAY_INDEX=re.compile('0|[1-9][0-9]*$') - +_nothing = object() -class JsonPointerException(Exception): - pass +def set_pointer(doc, pointer, value, inplace=True): + """Resolves pointer against doc and sets the value of the target within doc. -class EndOfList(object): - """ Result of accessing element "-" of a list """ + With inplace set to true, doc is modified as long as pointer is not the + root. - def __init__(self, list_): - self.list_ = list_ + >>> obj = {'foo': {'anArray': [ {'prop': 44}], 'another prop': {'baz': 'A string' }}} + >>> set_pointer(obj, '/foo/anArray/0/prop', 55) == \ + {'foo': {'another prop': {'baz': 'A string'}, 'anArray': [{'prop': 55}]}} + True - def __repr__(self): - return '{cls}({lst})'.format(cls=self.__class__.__name__, - lst=repr(self.list_)) + >>> set_pointer(obj, '/foo/yet another prop', 'added prop') == \ + {'foo': {'another prop': {'baz': 'A string'}, 'yet another prop': 'added prop', 'anArray': [{'prop': 55}]}} + True + >>> obj = {'foo': {}} + >>> set_pointer(obj, '/foo/a%20b', 'x') == \ + {'foo': {'a%20b': 'x' }} + True + """ -_nothing = object() + pointer = JsonPointer(pointer) + return pointer.set(doc, value, inplace) def resolve_pointer(doc, pointer, default=_nothing): - """ - Resolves pointer against doc and returns the referenced object + """ Resolves pointer against doc and returns the referenced object - >>> obj = {"foo": {"anArray": [ {"prop": 44}], "another prop": {"baz": "A string" }}} + >>> obj = {'foo': {'anArray': [ {'prop': 44}], 'another prop': {'baz': 'A string' }}, 'a%20b': 1, 'c d': 2} >>> resolve_pointer(obj, '') == obj True @@ -94,10 +97,10 @@ >>> resolve_pointer(obj, '/foo') == obj['foo'] True - >>> resolve_pointer(obj, '/foo/another%20prop') == obj['foo']['another prop'] + >>> resolve_pointer(obj, '/foo/another prop') == obj['foo']['another prop'] True - >>> resolve_pointer(obj, '/foo/another%20prop/baz') == obj['foo']['another prop']['baz'] + >>> resolve_pointer(obj, '/foo/another prop/baz') == obj['foo']['another prop']['baz'] True >>> resolve_pointer(obj, '/foo/anArray/0') == obj['foo']['anArray'][0] @@ -106,50 +109,83 @@ >>> resolve_pointer(obj, '/some/path', None) == None True + >>> resolve_pointer(obj, '/a b', None) == None + True + + >>> resolve_pointer(obj, '/a%20b') == 1 + True + + >>> resolve_pointer(obj, '/c d') == 2 + True + + >>> resolve_pointer(obj, '/c%20d', None) == None + True """ pointer = JsonPointer(pointer) return pointer.resolve(doc, default) -def set_pointer(doc, pointer, value, inplace=True): - """ - Resolves pointer against doc and sets the value of the target within doc. - With inplace set to true, doc is modified as long as pointer is not the - root. +def pairwise(iterable): + """ Transforms a list to a list of tuples of adjacent items - >>> obj = {"foo": {"anArray": [ {"prop": 44}], "another prop": {"baz": "A string" }}} + s -> (s0,s1), (s1,s2), (s2, s3), ... - >>> set_pointer(obj, '/foo/anArray/0/prop', 55) == \ - {'foo': {'another prop': {'baz': 'A string'}, 'anArray': [{'prop': 55}]}} - True + >>> list(pairwise([])) + [] - >>> set_pointer(obj, '/foo/yet%20another%20prop', 'added prop') == \ - {'foo': {'another prop': {'baz': 'A string'}, 'yet another prop': 'added prop', 'anArray': [{'prop': 55}]}} - True + >>> list(pairwise([1])) + [] + >>> list(pairwise([1, 2, 3, 4])) + [(1, 2), (2, 3), (3, 4)] """ + a, b = tee(iterable) + for _ in b: + break + return izip(a, b) - pointer = JsonPointer(pointer) - return pointer.set(doc, value, inplace) + +class JsonPointerException(Exception): + pass + + +class EndOfList(object): + """Result of accessing element "-" of a list""" + + def __init__(self, list_): + self.list_ = list_ + + def __repr__(self): + return '{cls}({lst})'.format(cls=self.__class__.__name__, + lst=repr(self.list_)) class JsonPointer(object): - """ A JSON Pointer that can reference parts of an JSON document """ + """A JSON Pointer that can reference parts of an JSON document""" + + # Array indices must not contain: + # leading zeros, signs, spaces, decimals, etc + _RE_ARRAY_INDEX = re.compile('0|[1-9][0-9]*$') + _RE_INVALID_ESCAPE = re.compile('(~[^01]|~$)') def __init__(self, pointer): + + # validate escapes + invalid_escape = self._RE_INVALID_ESCAPE.search(pointer) + if invalid_escape: + raise JsonPointerException('Found invalid escape {0}'.format( + invalid_escape.group())) + parts = pointer.split('/') if parts.pop(0) != '': raise JsonPointerException('location must starts with /') - parts = map(unquote, parts) - parts = [part.replace('~1', '/') for part in parts] - parts = [part.replace('~0', '~') for part in parts] + parts = [unescape(part) for part in parts] self.parts = parts - def to_last(self, doc): - """ Resolves ptr until the last step, returns (sub-doc, last-step) """ + """Resolves ptr until the last step, returns (sub-doc, last-step)""" if not self.parts: return doc, None @@ -159,7 +195,6 @@ return doc, self.get_part(doc, self.parts[-1]) - def resolve(self, doc, default=_nothing): """Resolves the pointer against doc and returns the referenced object""" @@ -175,11 +210,10 @@ return doc - get = resolve def set(self, doc, value, inplace=True): - """ Resolve the pointer against the doc and replace the target with value. """ + """Resolve the pointer against the doc and replace the target with value.""" if len(self.parts) == 0: if inplace: @@ -195,7 +229,7 @@ return doc def get_part(self, doc, part): - """ Returns the next step in the correct type """ + """Returns the next step in the correct type""" if isinstance(doc, Mapping): return part @@ -205,18 +239,19 @@ if part == '-': return part - if not RE_ARRAY_INDEX.match(str(part)): - raise JsonPointerException("'%s' is not a valid list index" % (part, )) + if not self._RE_ARRAY_INDEX.match(str(part)): + raise JsonPointerException("'%s' is not a valid sequence index" % part) return int(part) elif hasattr(doc, '__getitem__'): - # Allow indexing via ducktyping if the target has defined __getitem__ + # Allow indexing via ducktyping + # if the target has defined __getitem__ return part else: raise JsonPointerException("Document '%s' does not support indexing, " - "must be dict/list or support __getitem__" % type(doc)) + "must be mapping/sequence or support __getitem__" % type(doc)) def walk(self, doc, part): @@ -224,17 +259,9 @@ part = self.get_part(doc, part) - assert (type(doc) in (dict, list) or hasattr(doc, '__getitem__')), "invalid document type %s" % (type(doc),) - - if isinstance(doc, Mapping): - try: - return doc[part] - - except KeyError: - raise JsonPointerException("member '%s' not found in %s" % (part, doc)) - - elif isinstance(doc, Sequence): + assert hasattr(doc, '__getitem__'), "invalid document type %s" % (type(doc),) + if isinstance(doc, Sequence): if part == '-': return EndOfList(doc) @@ -244,72 +271,61 @@ except IndexError: raise JsonPointerException("index '%s' is out of bounds" % (part, )) - else: - # Object supports __getitem__, assume custom indexing + # Else the object is a mapping or supports __getitem__(so assume custom indexing) + try: return doc[part] + except KeyError: + raise JsonPointerException("member '%s' not found in %s" % (part, doc)) + + def contains(self, ptr): - """Returns True if self contains the given ptr""" + """ Returns True if self contains the given ptr """ return self.parts[:len(ptr.parts)] == ptr.parts def __contains__(self, item): - """Returns True if self contains the given ptr""" + """ Returns True if self contains the given ptr """ return self.contains(item) @property def path(self): - """ Returns the string representation of the pointer + """Returns the string representation of the pointer >>> ptr = JsonPointer('/~0/0/~1').path == '/~0/0/~1' """ - parts = [part.replace('~', '~0') for part in self.parts] - parts = [part.replace('/', '~1') for part in parts] + parts = [escape(part) for part in self.parts] return ''.join('/' + part for part in parts) def __eq__(self, other): - """ compares a pointer to another object + """Compares a pointer to another object Pointers can be compared by comparing their strings (or splitted strings), because no two different parts can point to the same - structure in an object (eg no different number representations) """ + structure in an object (eg no different number representations) + """ if not isinstance(other, JsonPointer): return False return self.parts == other.parts - def __hash__(self): return hash(tuple(self.parts)) @classmethod def from_parts(cls, parts): - """ Constructs a JsonPointer from a list of (unescaped) paths + """Constructs a JsonPointer from a list of (unescaped) paths >>> JsonPointer.from_parts(['a', '~', '/', 0]).path == '/a/~0/~1/0' True """ - parts = [str(part) for part in parts] - parts = [part.replace('~', '~0') for part in parts] - parts = [part.replace('/', '~1') for part in parts] + parts = [escape(str(part)) for part in parts] ptr = cls(''.join('/' + part for part in parts)) return ptr +def escape(s): + return s.replace('~', '~0').replace('/', '~1') -def pairwise(iterable): - """ s -> (s0,s1), (s1,s2), (s2, s3), ... - - >>> list(pairwise([])) - [] - - >>> list(pairwise([1])) - [] - - >>> list(pairwise([1, 2, 3, 4])) - [(1, 2), (2, 3), (3, 4)] - """ - a, b = tee(iterable) - for _ in b: - break - return izip(a, b) +def unescape(s): + return s.replace('~1', '/').replace('~0', '~') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/setup.cfg new/jsonpointer-1.14/setup.cfg --- old/jsonpointer-1.10/setup.cfg 2015-10-28 20:12:49.000000000 +0100 +++ new/jsonpointer-1.14/setup.cfg 2017-10-30 20:49:55.000000000 +0100 @@ -1,5 +1,7 @@ +[bdist_wheel] +universal = 1 + [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/setup.py new/jsonpointer-1.14/setup.py --- old/jsonpointer-1.10/setup.py 2015-10-28 20:05:06.000000000 +0100 +++ new/jsonpointer-1.14/setup.py 2017-10-30 20:49:19.000000000 +0100 @@ -48,6 +48,7 @@ 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development :: Libraries', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/jsonpointer-1.10/tests.py new/jsonpointer-1.14/tests.py --- old/jsonpointer-1.10/tests.py 2015-10-28 19:54:18.000000000 +0100 +++ new/jsonpointer-1.14/tests.py 2017-10-30 20:49:19.000000000 +0100 @@ -10,6 +10,7 @@ from jsonpointer import resolve_pointer, EndOfList, JsonPointerException, \ JsonPointer, set_pointer + class SpecificationTests(unittest.TestCase): """ Tests all examples from the JSON Pointer specification """ @@ -73,6 +74,7 @@ new_ptr = JsonPointer.from_parts(parts) self.assertEqual(ptr, new_ptr) + class ComparisonTests(unittest.TestCase): def setUp(self): @@ -108,7 +110,6 @@ self.assertTrue(self.ptr1 in self.ptr1) self.assertFalse(self.ptr3 in self.ptr1) - class WrongInputTests(unittest.TestCase): def test_no_start_slash(self): @@ -125,6 +126,12 @@ doc = [0, 1, 2] self.assertRaises(JsonPointerException, resolve_pointer, doc, '/10') + def test_trailing_escape(self): + self.assertRaises(JsonPointerException, JsonPointer, '/foo/bar~') + + def test_invalid_escape(self): + self.assertRaises(JsonPointerException, JsonPointer, '/foo/bar~2') + class ToLastTests(unittest.TestCase): @@ -192,42 +199,52 @@ self.assertRaises(JsonPointerException, set_pointer, doc, "", 9) + class AltTypesTests(unittest.TestCase): - def test_alttypes(self): - JsonPointer.alttypes = True + class Node(object): + def __init__(self, name, parent=None): + self.name = name + self.parent = parent + self.left = None + self.right = None + + def set_left(self, node): + node.parent = self + self.left = node + + def set_right(self, node): + node.parent = self + self.right = node + + def __getitem__(self, key): + if key == 'left': + return self.left + if key == 'right': + return self.right + + raise KeyError("Only left and right supported") + + def __setitem__(self, key, val): + if key == 'left': + return self.set_left(val) + if key == 'right': + return self.set_right(val) + + raise KeyError("Only left and right supported: %s" % key) + + class mdict(object): + def __init__(self, d): + self._d = d + def __getitem__(self, item): + return self._d[item] - class Node(object): - def __init__(self, name, parent=None): - self.name = name - self.parent = parent - self.left = None - self.right = None - - def set_left(self, node): - node.parent = self - self.left = node - - def set_right(self, node): - node.parent = self - self.right = node - - def __getitem__(self, key): - if key == 'left': - return self.left - if key == 'right': - return self.right - - raise KeyError("Only left and right supported") - - def __setitem__(self, key, val): - if key == 'left': - return self.set_left(val) - if key == 'right': - return self.set_right(val) + mdict = mdict({'root': {'1': {'2': '3'}}}) + Node = Node - raise KeyError("Only left and right supported: %s" % key) + def test_alttypes(self): + Node = self.Node root = Node('root') root.set_left(Node('a')) @@ -249,6 +266,39 @@ set_pointer(root, '/left/right', Node('AB')) self.assertEqual(resolve_pointer(root, '/left/right').name, 'AB') + def test_mock_dict_sanity(self): + doc = self.mdict + default = None + + # TODO: Generate this automatically for any given object + path_to_expected_value = { + '/root/1': {'2': '3'}, + '/root': {'1': {'2': '3'}}, + '/root/1/2': '3', + } + + for path, expected_value in iter(path_to_expected_value.items()): + self.assertEqual(resolve_pointer(doc, path, default), expected_value) + + def test_mock_dict_returns_default(self): + doc = self.mdict + default = None + + path_to_expected_value = { + '/foo': default, + '/x/y/z/d': default + } + + for path, expected_value in iter(path_to_expected_value.items()): + self.assertEqual(resolve_pointer(doc, path, default), expected_value) + + def test_mock_dict_raises_key_error(self): + doc = self.mdict + self.assertRaises(JsonPointerException, resolve_pointer, doc, '/foo') + self.assertRaises(JsonPointerException, resolve_pointer, doc, '/root/1/2/3/4') + + + suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(SpecificationTests)) suite.addTest(unittest.makeSuite(ComparisonTests))