diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e1891b..06c9f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `.get` accessor for even properties ([#165]) - Added type information for all event member functions ([#173]) +### Fixed +- Fixed event `__eq__` operator raising `AttributeError` on non-CloudEvent values ([#172]) + ### Changed - Code quality and styling tooling is unified and configs compatibility is ensured ([#167]) - CI configurations updated and added macOS and Windows tests ([#169]) @@ -18,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - `docs` folder and related unused tooling ([#168]) + ## [1.3.0] — 2022-09-07 ### Added - Python 3.9 support ([#144]) @@ -156,4 +160,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#168]: https://github.com/cloudevents/sdk-python/pull/168 [#169]: https://github.com/cloudevents/sdk-python/pull/169 [#170]: https://github.com/cloudevents/sdk-python/pull/170 +[#172]: https://github.com/cloudevents/sdk-python/pull/172 [#173]: https://github.com/cloudevents/sdk-python/pull/173 diff --git a/cloudevents/http/event.py b/cloudevents/http/event.py index b4ef41a..ee78cff 100644 --- a/cloudevents/http/event.py +++ b/cloudevents/http/event.py @@ -68,7 +68,9 @@ class CloudEvent: ) def __eq__(self, other: typing.Any) -> bool: - return self.data == other.data and self._attributes == other._attributes + if isinstance(other, CloudEvent): + return self.data == other.data and self._attributes == other._attributes + return False # Data access is handled via `.data` member # Attribute access is managed via Mapping type diff --git a/cloudevents/tests/test_http_cloudevent.py b/cloudevents/tests/test_http_cloudevent.py index 3737ea6..fa4bd91 100644 --- a/cloudevents/tests/test_http_cloudevent.py +++ b/cloudevents/tests/test_http_cloudevent.py @@ -47,6 +47,18 @@ def your_dummy_data(): return '{"name":"paul"}' +@pytest.fixture() +def dummy_event(dummy_attributes, my_dummy_data): + return CloudEvent(attributes=dummy_attributes, data=my_dummy_data) + + +@pytest.fixture() +def non_exiting_attribute_name(dummy_event): + result = "nonexisting" + assert result not in dummy_event + return result + + def test_http_cloudevent_equality(dummy_attributes, my_dummy_data, your_dummy_data): data = my_dummy_data event1 = CloudEvent(dummy_attributes, data) @@ -71,6 +83,21 @@ def test_http_cloudevent_equality(dummy_attributes, my_dummy_data, your_dummy_da assert event1 != event2 and event3 != event1 +@pytest.mark.parametrize( + "non_cloudevent_value", + ( + 1, + None, + object(), + "Hello World", + ), +) +def test_http_cloudevent_must_not_equal_to_non_cloudevent_value( + dummy_event, non_cloudevent_value +): + assert not dummy_event == non_cloudevent_value + + def test_http_cloudevent_mutates_equality( dummy_attributes, my_dummy_data, your_dummy_data ): @@ -145,18 +172,6 @@ def test_none_json_or_string(): assert _json_or_string(None) is None -@pytest.fixture() -def dummy_event(dummy_attributes, my_dummy_data): - return CloudEvent(attributes=dummy_attributes, data=my_dummy_data) - - -@pytest.fixture() -def non_exiting_attribute_name(dummy_event): - result = "nonexisting" - assert result not in dummy_event - return result - - def test_get_operation_on_non_existing_attribute_must_not_raise_exception( dummy_event, non_exiting_attribute_name ):