From f3b488643e6a7850ce9547f8b81ae4195f8473bd Mon Sep 17 00:00:00 2001 From: Amin Farjadi Date: Wed, 24 Jun 2026 11:02:51 +0100 Subject: [PATCH 1/3] fix: EventBridgeEvent data class --- .../data_classes/event_bridge_event.py | 26 +++++++++---------- tests/events/eventBridgeEventBase.json | 8 ++++++ .../test_event_bridge_event.py | 17 ++++++++++++ 3 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 tests/events/eventBridgeEventBase.json diff --git a/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py b/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py index f7ce1953e2a..bfbf9990cd9 100644 --- a/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py +++ b/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py @@ -14,41 +14,41 @@ class EventBridgeEvent(DictWrapper): """ @property - def get_id(self) -> str: + def get_id(self) -> str | None: """A unique value is generated for every event. This can be helpful in tracing events as they move through rules to targets, and are processed.""" # Note: this name conflicts with existing python builtins - return self["id"] + return self.get("id") @property - def version(self) -> str: + def version(self) -> str | None: """By default, this is set to 0 (zero) in all events.""" - return self["version"] + return self.get("version") @property - def account(self) -> str: + def account(self) -> str | None: """The 12-digit number identifying an AWS account.""" - return self["account"] + return self.get("account") @property - def time(self) -> str: + def time(self) -> str | None: """The event timestamp, which can be specified by the service originating the event. If the event spans a time interval, the service might choose to report the start time, so this value can be noticeably before the time the event is actually received. """ - return self["time"] + return self.get("time") @property - def region(self) -> str: + def region(self) -> str | None: """Identifies the AWS region where the event originated.""" - return self["region"] + return self.get("region") @property - def resources(self) -> list[str]: + def resources(self) -> list[str] | None: """This JSON array contains ARNs that identify resources that are involved in the event. Inclusion of these ARNs is at the discretion of the service.""" - return self["resources"] + return self.get("resources") @property def source(self) -> str: @@ -68,4 +68,4 @@ def detail(self) -> dict[str, Any]: @property def replay_name(self) -> str | None: """Identifies whether the event is being replayed and what is the name of the replay.""" - return self["replay-name"] + return self.get("replay-name") diff --git a/tests/events/eventBridgeEventBase.json b/tests/events/eventBridgeEventBase.json new file mode 100644 index 00000000000..42e21439162 --- /dev/null +++ b/tests/events/eventBridgeEventBase.json @@ -0,0 +1,8 @@ +{ + "detail-type": "EC2 Instance State-change Notification", + "source": "aws.ec2", + "detail": { + "instance_id": "i-1234567890abcdef0", + "state": "terminated" + } +} diff --git a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py index 6dfc0c82485..f833e451c79 100644 --- a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py +++ b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py @@ -18,3 +18,20 @@ def test_event_bridge_event(): assert parsed_event.detail_type == raw_event["detail-type"] assert parsed_event.detail == raw_event["detail"] assert parsed_event.replay_name == "replay_archive" + + +def test_event_bridge_event_base(): + raw_event = load_event("eventBridgeEventBase.json") + parsed_event = EventBridgeEvent(raw_event) + + assert parsed_event.source == raw_event["source"] + assert parsed_event.detail_type == raw_event["detail-type"] + assert parsed_event.detail == raw_event["detail"] + + assert parsed_event.get_id is None + assert parsed_event.version is None + assert parsed_event.account is None + assert parsed_event.time is None + assert parsed_event.region is None + assert parsed_event.resources is None + assert parsed_event.replay_name is None From e3327faf66c4d784d2158d87ffefdd31e09dff5e Mon Sep 17 00:00:00 2001 From: Amin Farjadi Date: Wed, 24 Jun 2026 11:29:16 +0100 Subject: [PATCH 2/3] refactor: improve namings, add docstring --- tests/events/eventBridgeEventBase.json | 8 -------- tests/events/eventBridgeEventMinInfo.json | 7 +++++++ .../required_dependencies/test_event_bridge_event.py | 8 ++++++-- 3 files changed, 13 insertions(+), 10 deletions(-) delete mode 100644 tests/events/eventBridgeEventBase.json create mode 100644 tests/events/eventBridgeEventMinInfo.json diff --git a/tests/events/eventBridgeEventBase.json b/tests/events/eventBridgeEventBase.json deleted file mode 100644 index 42e21439162..00000000000 --- a/tests/events/eventBridgeEventBase.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "detail-type": "EC2 Instance State-change Notification", - "source": "aws.ec2", - "detail": { - "instance_id": "i-1234567890abcdef0", - "state": "terminated" - } -} diff --git a/tests/events/eventBridgeEventMinInfo.json b/tests/events/eventBridgeEventMinInfo.json new file mode 100644 index 00000000000..3f342766715 --- /dev/null +++ b/tests/events/eventBridgeEventMinInfo.json @@ -0,0 +1,7 @@ +{ + "detail-type": "My custom event", + "source": "my-custom-source", + "detail": { + "custom_field": "cool" + } +} \ No newline at end of file diff --git a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py index f833e451c79..dead169ee7a 100644 --- a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py +++ b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py @@ -20,8 +20,12 @@ def test_event_bridge_event(): assert parsed_event.replay_name == "replay_archive" -def test_event_bridge_event_base(): - raw_event = load_event("eventBridgeEventBase.json") +def test_event_bridge_event_with_minimum_info(): + """Testing a custom event with minimum required information. + + ref: https://docs.aws.amazon.com/eventbridge/latest/ref/events-structure.html#eb-custom-event + """ + raw_event = load_event("eventBridgeEventMinInfo.json") parsed_event = EventBridgeEvent(raw_event) assert parsed_event.source == raw_event["source"] From 40b4560a682a3a262cc8c75ba4596a3f2b3b6ce2 Mon Sep 17 00:00:00 2001 From: Amin Farjadi Date: Wed, 24 Jun 2026 22:02:06 +0100 Subject: [PATCH 3/3] address comment on issue 8300 --- .../data_classes/event_bridge_event.py | 24 +++++++++---------- tests/events/eventBridgeEvent.json | 9 +++---- tests/events/eventBridgeEventMinInfo.json | 7 ------ .../test_event_bridge_event.py | 21 ---------------- 4 files changed, 15 insertions(+), 46 deletions(-) delete mode 100644 tests/events/eventBridgeEventMinInfo.json diff --git a/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py b/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py index bfbf9990cd9..4655701574d 100644 --- a/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py +++ b/aws_lambda_powertools/utilities/data_classes/event_bridge_event.py @@ -14,41 +14,41 @@ class EventBridgeEvent(DictWrapper): """ @property - def get_id(self) -> str | None: + def get_id(self) -> str: """A unique value is generated for every event. This can be helpful in tracing events as they move through rules to targets, and are processed.""" # Note: this name conflicts with existing python builtins - return self.get("id") + return self["id"] @property - def version(self) -> str | None: + def version(self) -> str: """By default, this is set to 0 (zero) in all events.""" - return self.get("version") + return self["version"] @property - def account(self) -> str | None: + def account(self) -> str: """The 12-digit number identifying an AWS account.""" - return self.get("account") + return self["account"] @property - def time(self) -> str | None: + def time(self) -> str: """The event timestamp, which can be specified by the service originating the event. If the event spans a time interval, the service might choose to report the start time, so this value can be noticeably before the time the event is actually received. """ - return self.get("time") + return self["time"] @property - def region(self) -> str | None: + def region(self) -> str: """Identifies the AWS region where the event originated.""" - return self.get("region") + return self["region"] @property - def resources(self) -> list[str] | None: + def resources(self) -> list[str]: """This JSON array contains ARNs that identify resources that are involved in the event. Inclusion of these ARNs is at the discretion of the service.""" - return self.get("resources") + return self["resources"] @property def source(self) -> str: diff --git a/tests/events/eventBridgeEvent.json b/tests/events/eventBridgeEvent.json index 65872cf9a34..f7c6d4c0d37 100644 --- a/tests/events/eventBridgeEvent.json +++ b/tests/events/eventBridgeEvent.json @@ -6,12 +6,9 @@ "account": "111122223333", "time": "2017-12-22T18:43:48Z", "region": "us-west-1", - "resources": [ - "arn:aws:ec2:us-west-1:123456789012:instance/i-1234567890abcdef0" - ], + "resources": [], "detail": { "instance_id": "i-1234567890abcdef0", "state": "terminated" - }, - "replay-name": "replay_archive" -} + } +} \ No newline at end of file diff --git a/tests/events/eventBridgeEventMinInfo.json b/tests/events/eventBridgeEventMinInfo.json deleted file mode 100644 index 3f342766715..00000000000 --- a/tests/events/eventBridgeEventMinInfo.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "detail-type": "My custom event", - "source": "my-custom-source", - "detail": { - "custom_field": "cool" - } -} \ No newline at end of file diff --git a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py index dead169ee7a..e581cacae32 100644 --- a/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py +++ b/tests/unit/data_classes/required_dependencies/test_event_bridge_event.py @@ -17,25 +17,4 @@ def test_event_bridge_event(): assert parsed_event.source == raw_event["source"] assert parsed_event.detail_type == raw_event["detail-type"] assert parsed_event.detail == raw_event["detail"] - assert parsed_event.replay_name == "replay_archive" - - -def test_event_bridge_event_with_minimum_info(): - """Testing a custom event with minimum required information. - - ref: https://docs.aws.amazon.com/eventbridge/latest/ref/events-structure.html#eb-custom-event - """ - raw_event = load_event("eventBridgeEventMinInfo.json") - parsed_event = EventBridgeEvent(raw_event) - - assert parsed_event.source == raw_event["source"] - assert parsed_event.detail_type == raw_event["detail-type"] - assert parsed_event.detail == raw_event["detail"] - - assert parsed_event.get_id is None - assert parsed_event.version is None - assert parsed_event.account is None - assert parsed_event.time is None - assert parsed_event.region is None - assert parsed_event.resources is None assert parsed_event.replay_name is None