From a419a51132bb1c4b8ac9d7f4ac7d714ea3ed8bcd Mon Sep 17 00:00:00 2001 From: Mehdi Abaakouk Date: Tue, 4 Aug 2015 18:09:08 +0200 Subject: [PATCH] Add `len` extention to the json parser This extends the jsonpath_rw parser with customisation for gabbi. This first one is `len` --- gabbi/case.py | 4 +-- gabbi/gabbits_intercept/data.yaml | 1 + gabbi/json_parser.py | 56 +++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 gabbi/json_parser.py diff --git a/gabbi/case.py b/gabbi/case.py index 0d1a326..b557347 100644 --- a/gabbi/case.py +++ b/gabbi/case.py @@ -29,11 +29,11 @@ import unittest from unittest import case -import jsonpath_rw import six from six.moves.urllib import parse as urlparse import wsgi_intercept +from gabbi import json_parser from gabbi import utils REPLACERS = [ @@ -193,7 +193,7 @@ def extract_json_path_value(data, path): The input data is a Python datastructre, not a JSON string. """ - path_expr = jsonpath_rw.parse(path) + path_expr = json_parser.parse(path) matches = [match.value for match in path_expr.find(data)] try: return matches[0] diff --git a/gabbi/gabbits_intercept/data.yaml b/gabbi/gabbits_intercept/data.yaml index 9a63743..53829d1 100644 --- a/gabbi/gabbits_intercept/data.yaml +++ b/gabbi/gabbits_intercept/data.yaml @@ -25,6 +25,7 @@ tests: response_json_paths: $[0]: 1 $[1]: 2 + $.`len`: 2 - name: load json file url: / diff --git a/gabbi/json_parser.py b/gabbi/json_parser.py new file mode 100644 index 0000000..cd4a088 --- /dev/null +++ b/gabbi/json_parser.py @@ -0,0 +1,56 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import jsonpath_rw + + +class Len(jsonpath_rw.JSONPath): + """The JSONPath referring to the len of the current object. + + Concrete syntax is '`len`'. + """ + + def find(self, datum): + datum = jsonpath_rw.DatumInContext.wrap(datum) + try: + value = len(datum.value) + except TypeError: + return [] + else: + return [jsonpath_rw.DatumInContext(value, + context=None, + path=Len())] + + def __eq__(self, other): + return isinstance(other, Len) + + def __str__(self): + return '`len`' + + def __repr__(self): + return 'Len()' + + +class GabbiJsonPathParser(jsonpath_rw.parser.JsonPathParser): + """Custom gabbi LALR-parser for JsonPath""" + + def p_jsonpath_named_operator(self, p): + "jsonpath : NAMED_OPERATOR" + if p[1] == 'len': + p[0] = Len() + else: + super(GabbiJsonPathParser, self).p_jsonpath_named_operator(p) + + +def parse(path): + return GabbiJsonPathParser().parse(path)