diff --git a/aws_lambda_powertools/utilities/data_classes/s3_event.py b/aws_lambda_powertools/utilities/data_classes/s3_event.py index 802f1663edb..1a6f9c541a3 100644 --- a/aws_lambda_powertools/utilities/data_classes/s3_event.py +++ b/aws_lambda_powertools/utilities/data_classes/s3_event.py @@ -32,14 +32,14 @@ def key(self) -> str: return unquote_plus(self["key"]) @property - def size(self) -> str: - """Object size""" - return self["size"] + def size(self) -> Optional[int]: + """Object size. Object deletion event doesn't contain size.""" + return self.get("size") @property def etag(self) -> str: - """Object etag""" - return self["etag"] + """Object etag. Object deletion event doesn't contain etag; we default to empty string""" + return self.get("etag", "") # type: ignore[return-value] # false positive @property def version_id(self) -> str: @@ -178,8 +178,8 @@ def size(self) -> int: @property def etag(self) -> str: - """object eTag""" - return self["s3"]["object"]["eTag"] + """Object eTag. Object deletion event doesn't contain eTag; we default to empty string""" + return self["s3"]["object"].get("eTag", "") @property def version_id(self) -> Optional[str]: diff --git a/aws_lambda_powertools/utilities/parser/models/s3.py b/aws_lambda_powertools/utilities/parser/models/s3.py index db6c41d30f3..cb5df44e193 100644 --- a/aws_lambda_powertools/utilities/parser/models/s3.py +++ b/aws_lambda_powertools/utilities/parser/models/s3.py @@ -61,7 +61,7 @@ class S3Message(BaseModel): class S3EventNotificationObjectModel(BaseModel): key: str size: Optional[NonNegativeFloat] = None - etag: str + etag: str = Field(default="") version_id: str = Field(None, alias="version-id") sequencer: Optional[str] = None diff --git a/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json b/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json index af52ee2fef0..7c0995338a8 100644 --- a/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json +++ b/tests/events/s3EventBridgeNotificationObjectDeletedEvent.json @@ -16,8 +16,6 @@ }, "object": { "key": "IMG_m7fzo3.jpg", - "size": 184662, - "etag": "4e68adba0abe2dc8653dc3354e14c01d", "sequencer": "006408CAD69598B05E" }, "request-id": "0BH729840619AG5K", @@ -26,4 +24,4 @@ "reason": "DeleteObject", "deletion-type": "Delete Marker Created" } -} \ No newline at end of file +} diff --git a/tests/unit/data_classes/test_s3_eventbridge_notification.py b/tests/unit/data_classes/test_s3_eventbridge_notification.py index 391c3fa1788..ae27ad2965f 100644 --- a/tests/unit/data_classes/test_s3_eventbridge_notification.py +++ b/tests/unit/data_classes/test_s3_eventbridge_notification.py @@ -26,10 +26,10 @@ def test_s3_eventbridge_notification_detail_parsed(raw_event: Dict): assert parsed_event.detail.deletion_type == raw_event["detail"].get("deletion-type") assert parsed_event.detail.destination_access_tier == raw_event["detail"].get("destination-access-tier") assert parsed_event.detail.destination_storage_class == raw_event["detail"].get("destination-storage-class") - assert parsed_event.detail.object.etag == raw_event["detail"]["object"]["etag"] + assert parsed_event.detail.object.etag == raw_event["detail"]["object"].get("etag", "") assert parsed_event.detail.object.key == raw_event["detail"]["object"]["key"] assert parsed_event.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] - assert parsed_event.detail.object.size == raw_event["detail"]["object"]["size"] + assert parsed_event.detail.object.size == raw_event["detail"]["object"].get("size") assert parsed_event.detail.reason == raw_event["detail"].get("reason") assert parsed_event.detail.version == raw_event["detail"].get("version") assert parsed_event.detail.request_id == raw_event["detail"]["request-id"] diff --git a/tests/unit/parser/test_s3_notification.py b/tests/unit/parser/test_s3_notification.py index c77c70095a3..ca83851d06c 100644 --- a/tests/unit/parser/test_s3_notification.py +++ b/tests/unit/parser/test_s3_notification.py @@ -52,8 +52,8 @@ def test_s3_eventbridge_notification_object_deleted_event(): assert model.detail.version == raw_event["detail"]["version"] assert model.detail.bucket.name == raw_event["detail"]["bucket"]["name"] assert model.detail.object.key == raw_event["detail"]["object"]["key"] - assert model.detail.object.size == raw_event["detail"]["object"]["size"] - assert model.detail.object.etag == raw_event["detail"]["object"]["etag"] + assert model.detail.object.size == raw_event["detail"]["object"].get("size") + assert model.detail.object.etag == raw_event["detail"]["object"].get("etag", "") assert model.detail.object.sequencer == raw_event["detail"]["object"]["sequencer"] assert model.detail.request_id == raw_event["detail"]["request-id"] assert model.detail.requester == raw_event["detail"]["requester"]