From ade5bf398d2066a10edcd9956ae491b7c08e3050 Mon Sep 17 00:00:00 2001 From: Jonathan Stewmon Date: Mon, 21 Mar 2016 09:50:18 -0500 Subject: [PATCH 1/3] implemented items, to_object and zip functions --- jmespath/compat.py | 4 ++++ jmespath/functions.py | 17 ++++++++++++++++- tests/compliance/functions.json | 31 ++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/jmespath/compat.py b/jmespath/compat.py index 2ed0fe78..e73cb61a 100644 --- a/jmespath/compat.py +++ b/jmespath/compat.py @@ -15,7 +15,9 @@ def __new__(cls, name, this_bases, d): if PY2: text_type = unicode string_type = basestring + iteritems = dict.iteritems from itertools import izip_longest as zip_longest + from itertools import imap as map def with_str_method(cls): """Class decorator that handles __str__ compat between py2 and py3.""" @@ -50,6 +52,8 @@ def get_methods(cls): else: text_type = str string_type = str + iteritems = dict.items + map = map from itertools import zip_longest def with_str_method(cls): diff --git a/jmespath/functions.py b/jmespath/functions.py index ab922822..7f2b8a41 100644 --- a/jmespath/functions.py +++ b/jmespath/functions.py @@ -2,8 +2,11 @@ import json from jmespath import exceptions +from jmespath.compat import get_methods +from jmespath.compat import iteritems +from jmespath.compat import map from jmespath.compat import string_type as STRING_TYPE -from jmespath.compat import get_methods, with_metaclass +from jmespath.compat import with_metaclass # python types -> jmespath types @@ -184,6 +187,10 @@ def _func_to_array(self, arg): else: return [arg] + @signature({'types': ['array']}) + def _func_to_object(self, pairs): + return dict(pairs) + @signature({'types': []}) def _func_to_string(self, arg): if isinstance(arg, STRING_TYPE): @@ -280,6 +287,10 @@ def _func_sort(self, arg): def _func_sum(self, arg): return sum(arg) + @signature({'types': ['object']}) + def _func_items(self, arg): + return list(map(list, iteritems(arg))) + @signature({"types": ['object']}) def _func_keys(self, arg): # To be consistent with .values() @@ -339,6 +350,10 @@ def _func_max_by(self, array, expref): 'min_by') return max(array, key=keyfunc) + @signature({'types': ['array'], 'variadic': True}) + def _func_zip(self, *arguments): + return list(map(list, zip(*arguments))) + def _create_key_func(self, expref, allowed_types, function_name): def keyfunc(x): result = expref.visit(expref.expression, x) diff --git a/tests/compliance/functions.json b/tests/compliance/functions.json index a749dda2..a13cf88e 100644 --- a/tests/compliance/functions.json +++ b/tests/compliance/functions.json @@ -12,6 +12,7 @@ "empty_list": [], "empty_hash": {}, "objects": {"foo": "bar", "bar": "baz"}, + "pairs": [["a", "first"], ["b", "second"], ["c", "third"]], "null_key": null }, "cases": [ @@ -175,6 +176,18 @@ "expression": "floor(str)", "error": "invalid-type" }, + { + "expression": "items(objects)", + "result": [["foo", "bar"], ["bar", "baz"]] + }, + { + "expression": "items(empty_hash)", + "result": [] + }, + { + "expression": "items(numbers)", + "error": "invalid-type" + }, { "expression": "length('abc')", "result": 3 @@ -189,7 +202,7 @@ }, { "expression": "length(@)", - "result": 12 + "result": 13 }, { "expression": "length(strings[0])", @@ -479,6 +492,10 @@ "expression": "to_array(false)", "result": [false] }, + { + "expression": "to_object(pairs)", + "result": {"a": "first", "b": "second", "c": "third"} + }, { "expression": "to_string('foo')", "result": "foo" @@ -575,6 +592,18 @@ "expression": "not_null()", "error": "invalid-arity" }, + { + "expression": "zip(strings, numbers)", + "result": [["a", -1], ["b", 3], ["c", 4]] + }, + { + "expression": "zip(strings, numbers, decimals)", + "result": [["a", -1, 1.01], ["b", 3, 1.2], ["c", 4, -1.5]] + }, + { + "expression": "zip(str)", + "error": "invalid-type" + }, { "description": "function projection on single arg function", "expression": "numbers[].to_string(@)", From b1709c3d4f7cc1fb6a27f66a54a86ba4810a05ef Mon Sep 17 00:00:00 2001 From: Jonathan Stewmon Date: Mon, 21 Mar 2016 12:46:29 -0500 Subject: [PATCH 2/3] sort items result to make result predictable --- tests/compliance/functions.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/compliance/functions.json b/tests/compliance/functions.json index a13cf88e..3d31d759 100644 --- a/tests/compliance/functions.json +++ b/tests/compliance/functions.json @@ -177,8 +177,8 @@ "error": "invalid-type" }, { - "expression": "items(objects)", - "result": [["foo", "bar"], ["bar", "baz"]] + "expression": "sort_by(items(objects), &[0])", + "result": [["bar", "baz"], ["foo", "bar"]] }, { "expression": "items(empty_hash)", From bc92aae461a74824f7112beb22832d34b925ec3e Mon Sep 17 00:00:00 2001 From: Jonathan Stewmon Date: Thu, 15 Sep 2016 10:04:06 -0500 Subject: [PATCH 3/3] rename to_object to from_items --- jmespath/functions.py | 8 ++++---- tests/compliance/functions.json | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/jmespath/functions.py b/jmespath/functions.py index 7f2b8a41..2edf5ef5 100644 --- a/jmespath/functions.py +++ b/jmespath/functions.py @@ -187,10 +187,6 @@ def _func_to_array(self, arg): else: return [arg] - @signature({'types': ['array']}) - def _func_to_object(self, pairs): - return dict(pairs) - @signature({'types': []}) def _func_to_string(self, arg): if isinstance(arg, STRING_TYPE): @@ -291,6 +287,10 @@ def _func_sum(self, arg): def _func_items(self, arg): return list(map(list, iteritems(arg))) + @signature({'types': ['array']}) + def _func_from_items(self, items): + return dict(items) + @signature({"types": ['object']}) def _func_keys(self, arg): # To be consistent with .values() diff --git a/tests/compliance/functions.json b/tests/compliance/functions.json index 3d31d759..149cb88e 100644 --- a/tests/compliance/functions.json +++ b/tests/compliance/functions.json @@ -12,7 +12,7 @@ "empty_list": [], "empty_hash": {}, "objects": {"foo": "bar", "bar": "baz"}, - "pairs": [["a", "first"], ["b", "second"], ["c", "third"]], + "items": [["a", "first"], ["b", "second"], ["c", "third"]], "null_key": null }, "cases": [ @@ -188,6 +188,10 @@ "expression": "items(numbers)", "error": "invalid-type" }, + { + "expression": "from_items(items)", + "result": {"a": "first", "b": "second", "c": "third"} + }, { "expression": "length('abc')", "result": 3 @@ -492,10 +496,6 @@ "expression": "to_array(false)", "result": [false] }, - { - "expression": "to_object(pairs)", - "result": {"a": "first", "b": "second", "c": "third"} - }, { "expression": "to_string('foo')", "result": "foo"