Added Cloudevents V0.3 and V1 implementations (#22)
* Added v1 and v03 specs Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Added v1 and v03 specs implementations Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * linter Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * linter 2 Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Add changelog entry Signed-off-by: Dustin Ingram <di@users.noreply.github.com> Co-authored-by: Dustin Ingram <di@users.noreply.github.com>
This commit is contained in:
parent
b7ad8c2fbb
commit
bcacf3391a
|
@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
- Added Cloudevents V0.3 and V1 implementations ([#22])
|
||||||
- Add helpful text to README ([#23])
|
- Add helpful text to README ([#23])
|
||||||
- Add link to email in README ([#27])
|
- Add link to email in README ([#27])
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
[#15]: https://github.com/cloudevents/sdk-python/pull/15
|
[#15]: https://github.com/cloudevents/sdk-python/pull/15
|
||||||
[#17]: https://github.com/cloudevents/sdk-python/pull/17
|
[#17]: https://github.com/cloudevents/sdk-python/pull/17
|
||||||
[#21]: https://github.com/cloudevents/sdk-python/pull/21
|
[#21]: https://github.com/cloudevents/sdk-python/pull/21
|
||||||
|
[#22]: https://github.com/cloudevents/sdk-python/pull/22
|
||||||
[#23]: https://github.com/cloudevents/sdk-python/pull/23
|
[#23]: https://github.com/cloudevents/sdk-python/pull/23
|
||||||
[#25]: https://github.com/cloudevents/sdk-python/pull/25
|
[#25]: https://github.com/cloudevents/sdk-python/pull/25
|
||||||
[#27]: https://github.com/cloudevents/sdk-python/pull/27
|
[#27]: https://github.com/cloudevents/sdk-python/pull/27
|
||||||
|
|
|
@ -17,13 +17,13 @@ import typing
|
||||||
from cloudevents.sdk import exceptions
|
from cloudevents.sdk import exceptions
|
||||||
from cloudevents.sdk.converters import base
|
from cloudevents.sdk.converters import base
|
||||||
from cloudevents.sdk.event import base as event_base
|
from cloudevents.sdk.event import base as event_base
|
||||||
from cloudevents.sdk.event import v02
|
from cloudevents.sdk.event import v02, v03, v1
|
||||||
|
|
||||||
|
|
||||||
class BinaryHTTPCloudEventConverter(base.Converter):
|
class BinaryHTTPCloudEventConverter(base.Converter):
|
||||||
|
|
||||||
TYPE = "binary"
|
TYPE = "binary"
|
||||||
SUPPORTED_VERSIONS = [v02.Event]
|
SUPPORTED_VERSIONS = [v02.Event, v03.Event, v1.Event]
|
||||||
|
|
||||||
def can_read(self, content_type: str) -> bool:
|
def can_read(self, content_type: str) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -17,7 +17,9 @@ import json
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(slinkydeveloper) is this really needed?
|
||||||
class EventGetterSetter(object):
|
class EventGetterSetter(object):
|
||||||
|
|
||||||
def CloudEventVersion(self) -> str:
|
def CloudEventVersion(self) -> str:
|
||||||
raise Exception("not implemented")
|
raise Exception("not implemented")
|
||||||
|
|
||||||
|
@ -126,16 +128,10 @@ class BaseEvent(EventGetterSetter):
|
||||||
body: typing.IO,
|
body: typing.IO,
|
||||||
data_unmarshaller: typing.Callable
|
data_unmarshaller: typing.Callable
|
||||||
):
|
):
|
||||||
binary_mapping = {
|
|
||||||
"content-type": "contenttype",
|
|
||||||
# TODO(someone): add Distributed Tracing. It's not clear
|
|
||||||
# if this is one extension or two.
|
|
||||||
# https://github.com/cloudevents/spec/blob/master/extensions/distributed-tracing.md
|
|
||||||
}
|
|
||||||
for header, value in headers.items():
|
for header, value in headers.items():
|
||||||
header = header.lower()
|
header = header.lower()
|
||||||
if header in binary_mapping:
|
if header == "content-type":
|
||||||
self.Set(binary_mapping[header], value)
|
self.SetContentType(value)
|
||||||
elif header.startswith("ce-"):
|
elif header.startswith("ce-"):
|
||||||
self.Set(header[3:], value)
|
self.Set(header[3:], value)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from cloudevents.sdk.event import base
|
||||||
|
from cloudevents.sdk.event import opt
|
||||||
|
|
||||||
|
|
||||||
|
class Event(base.BaseEvent):
|
||||||
|
def __init__(self):
|
||||||
|
self.ce__specversion = opt.Option("specversion", "0.3", True)
|
||||||
|
self.ce__id = opt.Option("id", None, True)
|
||||||
|
self.ce__source = opt.Option("source", None, True)
|
||||||
|
self.ce__type = opt.Option("type", None, True)
|
||||||
|
|
||||||
|
self.ce__datacontenttype = opt.Option("datacontenttype", None, False)
|
||||||
|
self.ce__datacontentencoding = opt.Option(
|
||||||
|
"datacontentencoding",
|
||||||
|
None,
|
||||||
|
False
|
||||||
|
)
|
||||||
|
self.ce__subject = opt.Option("subject", None, False)
|
||||||
|
self.ce__time = opt.Option("time", None, False)
|
||||||
|
self.ce__schemaurl = opt.Option("schemaurl", None, False)
|
||||||
|
self.ce__data = opt.Option("data", None, False)
|
||||||
|
self.ce__extensions = opt.Option("extensions", dict(), False)
|
||||||
|
|
||||||
|
def CloudEventVersion(self) -> str:
|
||||||
|
return self.ce__specversion.get()
|
||||||
|
|
||||||
|
def EventType(self) -> str:
|
||||||
|
return self.ce__type.get()
|
||||||
|
|
||||||
|
def Source(self) -> str:
|
||||||
|
return self.ce__source.get()
|
||||||
|
|
||||||
|
def EventID(self) -> str:
|
||||||
|
return self.ce__id.get()
|
||||||
|
|
||||||
|
def EventTime(self) -> str:
|
||||||
|
return self.ce__time.get()
|
||||||
|
|
||||||
|
def Subject(self) -> str:
|
||||||
|
return self.ce__subject.get()
|
||||||
|
|
||||||
|
def SchemaURL(self) -> str:
|
||||||
|
return self.ce__schemaurl.get()
|
||||||
|
|
||||||
|
def Data(self) -> object:
|
||||||
|
return self.ce__data.get()
|
||||||
|
|
||||||
|
def Extensions(self) -> dict:
|
||||||
|
return self.ce__extensions.get()
|
||||||
|
|
||||||
|
def ContentType(self) -> str:
|
||||||
|
return self.ce__datacontenttype.get()
|
||||||
|
|
||||||
|
def ContentEncoding(self) -> str:
|
||||||
|
return self.ce__datacontentencoding.get()
|
||||||
|
|
||||||
|
def SetEventType(self, eventType: str) -> base.BaseEvent:
|
||||||
|
self.Set("type", eventType)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetSource(self, source: str) -> base.BaseEvent:
|
||||||
|
self.Set("source", source)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetEventID(self, eventID: str) -> base.BaseEvent:
|
||||||
|
self.Set("id", eventID)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetEventTime(self, eventTime: str) -> base.BaseEvent:
|
||||||
|
self.Set("time", eventTime)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetSubject(self, subject: str) -> base.BaseEvent:
|
||||||
|
self.Set("subject", subject)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetSchemaURL(self, schemaURL: str) -> base.BaseEvent:
|
||||||
|
self.Set("schemaurl", schemaURL)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetData(self, data: object) -> base.BaseEvent:
|
||||||
|
self.Set("data", data)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetExtensions(self, extensions: dict) -> base.BaseEvent:
|
||||||
|
self.Set("extensions", extensions)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetContentType(self, contentType: str) -> base.BaseEvent:
|
||||||
|
self.Set("datacontenttype", contentType)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetContentEncoding(self, contentEncoding: str) -> base.BaseEvent:
|
||||||
|
self.Set("datacontentencoding", contentEncoding)
|
||||||
|
return self
|
|
@ -0,0 +1,97 @@
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from cloudevents.sdk.event import base
|
||||||
|
from cloudevents.sdk.event import opt
|
||||||
|
|
||||||
|
|
||||||
|
class Event(base.BaseEvent):
|
||||||
|
def __init__(self):
|
||||||
|
self.ce__specversion = opt.Option("specversion", "1.0", True)
|
||||||
|
self.ce__id = opt.Option("id", None, True)
|
||||||
|
self.ce__source = opt.Option("source", None, True)
|
||||||
|
self.ce__type = opt.Option("type", None, True)
|
||||||
|
|
||||||
|
self.ce__datacontenttype = opt.Option("datacontenttype", None, False)
|
||||||
|
self.ce__dataschema = opt.Option("dataschema", None, False)
|
||||||
|
self.ce__subject = opt.Option("subject", None, False)
|
||||||
|
self.ce__time = opt.Option("time", None, False)
|
||||||
|
self.ce__data = opt.Option("data", None, False)
|
||||||
|
self.ce__extensions = opt.Option("extensions", dict(), False)
|
||||||
|
|
||||||
|
def CloudEventVersion(self) -> str:
|
||||||
|
return self.ce__specversion.get()
|
||||||
|
|
||||||
|
def EventType(self) -> str:
|
||||||
|
return self.ce__type.get()
|
||||||
|
|
||||||
|
def Source(self) -> str:
|
||||||
|
return self.ce__source.get()
|
||||||
|
|
||||||
|
def EventID(self) -> str:
|
||||||
|
return self.ce__id.get()
|
||||||
|
|
||||||
|
def EventTime(self) -> str:
|
||||||
|
return self.ce__time.get()
|
||||||
|
|
||||||
|
def Subject(self) -> str:
|
||||||
|
return self.ce__subject.get()
|
||||||
|
|
||||||
|
def Schema(self) -> str:
|
||||||
|
return self.ce__dataschema.get()
|
||||||
|
|
||||||
|
def ContentType(self) -> str:
|
||||||
|
return self.ce__datacontenttype.get()
|
||||||
|
|
||||||
|
def Data(self) -> object:
|
||||||
|
return self.ce__data.get()
|
||||||
|
|
||||||
|
def Extensions(self) -> dict:
|
||||||
|
return self.ce__extensions.get()
|
||||||
|
|
||||||
|
def SetEventType(self, eventType: str) -> base.BaseEvent:
|
||||||
|
self.Set("type", eventType)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetSource(self, source: str) -> base.BaseEvent:
|
||||||
|
self.Set("source", source)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetEventID(self, eventID: str) -> base.BaseEvent:
|
||||||
|
self.Set("id", eventID)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetEventTime(self, eventTime: str) -> base.BaseEvent:
|
||||||
|
self.Set("time", eventTime)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetSubject(self, subject: str) -> base.BaseEvent:
|
||||||
|
self.Set("subject", subject)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetSchema(self, schema: str) -> base.BaseEvent:
|
||||||
|
self.Set("dataschema", schema)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetContentType(self, contentType: str) -> base.BaseEvent:
|
||||||
|
self.Set("datacontenttype", contentType)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetData(self, data: object) -> base.BaseEvent:
|
||||||
|
self.Set("data", data)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def SetExtensions(self, extensions: dict) -> base.BaseEvent:
|
||||||
|
self.Set("extensions", extensions)
|
||||||
|
return self
|
|
@ -61,7 +61,9 @@ class HTTPMarshaller(object):
|
||||||
if not isinstance(data_unmarshaller, typing.Callable):
|
if not isinstance(data_unmarshaller, typing.Callable):
|
||||||
raise exceptions.InvalidDataUnmarshaller()
|
raise exceptions.InvalidDataUnmarshaller()
|
||||||
|
|
||||||
content_type = headers.get("content-type", headers.get("Content-Type"))
|
# Lower all header keys
|
||||||
|
headers = {key.lower(): value for key, value in headers.items()}
|
||||||
|
content_type = headers.get("content-type", None)
|
||||||
|
|
||||||
for cnvrtr in self.__converters:
|
for cnvrtr in self.__converters:
|
||||||
if cnvrtr.can_read(content_type) and cnvrtr.event_supported(event):
|
if cnvrtr.can_read(content_type) and cnvrtr.event_supported(event):
|
||||||
|
|
|
@ -12,26 +12,65 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from cloudevents.sdk.event import v02, v03, v1
|
||||||
|
|
||||||
contentType = "application/json"
|
contentType = "application/json"
|
||||||
ce_type = "word.found.exclamation"
|
ce_type = "word.found.exclamation"
|
||||||
ce_id = "16fb5f0b-211e-1102-3dfe-ea6e2806f124"
|
ce_id = "16fb5f0b-211e-1102-3dfe-ea6e2806f124"
|
||||||
source = "pytest"
|
source = "pytest"
|
||||||
specversion = "0.2"
|
|
||||||
eventTime = "2018-10-23T12:28:23.3464579Z"
|
eventTime = "2018-10-23T12:28:23.3464579Z"
|
||||||
body = '{"name":"john"}'
|
body = '{"name":"john"}'
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"ce-specversion": specversion,
|
v02.Event: {
|
||||||
"ce-type": ce_type,
|
"ce-specversion": "0.2",
|
||||||
"ce-id": ce_id,
|
"ce-type": ce_type,
|
||||||
"ce-time": eventTime,
|
"ce-id": ce_id,
|
||||||
"ce-source": source,
|
"ce-time": eventTime,
|
||||||
"Content-Type": contentType,
|
"ce-source": source,
|
||||||
|
"Content-Type": contentType,
|
||||||
|
},
|
||||||
|
v03.Event: {
|
||||||
|
"ce-specversion": "0.3",
|
||||||
|
"ce-type": ce_type,
|
||||||
|
"ce-id": ce_id,
|
||||||
|
"ce-time": eventTime,
|
||||||
|
"ce-source": source,
|
||||||
|
"Content-Type": contentType,
|
||||||
|
},
|
||||||
|
v1.Event: {
|
||||||
|
"ce-specversion": "1.0",
|
||||||
|
"ce-type": ce_type,
|
||||||
|
"ce-id": ce_id,
|
||||||
|
"ce-time": eventTime,
|
||||||
|
"ce-source": source,
|
||||||
|
"Content-Type": contentType,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
ce = {
|
|
||||||
"specversion": specversion,
|
json_ce = {
|
||||||
"type": ce_type,
|
v02.Event: {
|
||||||
"id": ce_id,
|
"specversion": "0.2",
|
||||||
"time": eventTime,
|
"type": ce_type,
|
||||||
"source": source,
|
"id": ce_id,
|
||||||
"contenttype": contentType,
|
"time": eventTime,
|
||||||
|
"source": source,
|
||||||
|
"contenttype": contentType,
|
||||||
|
},
|
||||||
|
v03.Event: {
|
||||||
|
"specversion": "0.3",
|
||||||
|
"type": ce_type,
|
||||||
|
"id": ce_id,
|
||||||
|
"time": eventTime,
|
||||||
|
"source": source,
|
||||||
|
"datacontenttype": contentType,
|
||||||
|
},
|
||||||
|
v1.Event: {
|
||||||
|
"specversion": "1.0",
|
||||||
|
"type": ce_type,
|
||||||
|
"id": ce_id,
|
||||||
|
"time": eventTime,
|
||||||
|
"source": source,
|
||||||
|
"datacontenttype": contentType,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ from cloudevents.sdk import marshaller
|
||||||
|
|
||||||
from cloudevents.sdk.event import v01
|
from cloudevents.sdk.event import v01
|
||||||
from cloudevents.sdk.event import v02
|
from cloudevents.sdk.event import v02
|
||||||
|
from cloudevents.sdk.event import v03
|
||||||
|
from cloudevents.sdk.event import v1
|
||||||
|
|
||||||
from cloudevents.sdk.converters import binary
|
from cloudevents.sdk.converters import binary
|
||||||
from cloudevents.sdk.converters import structured
|
from cloudevents.sdk.converters import structured
|
||||||
|
@ -28,28 +30,32 @@ from cloudevents.sdk.converters import structured
|
||||||
from cloudevents.tests import data
|
from cloudevents.tests import data
|
||||||
|
|
||||||
|
|
||||||
def test_binary_converter_upstream():
|
@pytest.mark.parametrize("event_class", [v02.Event, v03.Event, v1.Event])
|
||||||
|
def test_binary_converter_upstream(event_class):
|
||||||
m = marshaller.NewHTTPMarshaller(
|
m = marshaller.NewHTTPMarshaller(
|
||||||
[binary.NewBinaryHTTPCloudEventConverter()])
|
[binary.NewBinaryHTTPCloudEventConverter()])
|
||||||
event = m.FromRequest(v02.Event(), data.headers, None, lambda x: x)
|
event = m.FromRequest(event_class(), data.headers[event_class], None, lambda x: x)
|
||||||
assert event is not None
|
assert event is not None
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.EventType() == data.ce_type
|
||||||
assert event.Get("id") == (data.ce_id, True)
|
assert event.EventID() == data.ce_id
|
||||||
|
assert event.ContentType() == data.contentType
|
||||||
|
|
||||||
|
|
||||||
def test_structured_converter_upstream():
|
@pytest.mark.parametrize("event_class", [v02.Event, v03.Event, v1.Event])
|
||||||
|
def test_structured_converter_upstream(event_class):
|
||||||
m = marshaller.NewHTTPMarshaller(
|
m = marshaller.NewHTTPMarshaller(
|
||||||
[structured.NewJSONHTTPCloudEventConverter()])
|
[structured.NewJSONHTTPCloudEventConverter()])
|
||||||
event = m.FromRequest(
|
event = m.FromRequest(
|
||||||
v02.Event(),
|
event_class(),
|
||||||
{"Content-Type": "application/cloudevents+json"},
|
{"Content-Type": "application/cloudevents+json"},
|
||||||
io.StringIO(json.dumps(data.ce)),
|
io.StringIO(json.dumps(data.json_ce[event_class])),
|
||||||
lambda x: x.read(),
|
lambda x: x.read(),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert event is not None
|
assert event is not None
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.EventType() == data.ce_type
|
||||||
assert event.Get("id") == (data.ce_id, True)
|
assert event.EventID() == data.ce_id
|
||||||
|
assert event.ContentType() == data.contentType
|
||||||
|
|
||||||
|
|
||||||
def test_binary_converter_v01():
|
def test_binary_converter_v01():
|
||||||
|
@ -86,7 +92,7 @@ def test_structured_converter_v01():
|
||||||
event = m.FromRequest(
|
event = m.FromRequest(
|
||||||
v01.Event(),
|
v01.Event(),
|
||||||
{"Content-Type": "application/cloudevents+json"},
|
{"Content-Type": "application/cloudevents+json"},
|
||||||
io.StringIO(json.dumps(data.ce)),
|
io.StringIO(json.dumps(data.json_ce[v02.Event])),
|
||||||
lambda x: x.read(),
|
lambda x: x.read(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -94,33 +100,36 @@ def test_structured_converter_v01():
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.Get("type") == (data.ce_type, True)
|
||||||
assert event.Get("id") == (data.ce_id, True)
|
assert event.Get("id") == (data.ce_id, True)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("event_class", [v02.Event, v03.Event, v1.Event])
|
||||||
def test_default_http_marshaller_with_structured():
|
def test_default_http_marshaller_with_structured(event_class):
|
||||||
m = marshaller.NewDefaultHTTPMarshaller()
|
m = marshaller.NewDefaultHTTPMarshaller()
|
||||||
|
|
||||||
event = m.FromRequest(
|
event = m.FromRequest(
|
||||||
v02.Event(),
|
event_class(),
|
||||||
{"Content-Type": "application/cloudevents+json"},
|
{"Content-Type": "application/cloudevents+json"},
|
||||||
io.StringIO(json.dumps(data.ce)),
|
io.StringIO(json.dumps(data.json_ce[event_class])),
|
||||||
lambda x: x.read(),
|
lambda x: x.read(),
|
||||||
)
|
)
|
||||||
assert event is not None
|
assert event is not None
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.EventType() == data.ce_type
|
||||||
assert event.Get("id") == (data.ce_id, True)
|
assert event.EventID() == data.ce_id
|
||||||
|
assert event.ContentType() == data.contentType
|
||||||
|
|
||||||
|
|
||||||
def test_default_http_marshaller_with_binary():
|
@pytest.mark.parametrize("event_class", [v02.Event, v03.Event, v1.Event])
|
||||||
|
def test_default_http_marshaller_with_binary(event_class):
|
||||||
m = marshaller.NewDefaultHTTPMarshaller()
|
m = marshaller.NewDefaultHTTPMarshaller()
|
||||||
|
|
||||||
event = m.FromRequest(
|
event = m.FromRequest(
|
||||||
v02.Event(), data.headers,
|
event_class(), data.headers[event_class],
|
||||||
io.StringIO(json.dumps(data.body)),
|
io.StringIO(json.dumps(data.body)),
|
||||||
json.load
|
json.load
|
||||||
)
|
)
|
||||||
assert event is not None
|
assert event is not None
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.EventType() == data.ce_type
|
||||||
assert event.Get("data") == (data.body, True)
|
assert event.EventID() == data.ce_id
|
||||||
assert event.Get("id") == (data.ce_id, True)
|
assert event.ContentType() == data.contentType
|
||||||
|
assert event.Data() == data.body
|
||||||
|
|
||||||
|
|
||||||
def test_unsupported_event_configuration():
|
def test_unsupported_event_configuration():
|
||||||
|
@ -131,7 +140,7 @@ def test_unsupported_event_configuration():
|
||||||
m.FromRequest,
|
m.FromRequest,
|
||||||
v01.Event(),
|
v01.Event(),
|
||||||
{"Content-Type": "application/cloudevents+json"},
|
{"Content-Type": "application/cloudevents+json"},
|
||||||
io.StringIO(json.dumps(data.ce)),
|
io.StringIO(json.dumps(data.json_ce[v02.Event])),
|
||||||
lambda x: x.read(),
|
lambda x: x.read(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
|
import pytest
|
||||||
|
|
||||||
from cloudevents.sdk.event import v01
|
from cloudevents.sdk.event import v01, v02, v03, v1
|
||||||
from cloudevents.sdk.event import v02
|
|
||||||
|
|
||||||
from cloudevents.sdk import converters
|
from cloudevents.sdk import converters
|
||||||
from cloudevents.sdk import marshaller
|
from cloudevents.sdk import marshaller
|
||||||
|
@ -24,10 +24,10 @@ from cloudevents.sdk.converters import structured
|
||||||
|
|
||||||
from cloudevents.tests import data
|
from cloudevents.tests import data
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("event_class", [v02.Event, v03.Event, v1.Event])
|
||||||
def test_event_pipeline_upstream():
|
def test_event_pipeline_upstream(event_class):
|
||||||
event = (
|
event = (
|
||||||
v02.Event()
|
event_class()
|
||||||
.SetContentType(data.contentType)
|
.SetContentType(data.contentType)
|
||||||
.SetData(data.body)
|
.SetData(data.body)
|
||||||
.SetEventID(data.ce_id)
|
.SetEventID(data.ce_id)
|
||||||
|
|
|
@ -15,46 +15,51 @@
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import copy
|
import copy
|
||||||
|
import pytest
|
||||||
|
|
||||||
from cloudevents.sdk import converters
|
from cloudevents.sdk import converters
|
||||||
from cloudevents.sdk import marshaller
|
from cloudevents.sdk import marshaller
|
||||||
|
|
||||||
from cloudevents.sdk.converters import structured
|
from cloudevents.sdk.converters import structured
|
||||||
from cloudevents.sdk.event import v01
|
from cloudevents.sdk.event import v01, v02, v03, v1
|
||||||
from cloudevents.sdk.event import v02
|
from cloudevents.sdk.event import v02
|
||||||
|
|
||||||
|
|
||||||
from cloudevents.tests import data
|
from cloudevents.tests import data
|
||||||
|
|
||||||
|
|
||||||
def test_binary_event_to_request_upstream():
|
@pytest.mark.parametrize("event_class", [v02.Event, v03.Event, v1.Event])
|
||||||
|
def test_binary_event_to_request_upstream(event_class):
|
||||||
m = marshaller.NewDefaultHTTPMarshaller()
|
m = marshaller.NewDefaultHTTPMarshaller()
|
||||||
event = m.FromRequest(
|
event = m.FromRequest(
|
||||||
v02.Event(),
|
event_class(),
|
||||||
{"Content-Type": "application/cloudevents+json"},
|
{"Content-Type": "application/cloudevents+json"},
|
||||||
io.StringIO(json.dumps(data.ce)),
|
io.StringIO(json.dumps(data.json_ce[event_class])),
|
||||||
lambda x: x.read(),
|
lambda x: x.read(),
|
||||||
)
|
)
|
||||||
|
|
||||||
assert event is not None
|
assert event is not None
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.EventType() == data.ce_type
|
||||||
assert event.Get("id") == (data.ce_id, True)
|
assert event.EventID() == data.ce_id
|
||||||
|
assert event.ContentType() == data.contentType
|
||||||
|
|
||||||
new_headers, _ = m.ToRequest(event, converters.TypeBinary, lambda x: x)
|
new_headers, _ = m.ToRequest(event, converters.TypeBinary, lambda x: x)
|
||||||
assert new_headers is not None
|
assert new_headers is not None
|
||||||
assert "ce-specversion" in new_headers
|
assert "ce-specversion" in new_headers
|
||||||
|
|
||||||
|
|
||||||
def test_structured_event_to_request_upstream():
|
@pytest.mark.parametrize("event_class", [v02.Event, v03.Event, v1.Event])
|
||||||
copy_of_ce = copy.deepcopy(data.ce)
|
def test_structured_event_to_request_upstream(event_class):
|
||||||
|
copy_of_ce = copy.deepcopy(data.json_ce[event_class])
|
||||||
m = marshaller.NewDefaultHTTPMarshaller()
|
m = marshaller.NewDefaultHTTPMarshaller()
|
||||||
http_headers = {"content-type": "application/cloudevents+json"}
|
http_headers = {"content-type": "application/cloudevents+json"}
|
||||||
event = m.FromRequest(
|
event = m.FromRequest(
|
||||||
v02.Event(), http_headers, io.StringIO(json.dumps(data.ce)), lambda x: x.read()
|
event_class(), http_headers, io.StringIO(json.dumps(data.json_ce[event_class])), lambda x: x.read()
|
||||||
)
|
)
|
||||||
assert event is not None
|
assert event is not None
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.EventType() == data.ce_type
|
||||||
assert event.Get("id") == (data.ce_id, True)
|
assert event.EventID() == data.ce_id
|
||||||
|
assert event.ContentType() == data.contentType
|
||||||
|
|
||||||
new_headers, _ = m.ToRequest(event, converters.TypeStructured, lambda x: x)
|
new_headers, _ = m.ToRequest(event, converters.TypeStructured, lambda x: x)
|
||||||
for key in new_headers:
|
for key in new_headers:
|
||||||
|
@ -65,11 +70,11 @@ def test_structured_event_to_request_upstream():
|
||||||
|
|
||||||
|
|
||||||
def test_structured_event_to_request_v01():
|
def test_structured_event_to_request_v01():
|
||||||
copy_of_ce = copy.deepcopy(data.ce)
|
copy_of_ce = copy.deepcopy(data.json_ce[v02.Event])
|
||||||
m = marshaller.NewHTTPMarshaller([structured.NewJSONHTTPCloudEventConverter()])
|
m = marshaller.NewHTTPMarshaller([structured.NewJSONHTTPCloudEventConverter()])
|
||||||
http_headers = {"content-type": "application/cloudevents+json"}
|
http_headers = {"content-type": "application/cloudevents+json"}
|
||||||
event = m.FromRequest(
|
event = m.FromRequest(
|
||||||
v01.Event(), http_headers, io.StringIO(json.dumps(data.ce)), lambda x: x.read()
|
v01.Event(), http_headers, io.StringIO(json.dumps(data.json_ce[v02.Event])), lambda x: x.read()
|
||||||
)
|
)
|
||||||
assert event is not None
|
assert event is not None
|
||||||
assert event.Get("type") == (data.ce_type, True)
|
assert event.Get("type") == (data.ce_type, True)
|
||||||
|
|
|
@ -52,25 +52,25 @@ async def echo(request):
|
||||||
def test_reusable_marshaller():
|
def test_reusable_marshaller():
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
_, r = app.test_client.post(
|
_, r = app.test_client.post(
|
||||||
"/is-ok", headers=test_data.headers, data=test_data.body
|
"/is-ok", headers=test_data.headers[v02.Event], data=test_data.body
|
||||||
)
|
)
|
||||||
assert r.status == 200
|
assert r.status == 200
|
||||||
|
|
||||||
|
|
||||||
def test_web_app_integration():
|
def test_web_app_integration():
|
||||||
_, r = app.test_client.post(
|
_, r = app.test_client.post(
|
||||||
"/is-ok", headers=test_data.headers, data=test_data.body
|
"/is-ok", headers=test_data.headers[v02.Event], data=test_data.body
|
||||||
)
|
)
|
||||||
assert r.status == 200
|
assert r.status == 200
|
||||||
|
|
||||||
|
|
||||||
def test_web_app_echo():
|
def test_web_app_echo():
|
||||||
_, r = app.test_client.post("/echo", headers=test_data.headers, data=test_data.body)
|
_, r = app.test_client.post("/echo", headers=test_data.headers[v02.Event], data=test_data.body)
|
||||||
assert r.status == 200
|
assert r.status == 200
|
||||||
event = m.FromRequest(v02.Event(), dict(r.headers), r.body, lambda x: x)
|
event = m.FromRequest(v02.Event(), dict(r.headers), r.body, lambda x: x)
|
||||||
assert event is not None
|
assert event is not None
|
||||||
props = event.Properties()
|
props = event.Properties()
|
||||||
for key in test_data.headers.keys():
|
for key in test_data.headers[v02.Event].keys():
|
||||||
if key == "Content-Type":
|
if key == "Content-Type":
|
||||||
assert "contenttype" in props
|
assert "contenttype" in props
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Reference in New Issue