From c0c59ba6582f1e0bbdfa78be03248f063d9c4416 Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Wed, 9 Aug 2023 11:38:06 -0400 Subject: [PATCH 1/9] implementation --- linodecli/api_request.py | 20 +++++++++++++++++++- linodecli/baked/operation.py | 17 +++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index 891e35329..2694d5605 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -150,6 +150,18 @@ 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 = None + if parsed_args_dict['order_by'] is not None: + order_by = parsed_args_dict['order_by'] + order = 'asc' if parsed_args_dict['order'] == None else parsed_args_dict['order'] + + del parsed_args_dict['order_by'] + del parsed_args_dict['order'] + + print(order_by, order) + + # The "+and" list to be used in the filter header filter_list = [] @@ -162,7 +174,13 @@ def _build_filter_header( filter_list.extend(new_filters) if len(filter_list) > 0: - return json.dumps({"+and": filter_list}) + if order_by is None: + return json.dumps({"+and": filter_list}) + else: + return json.dumps({"+and": filter_list, "+order_by": order_by, "+order": order}) + else: + if order_by is not None: + return json.dumps({"+order_by": order_by, "+order": order}) return None diff --git a/linodecli/baked/operation.py b/linodecli/baked/operation.py index 5a8b02674..9bac223b0 100644 --- a/linodecli/baked/operation.py +++ b/linodecli/baked/operation.py @@ -315,8 +315,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( @@ -332,6 +334,21 @@ def parse_args( type=expected_type, 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.") + + order_group = parser.add_mutually_exclusive_group() + + order_group.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 From 50774126102711ca93cf244b0cabd13491d8c193 Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Wed, 9 Aug 2023 11:56:12 -0400 Subject: [PATCH 2/9] cleaning up code --- linodecli/api_request.py | 5 +---- linodecli/baked/operation.py | 10 +++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index 2694d5605..010dfef54 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -151,7 +151,7 @@ def _build_filter_header( del parsed_args_dict[p.name] # check for order_by and order - order_by = None + order_by, order = None, None if parsed_args_dict['order_by'] is not None: order_by = parsed_args_dict['order_by'] order = 'asc' if parsed_args_dict['order'] == None else parsed_args_dict['order'] @@ -159,9 +159,6 @@ def _build_filter_header( del parsed_args_dict['order_by'] del parsed_args_dict['order'] - print(order_by, order) - - # The "+and" list to be used in the filter header filter_list = [] diff --git a/linodecli/baked/operation.py b/linodecli/baked/operation.py index 9bac223b0..a5866e03d 100644 --- a/linodecli/baked/operation.py +++ b/linodecli/baked/operation.py @@ -6,6 +6,7 @@ import json import platform import re +import sys from getpass import getpass from os import environ, path @@ -339,11 +340,10 @@ def parse_args( parser.add_argument( "--order_by", choices=filterable_args, - help="Attribute to order the results by - must be filterable.") - - order_group = parser.add_mutually_exclusive_group() - - order_group.add_argument( + help="Attribute to order the results by - must be filterable.", + required='--order' in sys.argv) + + parser.add_argument( "--order", choices=['asc', 'desc'], default='asc', From 22bbf4d2b413b1755f99a9c729ef40b82d00e60c Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Wed, 9 Aug 2023 12:37:12 -0400 Subject: [PATCH 3/9] linting and tests --- linodecli/api_request.py | 5 ++--- linodecli/baked/operation.py | 8 ++++---- tests/unit/test_api_request.py | 1 + 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index 010dfef54..ffe36ce21 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -154,7 +154,7 @@ def _build_filter_header( order_by, order = None, None if parsed_args_dict['order_by'] is not None: order_by = parsed_args_dict['order_by'] - order = 'asc' if parsed_args_dict['order'] == None else parsed_args_dict['order'] + order = 'asc' if parsed_args_dict['order'] is None else parsed_args_dict['order'] del parsed_args_dict['order_by'] del parsed_args_dict['order'] @@ -173,8 +173,7 @@ def _build_filter_header( if len(filter_list) > 0: if order_by is None: return json.dumps({"+and": filter_list}) - else: - return json.dumps({"+and": filter_list, "+order_by": order_by, "+order": order}) + return json.dumps({"+and": filter_list, "+order_by": order_by, "+order": order}) else: if order_by is not None: return json.dumps({"+order_by": order_by, "+order": order}) diff --git a/linodecli/baked/operation.py b/linodecli/baked/operation.py index a5866e03d..cc8fe99f9 100644 --- a/linodecli/baked/operation.py +++ b/linodecli/baked/operation.py @@ -335,17 +335,17 @@ def parse_args( type=expected_type, 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) - + required='--order' in sys.argv) + parser.add_argument( "--order", - choices=['asc', 'desc'], + choices=['asc', 'desc'], default='asc', help="Either “asc” or “desc”. Defaults to “asc”. Requires +order_by") diff --git a/tests/unit/test_api_request.py b/tests/unit/test_api_request.py index 52a30ecff..dcc6b1d02 100644 --- a/tests/unit/test_api_request.py +++ b/tests/unit/test_api_request.py @@ -109,6 +109,7 @@ def test_build_filter_header(self, list_operation): SimpleNamespace( filterable_result="bar", filterable_list_result=["foo", "bar"], + order_by=None, ), ) From f9d23602fd2a210af3443e8323e416fa09dc2e4f Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Wed, 9 Aug 2023 13:14:56 -0400 Subject: [PATCH 4/9] more linting --- linodecli/api_request.py | 7 +++---- tests/unit/test_api_request.py | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index ffe36ce21..0bfbaf37c 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -155,7 +155,7 @@ def _build_filter_header( if parsed_args_dict['order_by'] is not None: order_by = parsed_args_dict['order_by'] order = 'asc' if parsed_args_dict['order'] is None else parsed_args_dict['order'] - + del parsed_args_dict['order_by'] del parsed_args_dict['order'] @@ -174,9 +174,8 @@ def _build_filter_header( if order_by is None: return json.dumps({"+and": filter_list}) return json.dumps({"+and": filter_list, "+order_by": order_by, "+order": order}) - else: - if order_by is not None: - return json.dumps({"+order_by": order_by, "+order": order}) + elif order_by is not None: + return json.dumps({"+order_by": order_by, "+order": order}) return None diff --git a/tests/unit/test_api_request.py b/tests/unit/test_api_request.py index dcc6b1d02..84c390d13 100644 --- a/tests/unit/test_api_request.py +++ b/tests/unit/test_api_request.py @@ -110,6 +110,7 @@ def test_build_filter_header(self, list_operation): filterable_result="bar", filterable_list_result=["foo", "bar"], order_by=None, + order=None ), ) From d9d67765687f829e469e2160e2752746c4e8e558 Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Wed, 9 Aug 2023 13:17:50 -0400 Subject: [PATCH 5/9] lint again --- linodecli/api_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index 0bfbaf37c..04717cef3 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -174,7 +174,7 @@ def _build_filter_header( if order_by is None: return json.dumps({"+and": filter_list}) return json.dumps({"+and": filter_list, "+order_by": order_by, "+order": order}) - elif order_by is not None: + if order_by is not None: return json.dumps({"+order_by": order_by, "+order": order}) return None From 147c65cf9740c6bc15a60487140c9e64a98b5b9f Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Wed, 9 Aug 2023 13:22:45 -0400 Subject: [PATCH 6/9] reformatting --- linodecli/api_request.py | 18 ++++++++++++------ linodecli/baked/operation.py | 15 ++++++++------- tests/unit/test_api_request.py | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index 04717cef3..dd8f2310e 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -152,12 +152,16 @@ def _build_filter_header( # check for order_by and order order_by, order = None, None - if parsed_args_dict['order_by'] is not None: - order_by = parsed_args_dict['order_by'] - order = 'asc' if parsed_args_dict['order'] is None else parsed_args_dict['order'] + if parsed_args_dict["order_by"] is not None: + order_by = parsed_args_dict["order_by"] + order = ( + "asc" + if parsed_args_dict["order"] is None + else parsed_args_dict["order"] + ) - del parsed_args_dict['order_by'] - del parsed_args_dict['order'] + del parsed_args_dict["order_by"] + del parsed_args_dict["order"] # The "+and" list to be used in the filter header filter_list = [] @@ -173,7 +177,9 @@ def _build_filter_header( if len(filter_list) > 0: if order_by is None: return json.dumps({"+and": filter_list}) - return json.dumps({"+and": filter_list, "+order_by": order_by, "+order": order}) + return json.dumps( + {"+and": filter_list, "+order_by": order_by, "+order": order} + ) if order_by is not None: return json.dumps({"+order_by": order_by, "+order": order}) diff --git a/linodecli/baked/operation.py b/linodecli/baked/operation.py index cc8fe99f9..88ed4deed 100644 --- a/linodecli/baked/operation.py +++ b/linodecli/baked/operation.py @@ -338,17 +338,18 @@ def parse_args( # Add --order_by and --order argument parser.add_argument( - "--order_by", + "--order_by", choices=filterable_args, help="Attribute to order the results by - must be filterable.", - required='--order' in sys.argv) + 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") - + "--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 diff --git a/tests/unit/test_api_request.py b/tests/unit/test_api_request.py index 84c390d13..741bc13fc 100644 --- a/tests/unit/test_api_request.py +++ b/tests/unit/test_api_request.py @@ -110,7 +110,7 @@ def test_build_filter_header(self, list_operation): filterable_result="bar", filterable_list_result=["foo", "bar"], order_by=None, - order=None + order=None, ), ) From 586a2c6b87865a53ab6f45b6375f8faf595e4bff Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Wed, 9 Aug 2023 16:42:37 -0400 Subject: [PATCH 7/9] code optimization and more tests --- linodecli/api_request.py | 26 ++++--------- tests/unit/test_api_request.py | 71 ++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 19 deletions(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index dd8f2310e..c415c92b9 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -151,17 +151,8 @@ def _build_filter_header( del parsed_args_dict[p.name] # check for order_by and order - order_by, order = None, None - if parsed_args_dict["order_by"] is not None: - order_by = parsed_args_dict["order_by"] - order = ( - "asc" - if parsed_args_dict["order"] is None - else parsed_args_dict["order"] - ) - - del parsed_args_dict["order_by"] - del parsed_args_dict["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 = [] @@ -174,16 +165,13 @@ def _build_filter_header( new_filters = [{k: j} for j in v] if isinstance(v, list) else [{k: v}] filter_list.extend(new_filters) + result = {} if len(filter_list) > 0: - if order_by is None: - return json.dumps({"+and": filter_list}) - return json.dumps( - {"+and": filter_list, "+order_by": order_by, "+order": order} - ) + result["+and"] = filter_list if order_by is not None: - return json.dumps({"+order_by": order_by, "+order": order}) - - return 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: diff --git a/tests/unit/test_api_request.py b/tests/unit/test_api_request.py index 741bc13fc..61b942aa2 100644 --- a/tests/unit/test_api_request.py +++ b/tests/unit/test_api_request.py @@ -127,6 +127,77 @@ def test_build_filter_header(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") From d5ad5b7f6c74deffcf48c24543b14f1c12b448c7 Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Thu, 10 Aug 2023 09:17:29 -0400 Subject: [PATCH 8/9] linting --- linodecli/api_request.py | 8 ++++---- tests/unit/test_api_request.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/linodecli/api_request.py b/linodecli/api_request.py index d8f66c0c8..0fe00f657 100644 --- a/linodecli/api_request.py +++ b/linodecli/api_request.py @@ -167,10 +167,10 @@ def _build_filter_header( result = {} if len(filter_list) > 0: - if len(filter_list) == 1: - result = filter_list[0] - else: - result["+and"] = filter_list + 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 diff --git a/tests/unit/test_api_request.py b/tests/unit/test_api_request.py index a0be4f3cb..08138af9b 100644 --- a/tests/unit/test_api_request.py +++ b/tests/unit/test_api_request.py @@ -126,7 +126,7 @@ def test_build_filter_header(self, list_operation): ) == result ) - + def test_build_filter_header_single(self, list_operation): result = api_request._build_filter_header( list_operation, From b99577a4ec4b34017af5c46eb35a07558ad18156 Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Mon, 14 Aug 2023 11:47:42 -0400 Subject: [PATCH 9/9] linting --- linodecli/baked/operation.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/linodecli/baked/operation.py b/linodecli/baked/operation.py index 3fc4da9b4..31f1f5607 100644 --- a/linodecli/baked/operation.py +++ b/linodecli/baked/operation.py @@ -346,17 +346,17 @@ def _add_args_filter(self, parser): ) # 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, + "--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", + "--order", + choices=["asc", "desc"], + default="asc", + help="Either “asc” or “desc”. Defaults to “asc”. Requires +order_by", ) def _add_args_post_put(self, parser) -> List[Tuple[str, str]]: