From cf183c465c97d2f9e05af83ccc1a92bd58e8d495 Mon Sep 17 00:00:00 2001 From: Tony Sherman Date: Fri, 23 Feb 2024 21:08:17 -0500 Subject: [PATCH 1/6] add function to get multi-value query string params by name --- .../utilities/data_classes/common.py | 30 +++++++++++++++++++ .../data_classes/shared_functions.py | 29 ++++++++++++++++-- tests/unit/test_data_classes.py | 19 ++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index 067706140fd..ff69ca33bec 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -7,6 +7,7 @@ from aws_lambda_powertools.shared.headers_serializer import BaseHeadersSerializer from aws_lambda_powertools.utilities.data_classes.shared_functions import ( get_header_value, + get_multi_value_query_string_values, get_query_string_value, ) @@ -103,6 +104,10 @@ def headers(self) -> Dict[str, str]: def query_string_parameters(self) -> Optional[Dict[str, str]]: return self.get("queryStringParameters") + @property + def multi_value_query_string_parameters(self) -> Optional[Dict[str, List[str]]]: + return self.get("multiValueQueryStringParameters") + @property def resolved_query_string_parameters(self) -> Dict[str, List[str]]: """ @@ -184,6 +189,31 @@ def get_query_string_value(self, name: str, default_value: Optional[str] = None) default_value=default_value, ) + def get_multi_value_query_string_values( + self, + name: str, + default_values: Optional[List[str]] = None, + ) -> Optional[List[str]]: + """Get multi-value query string parameter values by name + + Parameters + ---------- + name: str + Multi-Value query string parameter name + default_values: List[str], optional + Default values is no values are found by name + Returns + ------- + List[str], optional + List of query string values + + """ + return get_multi_value_query_string_values( + multi_value_query_string_parameters=self.multi_value_query_string_parameters, + name=name, + default_values=default_values, + ) + @overload def get_header_value( self, diff --git a/aws_lambda_powertools/utilities/data_classes/shared_functions.py b/aws_lambda_powertools/utilities/data_classes/shared_functions.py index 594ea35bea7..83cebadff09 100644 --- a/aws_lambda_powertools/utilities/data_classes/shared_functions.py +++ b/aws_lambda_powertools/utilities/data_classes/shared_functions.py @@ -1,7 +1,7 @@ from __future__ import annotations import base64 -from typing import Any +from typing import Any, Dict def base64_decode(value: str) -> str: @@ -63,7 +63,7 @@ def get_header_value( def get_query_string_value( - query_string_parameters: dict[str, str] | None, + query_string_parameters: Dict[str, str] | None, name: str, default_value: str | None = None, ) -> str | None: @@ -84,3 +84,28 @@ def get_query_string_value( """ params = query_string_parameters return default_value if params is None else params.get(name, default_value) + + +def get_multi_value_query_string_values( + multi_value_query_string_parameters: Dict[str, list[str]] | None, + name: str, + default_values: list[str] | None = None, +) -> list[str] | None: + """ + Retrieves the values of a multi-value string parameters specified by the given name. + + Parameters + ---------- + name: str + The name of the query string parameter to retrieve. + default_value: list[str], optional + The default value to return if the parameter is not found. Defaults to None. + + Returns + ------- + List[str]. optional + The values of the query string parameter if found, or the default values if not found. + """ + + params = multi_value_query_string_parameters + return default_values if not params else params.get(name, default_values) diff --git a/tests/unit/test_data_classes.py b/tests/unit/test_data_classes.py index c810f653f5b..1c0dcb903db 100644 --- a/tests/unit/test_data_classes.py +++ b/tests/unit/test_data_classes.py @@ -259,6 +259,25 @@ def test_base_proxy_event_get_query_string_value(): assert value is None +def test_base_proxy_event_get_multi_value_query_string_values(): + default_values = ["default_1", "default_2"] + set_values = ["value_1", "value_2"] + + event = BaseProxyEvent({}) + values = event.get_multi_value_query_string_values("test", default_values) + assert values == default_values + + event._data["multiValueQueryStringParameters"] = {"test": set_values} + values = event.get_multi_value_query_string_values("test", default_values) + assert values == set_values + + values = event.get_multi_value_query_string_values("unknown", default_values) + assert values == default_values + + values = event.get_multi_value_query_string_values("unknown") + assert values is None + + def test_base_proxy_event_get_header_value(): default_value = "default" set_value = "value" From 2d53499da629c4c807545cf5fe2c5bd5e307b303 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Mon, 26 Feb 2024 12:53:08 +0100 Subject: [PATCH 2/6] chore: return list only Signed-off-by: Heitor Lessa --- aws_lambda_powertools/utilities/data_classes/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index ff69ca33bec..fab90dd9ee4 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -193,7 +193,7 @@ def get_multi_value_query_string_values( self, name: str, default_values: Optional[List[str]] = None, - ) -> Optional[List[str]]: + ) ->List[str]: """Get multi-value query string parameter values by name Parameters From ab5f09ea79ede58a94a2f27640f30a46b7a3b2d3 Mon Sep 17 00:00:00 2001 From: Heitor Lessa Date: Mon, 26 Feb 2024 12:54:10 +0100 Subject: [PATCH 3/6] chore: return dict or empty list as default instead Signed-off-by: Heitor Lessa --- aws_lambda_powertools/utilities/data_classes/common.py | 4 ++-- .../utilities/data_classes/shared_functions.py | 8 +++++--- tests/unit/test_data_classes.py | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/common.py b/aws_lambda_powertools/utilities/data_classes/common.py index fab90dd9ee4..41fbe5cd0de 100644 --- a/aws_lambda_powertools/utilities/data_classes/common.py +++ b/aws_lambda_powertools/utilities/data_classes/common.py @@ -105,8 +105,8 @@ def query_string_parameters(self) -> Optional[Dict[str, str]]: return self.get("queryStringParameters") @property - def multi_value_query_string_parameters(self) -> Optional[Dict[str, List[str]]]: - return self.get("multiValueQueryStringParameters") + def multi_value_query_string_parameters(self) -> Dict[str, List[str]]: + return self.get("multiValueQueryStringParameters") or {} @property def resolved_query_string_parameters(self) -> Dict[str, List[str]]: diff --git a/aws_lambda_powertools/utilities/data_classes/shared_functions.py b/aws_lambda_powertools/utilities/data_classes/shared_functions.py index 83cebadff09..43a3aad281b 100644 --- a/aws_lambda_powertools/utilities/data_classes/shared_functions.py +++ b/aws_lambda_powertools/utilities/data_classes/shared_functions.py @@ -90,7 +90,7 @@ def get_multi_value_query_string_values( multi_value_query_string_parameters: Dict[str, list[str]] | None, name: str, default_values: list[str] | None = None, -) -> list[str] | None: +) -> list[str]: """ Retrieves the values of a multi-value string parameters specified by the given name. @@ -107,5 +107,7 @@ def get_multi_value_query_string_values( The values of the query string parameter if found, or the default values if not found. """ - params = multi_value_query_string_parameters - return default_values if not params else params.get(name, default_values) + default = default_values or [] + params = multi_value_query_string_parameters or {} + + return params.get(name) or default diff --git a/tests/unit/test_data_classes.py b/tests/unit/test_data_classes.py index 1c0dcb903db..c8f0c1fc932 100644 --- a/tests/unit/test_data_classes.py +++ b/tests/unit/test_data_classes.py @@ -275,7 +275,7 @@ def test_base_proxy_event_get_multi_value_query_string_values(): assert values == default_values values = event.get_multi_value_query_string_values("unknown") - assert values is None + assert values == [] def test_base_proxy_event_get_header_value(): From b60265be42ffcc462d9b44a9e2bb5dcc6b0192df Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 26 Feb 2024 12:58:35 +0100 Subject: [PATCH 4/6] chore: fix return type in ALB multi-query Signed-off-by: heitorlessa --- aws_lambda_powertools/utilities/data_classes/alb_event.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/alb_event.py b/aws_lambda_powertools/utilities/data_classes/alb_event.py index 1ec2535850b..a1ee3424a94 100644 --- a/aws_lambda_powertools/utilities/data_classes/alb_event.py +++ b/aws_lambda_powertools/utilities/data_classes/alb_event.py @@ -32,8 +32,8 @@ def request_context(self) -> ALBEventRequestContext: return ALBEventRequestContext(self._data) @property - def multi_value_query_string_parameters(self) -> Optional[Dict[str, List[str]]]: - return self.get("multiValueQueryStringParameters") + def multi_value_query_string_parameters(self) -> Dict[str, List[str]]: + return self.get("multiValueQueryStringParameters") or {} @property def resolved_query_string_parameters(self) -> Dict[str, List[str]]: From ac0a95eb83e9bc7d4101c6a0b50dd2dcb431c021 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 26 Feb 2024 13:02:45 +0100 Subject: [PATCH 5/6] docs: update query string example --- examples/event_handler_rest/src/accessing_request_details.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/event_handler_rest/src/accessing_request_details.py b/examples/event_handler_rest/src/accessing_request_details.py index 9929b601db0..037b76daa66 100644 --- a/examples/event_handler_rest/src/accessing_request_details.py +++ b/examples/event_handler_rest/src/accessing_request_details.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import List, Optional import requests from requests import Response @@ -20,6 +20,9 @@ def get_todos(): # alternatively _: Optional[str] = app.current_event.query_string_parameters.get("id") + # or multi-value query string parameters; ?category="red"&?category="blue" + _: List[str] = app.current_event.get_multi_value_query_string_values(name="category") + # Payload _: Optional[str] = app.current_event.body # raw str | None From 1326926ddaabe6a1d6e45f77373deeb2f8b8a890 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Mon, 26 Feb 2024 13:07:24 +0100 Subject: [PATCH 6/6] chore: adjust test on default value ALB --- tests/unit/data_classes/test_alb_event.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unit/data_classes/test_alb_event.py b/tests/unit/data_classes/test_alb_event.py index c55af8e91ef..47048ab9407 100644 --- a/tests/unit/data_classes/test_alb_event.py +++ b/tests/unit/data_classes/test_alb_event.py @@ -11,7 +11,9 @@ def test_alb_event(): assert parsed_event.path == raw_event["path"] assert parsed_event.query_string_parameters == raw_event["queryStringParameters"] assert parsed_event.headers == raw_event["headers"] - assert parsed_event.multi_value_query_string_parameters == raw_event.get("multiValueQueryStringParameters") + + assert parsed_event.multi_value_query_string_parameters == raw_event.get("multiValueQueryStringParameters", {}) + assert parsed_event.multi_value_headers == raw_event.get("multiValueHeaders") assert parsed_event.body == raw_event["body"] assert parsed_event.is_base64_encoded == raw_event["isBase64Encoded"]