Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support --order and --order_by for list operations #506

Merged
23 changes: 14 additions & 9 deletions linodecli/api_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ def _build_filter_header(
if p.name in parsed_args_dict:
del parsed_args_dict[p.name]

# check for order_by and order
order_by = parsed_args_dict.pop("order_by")
order = parsed_args_dict.pop("order") or "asc"

# The "+and" list to be used in the filter header
filter_list = []

Expand All @@ -161,15 +165,16 @@ def _build_filter_header(
new_filters = [{k: j} for j in v] if isinstance(v, list) else [{k: v}]
filter_list.extend(new_filters)

if len(filter_list) < 1:
return None

return json.dumps(
# Only use +and if there are multiple attributes to filter on
{"+and": filter_list}
if len(filter_list) > 1
else filter_list[0]
)
result = {}
if len(filter_list) > 0:
if len(filter_list) == 1:
result = filter_list[0]
else:
result["+and"] = filter_list
if order_by is not None:
result["+order_by"] = order_by
result["+order"] = order
return json.dumps(result) if len(result) > 0 else None


def _build_request_url(ctx, operation, parsed_args) -> str:
Expand Down
18 changes: 18 additions & 0 deletions linodecli/baked/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import platform
import re
import sys
from getpass import getpass
from os import environ, path

Expand Down Expand Up @@ -315,8 +316,10 @@ def parse_args(

if self.method == "get":
# build args for filtering
filterable_args = []
for attr in self.response_model.attrs:
if attr.filterable:
filterable_args.append(attr.name)
expected_type = TYPES[attr.datatype]
if expected_type == list:
parser.add_argument(
Expand All @@ -333,6 +336,21 @@ def parse_args(
metavar=attr.name,
)

# Add --order_by and --order argument
parser.add_argument(
"--order_by",
choices=filterable_args,
help="Attribute to order the results by - must be filterable.",
required="--order" in sys.argv,
)

parser.add_argument(
"--order",
choices=["asc", "desc"],
default="asc",
help="Either “asc” or “desc”. Defaults to “asc”. Requires +order_by",
)

elif self.method in ("post", "put"):
# build args for body JSON
for arg in self.args:
Expand Down
77 changes: 77 additions & 0 deletions tests/unit/test_api_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ def test_build_filter_header(self, list_operation):
SimpleNamespace(
filterable_result="bar",
filterable_list_result=["foo", "bar"],
order_by=None,
order=None,
amisiorek-akamai marked this conversation as resolved.
Show resolved Hide resolved
),
)

Expand All @@ -130,6 +132,8 @@ def test_build_filter_header_single(self, list_operation):
list_operation,
SimpleNamespace(
filterable_result="bar",
order_by=None,
order=None,
),
)

Expand All @@ -145,6 +149,8 @@ def test_build_filter_header_single_list(self, list_operation):
list_operation,
SimpleNamespace(
filterable_list_result=["foo", "bar"],
order_by=None,
order=None,
),
)

Expand All @@ -160,6 +166,77 @@ def test_build_filter_header_single_list(self, list_operation):
== result
)

def test_build_filter_header_order_by(self, list_operation):
result = api_request._build_filter_header(
list_operation,
SimpleNamespace(
filterable_result="bar",
filterable_list_result=["foo", "bar"],
order_by="baz",
order=None,
),
)

assert (
json.dumps(
{
"+and": [
{"filterable_result": "bar"},
{"filterable_list_result": "foo"},
{"filterable_list_result": "bar"},
],
"+order_by": "baz",
"+order": "asc",
}
)
== result
)

def test_build_filter_header_order(self, list_operation):
result = api_request._build_filter_header(
list_operation,
SimpleNamespace(
filterable_result="bar",
filterable_list_result=["foo", "bar"],
order_by="baz",
order="desc",
),
)

assert (
json.dumps(
{
"+and": [
{"filterable_result": "bar"},
{"filterable_list_result": "foo"},
{"filterable_list_result": "bar"},
],
"+order_by": "baz",
"+order": "desc",
}
)
== result
)

def test_build_filter_header_only_order(self, list_operation):
result = api_request._build_filter_header(
list_operation,
SimpleNamespace(
order_by="baz",
order="desc",
),
)

assert (
json.dumps(
{
"+order_by": "baz",
"+order": "desc",
}
)
== result
)

def test_do_request_get(self, mock_cli, list_operation):
mock_response = Mock(status_code=200, reason="OK")

Expand Down