From 244bed3e827166dcffaf5fec5abb16736fe9d8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20K=C3=B6gl?= Date: Sun, 10 Sep 2017 19:40:12 +0200 Subject: Revert optimizations due to compatibility issues with jsonpatch --- .travis.yml | 34 ++++++------ jsonpointer.py | 148 +++++++++++++++++++++------------------------------ requirements-dev.txt | 2 +- 3 files changed, 77 insertions(+), 107 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7c737e4..389dc95 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,21 @@ language: python python: -- '2.6' -- '2.7' -- '3.3' -- '3.4' -- '3.5' -- '3.6' -- pypy -- pypy3 + - "2.6" + - "2.7" + - "3.3" + - "3.4" + - "3.5" + - "3.6" + - "pypy" + - "pypy3" + install: -- travis_retry pip install coveralls + - travis_retry pip install coveralls + script: -- coverage run --source=jsonpointer tests.py + - coverage run --source=jsonpointer tests.py + after_script: -- coveralls + - coveralls + sudo: false -deploy: - provider: pypi - user: skoegl - password: - secure: g+81X6n8etmQQ9ZbxoSx/OoXsDHBwgoBlesnrYP4RBHLoez3wBbI2w1tu7Uce2irWMmkoFIpQHguXxOqHVoGzx18s1njp9/1fyrJ3f6gYbcQrUnwRFjYGcIc0TUSTI9dLpnRKCp9glNwIvPx7n6/5avZIaXveLU9j4DIm1xA1ZM= - on: - tags: true - distributions: sdist bdist_wheel diff --git a/jsonpointer.py b/jsonpointer.py index 5d41b58..9a6a613 100644 --- a/jsonpointer.py +++ b/jsonpointer.py @@ -36,22 +36,25 @@ from __future__ import unicode_literals # Will be parsed by setup.py to determine package metadata __author__ = 'Stefan Kögl ' -__version__ = '1.11' +__version__ = '1.10' __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 + 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 @@ -108,6 +111,26 @@ def resolve_pointer(doc, pointer, default=_nothing): return pointer.resolve(doc, default) +def pairwise(iterable): + """ Transforms a list to a list of tuples of adjacent items + + 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) + + class JsonPointerException(Exception): pass @@ -145,62 +168,23 @@ class JsonPointer(object): if not self.parts: return doc, None - doc = self.resolve(doc, parts=self.parts[:-1]) - last = self.parts[-1] - ptype = type(doc) - if ptype == dict: - pass - elif ptype == list or isinstance(doc, Sequence): - if not self._RE_ARRAY_INDEX.match(str(last)): - raise JsonPointerException( - "'%s' is not a valid list index" % (last, ) - ) - last = int(last) - - return doc, last - - def resolve(self, doc, default=_nothing, parts=None): - """ Resolves the pointer against doc, returns the referenced object """ - if parts is None: - parts = self.parts + for part in self.parts[:-1]: + doc = self.walk(doc, part) - try: - for part in parts: - ptype = type(doc) - if ptype == dict: - doc = doc[part] - elif ptype == list or isinstance(doc, Sequence): - if part == '-': - doc = EndOfList(doc) - else: - if not self._RE_ARRAY_INDEX.match(str(part)): - raise JsonPointerException( - "'%s' is not a valid list index" % (part, ) - ) - doc = doc[int(part)] + 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""" + + for part in self.parts: + + try: + doc = self.walk(doc, part) + except JsonPointerException: + if default is _nothing: + raise else: - doc = doc[part] - except KeyError: - if default is not _nothing: - return default - raise JsonPointerException( - "member '%s' not found in %s" % (part, doc) - ) - - except IndexError: - if default is not _nothing: - return default - raise JsonPointerException( - "index '%s' is out of bounds" % (part, ) - ) - - except TypeError: - if default is not _nothing: - return default - raise JsonPointerException( - "Document '%s' does not support indexing, must be dict/list " - "or support __getitem__" % type(doc) - ) + return default return doc @@ -225,19 +209,17 @@ class JsonPointer(object): def get_part(self, doc, part): """Returns the next step in the correct type""" - # Optimize for common cases of doc being a dict or list, but not a - # sub-class (because isinstance() is far slower) - ptype = type(doc) - if ptype == dict: + if isinstance(doc, Mapping): return part - if ptype == list or isinstance(doc, Sequence): + + elif isinstance(doc, Sequence): + if part == '-': return part if not self._RE_ARRAY_INDEX.match(str(part)): - raise JsonPointerException( - "'%s' is not a valid list index" % (part, ) - ) + raise JsonPointerException("'%s' is not a valid sequence index" % part) + return int(part) elif hasattr(doc, '__getitem__'): @@ -246,42 +228,34 @@ class JsonPointer(object): return part else: - raise JsonPointerException( - "Document '%s' does not support indexing, must be " - "mapping/sequence or support __getitem__" % type(doc) - ) + raise JsonPointerException("Document '%s' does not support indexing, " + "must be mapping/sequence or support __getitem__" % type(doc)) + def walk(self, doc, part): """ Walks one step in doc and returns the referenced part """ part = self.get_part(doc, part) - if part == '-' and isinstance(doc, Sequence): - return EndOfList(doc) + assert hasattr(doc, '__getitem__'), "invalid document type %s" % (type(doc),) - try: - return doc[part] + if isinstance(doc, Sequence): + if part == '-': + return EndOfList(doc) - except KeyError: - raise JsonPointerException( - "member '%s' not found in %s" % (part, doc) - ) + try: + return doc[part] - except IndexError: - raise JsonPointerException( - "index '%s' is out of bounds" % (part, ) - ) + except IndexError: + raise JsonPointerException("index '%s' is out of bounds" % (part, )) - except TypeError: - raise JsonPointerException( - "Document '%s' does not support indexing, must be dict/list " - "or support __getitem__" % type(doc) - ) + # 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) - ) + raise JsonPointerException("member '%s' not found in %s" % (part, doc)) + def contains(self, ptr): """ Returns True if self contains the given ptr """ diff --git a/requirements-dev.txt b/requirements-dev.txt index 51e335b..fd0fd6c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,2 @@ wheel -pandoc==1.0.0b2 +pandoc==1.0.0-alpha.3 -- cgit v1.2.1