Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions jmespath/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,14 +316,19 @@ def _func_sort_by(self, array, expref):
# either a string of a number. We then create a key function
# that validates that type, which requires that remaining array
# elements resolve to the same type as the first element.
# The type check is done on the resolved key, not on the array
# element, because that's the value the signature constrains.
keyfunc = self._create_key_func(expref,
['number', 'string'],
'sort_by')
required_key = keyfunc(array[0])
required_type = self._convert_to_jmespath_type(
type(expref.visit(expref.expression, array[0])).__name__)
type(required_key).__name__)
if required_type not in ['number', 'string']:
raise exceptions.JMESPathTypeError(
'sort_by', array[0], required_type, ['string', 'number'])
keyfunc = self._create_key_func(expref,
[required_type],
'sort_by')
'sort_by', required_key, required_type,
['string', 'number'])
keyfunc = self._create_key_func(expref, [required_type], 'sort_by')
return list(sorted(array, key=keyfunc))

@signature({'types': ['array']}, {'types': ['expref']})
Expand Down
10 changes: 10 additions & 0 deletions tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,13 @@ def test_variadic_is_pluralized(self):
self.assertEqual(
str(exception),
'Expected at least 1 argument for function not_null(), received 0')

def test_sort_by_reports_the_resolved_key_in_type_errors(self):
# The spec defines sort_by as sort_by(array, expression->number|
# expression->string), so the value that has the invalid type is the
# value the expression resolved to, not the array element it was
# resolved against. min_by/max_by already report the resolved key.
with self.assertRaises(exceptions.JMESPathTypeError) as e:
jmespath.search('sort_by(@, &k)', [{'k': [1, 2]}])
self.assertIn('invalid type for value: [1, 2]', str(e.exception))
self.assertIn('received: "array"', str(e.exception))