Skip to content

Commit e4b8dc4

Browse files
committed
fix tests to match implementation
1 parent cd6329f commit e4b8dc4

File tree

3 files changed

+19
-77
lines changed

3 files changed

+19
-77
lines changed

aws_lambda_powertools/utilities/parser/models/dynamodb.py

Lines changed: 7 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
from datetime import datetime
22
from typing import Any, Dict, List, Optional, Type, Union
33

4-
from pydantic import BaseModel
4+
from pydantic import BaseModel, field_validator
55

66
from aws_lambda_powertools.shared.dynamodb_deserializer import TypeDeserializer
77
from aws_lambda_powertools.utilities.parser.types import Literal
88

9+
_DESERIALIZER = TypeDeserializer()
910

10-
class DynamoDBStreamChangedRecordModel(BaseModel):
11-
_deserializer = TypeDeserializer()
1211

12+
class DynamoDBStreamChangedRecordModel(BaseModel):
1313
ApproximateCreationDateTime: Optional[datetime] = None
14-
Keys: Dict[str, Dict[str, Any]]
14+
Keys: Dict[str, Any]
1515
NewImage: Optional[Union[Dict[str, Any], Type[BaseModel], BaseModel]] = None
1616
OldImage: Optional[Union[Dict[str, Any], Type[BaseModel], BaseModel]] = None
1717
SequenceNumber: str
@@ -29,66 +29,9 @@ class DynamoDBStreamChangedRecordModel(BaseModel):
2929
# raise TypeError("DynamoDB streams model failed validation, missing both new & old stream images") # noqa: ERA001,E501
3030
# return values # noqa: ERA001
3131

32-
def __init__(self, **data: Any):
33-
"""DynamoDBStreamChangedRecordModel constructor
34-
Parameters
35-
----------
36-
data: Any
37-
Represents the model data
38-
"""
39-
super().__init__(**data)
40-
self._deserializer = TypeDeserializer()
41-
42-
def _deserialize_dynamodb_dict(self, key: str) -> Optional[Dict[str, Any]]:
43-
"""Deserialize DynamoDB records available in `Keys`, `NewImage`, and `OldImage`
44-
45-
Parameters
46-
----------
47-
key : str
48-
DynamoDB key (e.g., Keys, NewImage, or OldImage)
49-
50-
Returns
51-
-------
52-
Optional[Dict[str, Any]]
53-
Deserialized records in Python native types
54-
"""
55-
dynamodb_dict = getattr(self, key)
56-
if dynamodb_dict is None:
57-
return None
58-
59-
return {k: self._deserializer.deserialize(v) for k, v in dynamodb_dict.items()}
60-
61-
@property
62-
def approximate_creation_date_time(self) -> Optional[datetime]:
63-
"""The approximate date and time when the stream record was created, in UNIX epoch time format."""
64-
item = self.ApproximateCreationDateTime
65-
return None if item is None else item
66-
67-
@property
68-
def keys(self) -> Optional[Dict[str, Any]]:
69-
"""The primary key attribute(s) for the DynamoDB item that was modified."""
70-
return self._deserialize_dynamodb_dict("Keys")
71-
72-
@property
73-
def new_image(self) -> Optional[Dict[str, Any]]:
74-
"""The item in the DynamoDB table as it appeared after it was modified."""
75-
return self._deserialize_dynamodb_dict("NewImage")
76-
77-
@property
78-
def old_image(self) -> Optional[Dict[str, Any]]:
79-
"""The item in the DynamoDB table as it appeared before it was modified."""
80-
return self._deserialize_dynamodb_dict("OldImage")
81-
82-
@property
83-
def sequence_number(self) -> Optional[str]:
84-
"""The sequence number of the stream record."""
85-
return self.SequenceNumber
86-
87-
@property
88-
def size_bytes(self) -> Optional[int]:
89-
"""The size of the stream record, in bytes."""
90-
item = self.SizeBytes
91-
return None if item is None else int(item)
32+
@field_validator("Keys", "NewImage", "OldImage", mode="before")
33+
def deserialize_field(cls, value):
34+
return {k: _DESERIALIZER.deserialize(v) for k, v in value.items()}
9235

9336

9437
class UserIdentity(BaseModel):

tests/unit/parser/schemas.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Dict, List, Optional
1+
from typing import List, Optional
22

33
from pydantic import BaseModel
44

@@ -13,12 +13,11 @@
1313
SqsModel,
1414
SqsRecordModel,
1515
)
16-
from aws_lambda_powertools.utilities.parser.types import Literal
1716

1817

1918
class MyDynamoBusiness(BaseModel):
20-
Message: Dict[Literal["S"], str]
21-
Id: Dict[Literal["N"], int]
19+
Message: str
20+
Id: int
2221

2322

2423
class MyDynamoScheme(DynamoDBStreamChangedRecordModel):

tests/unit/parser/test_dynamodb.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@ def test_dynamo_db_stream_trigger_event():
2121

2222
new_image = parserd_event[0]["NewImage"]
2323
new_image_raw = raw_event["Records"][0]["dynamodb"]["NewImage"]
24-
assert new_image.Message["S"] == new_image_raw["Message"]["S"]
25-
assert new_image.Id["N"] == float(new_image_raw["Id"]["N"])
24+
assert new_image.Message == new_image_raw["Message"]["S"]
25+
assert new_image.Id == float(new_image_raw["Id"]["N"])
2626

2727
# record index 1
2828
old_image = parserd_event[1]["OldImage"]
2929
old_image_raw = raw_event["Records"][1]["dynamodb"]["OldImage"]
30-
assert old_image.Message["S"] == old_image_raw["Message"]["S"]
31-
assert old_image.Id["N"] == float(old_image_raw["Id"]["N"])
30+
assert old_image.Message == old_image_raw["Message"]["S"]
31+
assert old_image.Id == float(old_image_raw["Id"]["N"])
3232

3333
new_image = parserd_event[1]["NewImage"]
3434
new_image_raw = raw_event["Records"][1]["dynamodb"]["NewImage"]
35-
assert new_image.Message["S"] == new_image_raw["Message"]["S"]
36-
assert new_image.Id["N"] == float(new_image_raw["Id"]["N"])
35+
assert new_image.Message == new_image_raw["Message"]["S"]
36+
assert new_image.Id == float(new_image_raw["Id"]["N"])
3737

3838

3939
def test_dynamo_db_stream_trigger_event_no_envelope():
@@ -65,12 +65,12 @@ def test_dynamo_db_stream_trigger_event_no_envelope():
6565
keys = dynamodb.Keys
6666
raw_keys = raw_dynamodb["Keys"]
6767
assert keys is not None
68-
id_key = keys["Id"]
69-
assert id_key["N"] == raw_keys["Id"]["N"]
68+
id_key = keys.get("Id")
69+
assert id_key == int(raw_keys["Id"]["N"])
7070

7171
message_key = dynamodb.NewImage.Message
7272
assert message_key is not None
73-
assert message_key["S"] == "New item!"
73+
assert message_key == "New item!"
7474

7575

7676
def test_validate_event_does_not_conform_with_model_no_envelope():

0 commit comments

Comments
 (0)