Skip to content

Commit

Permalink
Raise an error when invalid sort keys are provided by the client
Browse files Browse the repository at this point in the history
  • Loading branch information
kinow committed Mar 8, 2021
1 parent 07c7f5c commit 87f07b3
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 9 deletions.
22 changes: 13 additions & 9 deletions cylc/flow/network/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,19 @@ def sort_elements(elements, args):
"""Sort iterable of elements by given attribute."""
sort_args = args.get('sort')
if sort_args and elements:
sort_keys = [
key
for key in [to_snake_case(k) for k in sort_args.keys]
if hasattr(elements[0], key)
]
if sort_keys:
elements.sort(
key=attrgetter(*sort_keys),
reverse=sort_args.reverse)
keys = [
key for key in [to_snake_case(k) for k in sort_args.keys]]
if not keys:
raise ValueError('You must provide at least one key to sort')
keys_not_in_schema = [
key for key in keys if not hasattr(elements[0], key)]
if keys_not_in_schema:
raise ValueError(f'''The following sort keys are not in the
schema: {', '.join(keys_not_in_schema)}''')
# sort using the keys provided
elements.sort(
key=attrgetter(*keys),
reverse=sort_args.reverse)
return elements


Expand Down
84 changes: 84 additions & 0 deletions tests/unit/network/test_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
# Copyright (C) NIWA & British Crown (Met Office) & Contributors.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from dataclasses import dataclass
from inspect import isclass

import pytest

from cylc.flow.network.schema import sort_elements, SortArgs


@dataclass
class DummyObject:
value: str


@pytest.mark.parametrize(
'elements,sort_args,expected_result',
[
# sort asc by key
(
[DummyObject(1), DummyObject(3), DummyObject(2)],
{
'keys': ['value'],
'reverse': False # NOTE: GraphQL ensures reverse is not None!
},
[DummyObject(1), DummyObject(2), DummyObject(3)]
),
# sort desc by key
(
[DummyObject(1), DummyObject(3), DummyObject(2)],
{
'keys': ['value'],
'reverse': True
},
[DummyObject(3), DummyObject(2), DummyObject(1)]
),
# raise error when no keys given
(
[DummyObject(1), DummyObject(3), DummyObject(2)],
{
'keys': [],
'reverse': True
},
ValueError
),
# raise error when any of the keys given are not in the schema
(
[DummyObject(1), DummyObject(3), DummyObject(2)],
{
'keys': ['value', 'river_name'],
'reverse': True
},
ValueError
)
]
)
def test_sort_args(elements, sort_args, expected_result):
"""Test the sorting function used by the schema."""
sort = SortArgs()
sort.keys = sort_args['keys']
sort.reverse = sort_args['reverse']
args = {
'sort': sort
}
if isclass(expected_result):
with pytest.raises(expected_result):
sort_elements(elements, args)
else:
sort_elements(elements, args)
assert elements == expected_result

0 comments on commit 87f07b3

Please sign in to comment.