Feat/expose event attributes (#195)

* feat: Add an API to read all event attributes

Signed-off-by: Yurii Serhiichuk <savik.ne@gmail.com>

* deps: update black version

Signed-off-by: Yurii Serhiichuk <savik.ne@gmail.com>

* chore: update version to v1.6.2

Signed-off-by: Yurii Serhiichuk <savik.ne@gmail.com>

* docs: update changelog

Signed-off-by: Yurii Serhiichuk <savik.ne@gmail.com>

* docs: fix the release number link

Signed-off-by: Yurii Serhiichuk <savik.ne@gmail.com>

Signed-off-by: Yurii Serhiichuk <savik.ne@gmail.com>
This commit is contained in:
Yurii Serhiichuk 2022-10-19 19:21:28 +03:00 committed by GitHub
parent 60f848a204
commit 6648eb52aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 4 deletions

View File

@ -11,7 +11,7 @@ repos:
- id: isort - id: isort
args: [ "--profile", "black", "--filter-files" ] args: [ "--profile", "black", "--filter-files" ]
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 22.8.0 rev: 22.10.0
hooks: hooks:
- id: black - id: black
language_version: python3.10 language_version: python3.10

View File

@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [1.6.2] — 2022-10-18
### Added
- Added `get_attributes` API to the `CloudEvent` API. The method returns a read-only
view on the event attributes. ([#195])
## [1.6.1] — 2022-08-18 ## [1.6.1] — 2022-08-18
### Fixed ### Fixed
- Missing `to_json` import. ([#191]) - Missing `to_json` import. ([#191])
@ -146,6 +151,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [0.0.1] - 2018-11-19 ## [0.0.1] - 2018-11-19
### Added ### Added
- Initial release - Initial release
[1.6.2]: https://github.com/cloudevents/sdk-python/compare/1.6.1...1.6.2
[1.6.1]: https://github.com/cloudevents/sdk-python/compare/1.6.0...1.6.1 [1.6.1]: https://github.com/cloudevents/sdk-python/compare/1.6.0...1.6.1
[1.6.0]: https://github.com/cloudevents/sdk-python/compare/1.5.0...1.6.0 [1.6.0]: https://github.com/cloudevents/sdk-python/compare/1.5.0...1.6.0
[1.5.0]: https://github.com/cloudevents/sdk-python/compare/1.4.0...1.5.0 [1.5.0]: https://github.com/cloudevents/sdk-python/compare/1.4.0...1.5.0
@ -210,3 +217,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#186]: https://github.com/cloudevents/sdk-python/pull/186 [#186]: https://github.com/cloudevents/sdk-python/pull/186
[#188]: https://github.com/cloudevents/sdk-python/pull/188 [#188]: https://github.com/cloudevents/sdk-python/pull/188
[#191]: https://github.com/cloudevents/sdk-python/pull/191 [#191]: https://github.com/cloudevents/sdk-python/pull/191
[#195]: https://github.com/cloudevents/sdk-python/pull/195

View File

@ -12,4 +12,4 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
__version__ = "1.6.1" __version__ = "1.6.2"

View File

@ -14,6 +14,8 @@
import typing import typing
from abc import abstractmethod from abc import abstractmethod
from types import MappingProxyType
from typing import Mapping
class CloudEvent: class CloudEvent:
@ -45,6 +47,14 @@ class CloudEvent:
""" """
raise NotImplementedError() raise NotImplementedError()
def get_attributes(self) -> Mapping[str, typing.Any]:
"""
Returns a read-only view on the attributes of the event.
:returns: Read-only view on the attributes of the event.
"""
return MappingProxyType(self._get_attributes())
@abstractmethod @abstractmethod
def _get_attributes(self) -> typing.Dict[str, typing.Any]: def _get_attributes(self) -> typing.Dict[str, typing.Any]:
""" """

View File

@ -15,6 +15,7 @@
import bz2 import bz2
import io import io
import json import json
import typing
import pytest import pytest
from sanic import Sanic, response from sanic import Sanic, response
@ -83,7 +84,6 @@ async def echo(request):
@pytest.mark.parametrize("body", invalid_cloudevent_request_body) @pytest.mark.parametrize("body", invalid_cloudevent_request_body)
def test_missing_required_fields_structured(body): def test_missing_required_fields_structured(body):
with pytest.raises(cloud_exceptions.MissingRequiredFields): with pytest.raises(cloud_exceptions.MissingRequiredFields):
_ = from_http( _ = from_http(
{"Content-Type": "application/cloudevents+json"}, json.dumps(body) {"Content-Type": "application/cloudevents+json"}, json.dumps(body)
) )
@ -188,7 +188,6 @@ def test_missing_ce_prefix_binary_event(specversion):
"ce-specversion": specversion, "ce-specversion": specversion,
} }
for key in headers: for key in headers:
# breaking prefix e.g. e-id instead of ce-id # breaking prefix e.g. e-id instead of ce-id
prefixed_headers[key[1:]] = headers[key] prefixed_headers[key[1:]] = headers[key]
@ -245,6 +244,25 @@ def test_structured_to_request(specversion):
assert body["data"] == data, f"|{body_bytes}|| {body}" assert body["data"] == data, f"|{body_bytes}|| {body}"
@pytest.mark.parametrize("specversion", ["1.0", "0.3"])
def test_attributes_view_accessor(specversion: str):
attributes: dict[str, typing.Any] = {
"specversion": specversion,
"type": "word.found.name",
"id": "96fb5f0b-001e-0108-6dfe-da6e2806f124",
"source": "pytest",
}
data = {"message": "Hello World!"}
event: CloudEvent = CloudEvent(attributes, data)
event_attributes: typing.Mapping[str, typing.Any] = event.get_attributes()
assert event_attributes["specversion"] == attributes["specversion"]
assert event_attributes["type"] == attributes["type"]
assert event_attributes["id"] == attributes["id"]
assert event_attributes["source"] == attributes["source"]
assert event_attributes["time"]
@pytest.mark.parametrize("specversion", ["1.0", "0.3"]) @pytest.mark.parametrize("specversion", ["1.0", "0.3"])
def test_binary_to_request(specversion): def test_binary_to_request(specversion):
attributes = { attributes = {

View File

@ -15,6 +15,7 @@
import bz2 import bz2
import io import io
import json import json
import typing
import pytest import pytest
from sanic import Sanic, response from sanic import Sanic, response
@ -242,6 +243,25 @@ def test_structured_to_request(specversion):
assert body["data"] == data, f"|{body_bytes}|| {body}" assert body["data"] == data, f"|{body_bytes}|| {body}"
@pytest.mark.parametrize("specversion", ["1.0", "0.3"])
def test_attributes_view_accessor(specversion: str):
attributes: dict[str, typing.Any] = {
"specversion": specversion,
"type": "word.found.name",
"id": "96fb5f0b-001e-0108-6dfe-da6e2806f124",
"source": "pytest",
}
data = {"message": "Hello World!"}
event: CloudEvent = CloudEvent(attributes, data)
event_attributes: typing.Mapping[str, typing.Any] = event.get_attributes()
assert event_attributes["specversion"] == attributes["specversion"]
assert event_attributes["type"] == attributes["type"]
assert event_attributes["id"] == attributes["id"]
assert event_attributes["source"] == attributes["source"]
assert event_attributes["time"]
@pytest.mark.parametrize("specversion", ["1.0", "0.3"]) @pytest.mark.parametrize("specversion", ["1.0", "0.3"])
def test_binary_to_request(specversion): def test_binary_to_request(specversion):
attributes = { attributes = {