Skip to content

Commit 0e01247

Browse files
author
Michael Brewer
committed
fix(parser): apigw check_message_id and tests
Changes: - Add some more unit tests - Fix bug with `check_message_id` not looking in the RequestContext - Add more mypy coverage - Add pragma: no cover
1 parent a768b68 commit 0e01247

File tree

6 files changed

+43
-24
lines changed

6 files changed

+43
-24
lines changed

aws_lambda_powertools/tracing/tracer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ def decorate(event, context, **kwargs):
335335
# see #465
336336
@overload
337337
def capture_method(self, method: "AnyCallableT") -> "AnyCallableT":
338-
...
338+
... # pragma: no cover
339339

340340
@overload
341341
def capture_method(
@@ -344,7 +344,7 @@ def capture_method(
344344
capture_response: Optional[bool] = None,
345345
capture_error: Optional[bool] = None,
346346
) -> Callable[["AnyCallableT"], "AnyCallableT"]:
347-
...
347+
... # pragma: no cover
348348

349349
def capture_method(
350350
self,

aws_lambda_powertools/utilities/feature_toggles/appconfig_fetcher.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Any, Dict, Optional
2+
from typing import Any, Dict, Optional, cast
33

44
from botocore.config import Config
55

@@ -56,11 +56,15 @@ def get_json_configuration(self) -> Dict[str, Any]:
5656
parsed JSON dictionary
5757
"""
5858
try:
59-
return self._conf_store.get(
60-
name=self.configuration_name,
61-
transform=TRANSFORM_TYPE,
62-
max_age=self._cache_seconds,
63-
) # parse result conf as JSON, keep in cache for self.max_age seconds
59+
# parse result conf as JSON, keep in cache for self.max_age seconds
60+
return cast(
61+
dict,
62+
self._conf_store.get(
63+
name=self.configuration_name,
64+
transform=TRANSFORM_TYPE,
65+
max_age=self._cache_seconds,
66+
),
67+
)
6468
except (GetParameterError, TransformParameterError) as exc:
6569
error_str = f"unable to get AWS AppConfig configuration file, exception={str(exc)}"
6670
self._logger.error(error_str)

aws_lambda_powertools/utilities/idempotency/persistence/dynamodb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def _update_record(self, data_record: DataRecord):
154154
"ExpressionAttributeNames": expression_attr_names,
155155
}
156156

157-
self.table.update_item(**kwargs)
157+
self.table.update_item(**kwargs) # type: ignore
158158

159159
def _delete_record(self, data_record: DataRecord) -> None:
160160
logger.debug(f"Deleting record for idempotency key: {data_record.idempotency_key}")

aws_lambda_powertools/utilities/parameters/dynamodb.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""
44

55

6-
from typing import Any, Dict, Optional
6+
from typing import Dict, Optional
77

88
import boto3
99
from boto3.dynamodb.conditions import Key
@@ -141,11 +141,6 @@ class DynamoDBProvider(BaseProvider):
141141
c Parameter value c
142142
"""
143143

144-
table: Any = None
145-
key_attr = None
146-
sort_attr = None
147-
value_attr = None
148-
149144
def __init__(
150145
self,
151146
table_name: str,
@@ -183,7 +178,7 @@ def _get(self, name: str, **sdk_options) -> str:
183178
# Explicit arguments will take precedence over keyword arguments
184179
sdk_options["Key"] = {self.key_attr: name}
185180

186-
return self.table.get_item(**sdk_options)["Item"][self.value_attr]
181+
return str(self.table.get_item(**sdk_options)["Item"][self.value_attr])
187182

188183
def _get_multiple(self, path: str, **sdk_options) -> Dict[str, str]:
189184
"""
@@ -209,4 +204,4 @@ def _get_multiple(self, path: str, **sdk_options) -> Dict[str, str]:
209204
response = self.table.query(**sdk_options)
210205
items.extend(response.get("Items", []))
211206

212-
return {item[self.sort_attr]: item[self.value_attr] for item in items}
207+
return {str(item[self.sort_attr]): str(item[self.value_attr]) for item in items}

aws_lambda_powertools/utilities/parser/models/apigw.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ class APIGatewayEventRequestContext(BaseModel):
6868
routeKey: Optional[str]
6969
operationName: Optional[str]
7070

71+
@root_validator()
72+
def check_message_id(cls, values):
73+
message_id, event_type = values.get("messageId"), values.get("eventType")
74+
if message_id is not None and event_type != "MESSAGE":
75+
raise TypeError("messageId is available only when the `eventType` is `MESSAGE`")
76+
return values
77+
7178

7279
class APIGatewayProxyEventModel(BaseModel):
7380
version: Optional[str]
@@ -83,10 +90,3 @@ class APIGatewayProxyEventModel(BaseModel):
8390
stageVariables: Optional[Dict[str, str]]
8491
isBase64Encoded: bool
8592
body: str
86-
87-
@root_validator()
88-
def check_message_id(cls, values):
89-
message_id, event_type = values.get("messageId"), values.get("eventType")
90-
if message_id is not None and event_type != "MESSAGE":
91-
raise TypeError("messageId is available only when the `eventType` is `MESSAGE`")
92-
return values

tests/functional/parser/test_apigw.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import pytest
2+
from pydantic import ValidationError
3+
14
from aws_lambda_powertools.utilities.parser import envelopes, event_parser
25
from aws_lambda_powertools.utilities.parser.models import APIGatewayProxyEventModel
36
from aws_lambda_powertools.utilities.typing import LambdaContext
@@ -100,3 +103,20 @@ def test_apigw_event():
100103
assert request_context.operationName is None
101104
assert identity.apiKey is None
102105
assert identity.apiKeyId is None
106+
107+
108+
def test_apigw_event_with_invalid_websocket_request():
109+
# GIVEN an event with an eventType != MESSAGE and has a messageId
110+
event = {
111+
"requestContext": {
112+
"eventType": "DISCONNECT",
113+
"messageId": "messageId",
114+
},
115+
}
116+
117+
# WHEN calling event_parser with APIGatewayProxyEventModel
118+
with pytest.raises(ValidationError) as err:
119+
handle_apigw_event(event, LambdaContext())
120+
121+
# THEN raise TypeError for invalid event
122+
assert "messageId is available only when the `eventType` is `MESSAGE`" in str(err.value)

0 commit comments

Comments
 (0)