Consolidating return types

Closes: #6
Closes: #4
Signed-off-by: Denis Makogon <denys.makogon@oracle.com>
This commit is contained in:
Denis Makogon 2018-12-10 10:11:02 -08:00
parent f4a3c05857
commit 043236bb42
8 changed files with 106 additions and 19 deletions

View File

@ -70,6 +70,14 @@ headers, body = m.ToRequest(event, converters.TypeStructured, lambda x: x)
```
## HOWTOs with various Python HTTP frameworks
In this topic you'd find various example how to integrate an SDK with various HTTP frameworks.
### Python requests
The goal of this package is to provide support for all released versions of CloudEvents, ideally while maintaining
the same API. It will use semantic versioning with following rules:
* MAJOR version increments when backwards incompatible changes is introduced.

View File

@ -39,8 +39,7 @@ class BinaryHTTPCloudEventConverter(base.Converter):
if not isinstance(data_marshaller, typing.Callable):
raise exceptions.InvalidDataMarshaller()
hs, data = event.MarshalBinary()
return hs, data_marshaller(data)
return event.MarshalBinary(data_marshaller)
def NewBinaryHTTPCloudEventConverter() -> BinaryHTTPCloudEventConverter:

View File

@ -13,7 +13,7 @@
# under the License.
import io
import ujson
import json
import typing
@ -117,11 +117,11 @@ class BaseEvent(EventGetterSetter):
def MarshalJSON(self, data_marshaller: typing.Callable) -> typing.IO:
props = self.Properties()
props["data"] = data_marshaller(props.get("data"))
return io.StringIO(ujson.dumps(props))
return io.BytesIO(json.dumps(props).encode("utf-8"))
def UnmarshalJSON(self, b: typing.IO,
data_unmarshaller: typing.Callable):
raw_ce = ujson.load(b)
raw_ce = json.load(b)
for name, value in raw_ce.items():
if name == "data":
value = data_unmarshaller(value)
@ -143,7 +143,8 @@ class BaseEvent(EventGetterSetter):
self.Set("extensions", exts)
self.Set("data", data_unmarshaller(body))
def MarshalBinary(self) -> (dict, object):
def MarshalBinary(
self, data_marshaller: typing.Callable) -> (dict, object):
headers = {}
props = self.Properties()
for key, value in props.items():
@ -156,4 +157,5 @@ class BaseEvent(EventGetterSetter):
headers.update(**exts)
data, _ = self.Get("data")
return headers, data
return headers, io.BytesIO(
str(data_marshaller(data)).encode("utf-8"))

View File

@ -12,9 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
import pytest
import io
import ujson
from cloudevents.sdk import exceptions
from cloudevents.sdk import marshaller
@ -49,7 +49,7 @@ def test_structured_converter_upstream():
event = m.FromRequest(
v02.Event(),
{"Content-Type": "application/cloudevents+json"},
io.StringIO(ujson.dumps(data.ce)),
io.StringIO(json.dumps(data.ce)),
lambda x: x.read()
)
@ -81,7 +81,7 @@ def test_structured_converter_v01():
event = m.FromRequest(
v01.Event(),
{"Content-Type": "application/cloudevents+json"},
io.StringIO(ujson.dumps(data.ce)),
io.StringIO(json.dumps(data.ce)),
lambda x: x.read()
)
@ -96,7 +96,7 @@ def test_default_http_marshaller():
event = m.FromRequest(
v02.Event(),
{"Content-Type": "application/cloudevents+json"},
io.StringIO(ujson.dumps(data.ce)),
io.StringIO(json.dumps(data.ce)),
lambda x: x.read()
)
assert event is not None

View File

@ -12,7 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import ujson
import io
import json
from cloudevents.sdk.event import v01
from cloudevents.sdk.event import v02
@ -43,7 +44,8 @@ def test_event_pipeline_upstream():
assert "ce-id" in new_headers
assert "ce-time" in new_headers
assert "ce-contenttype" in new_headers
assert data.body == body
assert isinstance(body, io.BytesIO)
assert data.body == body.read().decode("utf-8")
def test_event_pipeline_v01():
@ -63,7 +65,8 @@ def test_event_pipeline_v01():
)
_, body = m.ToRequest(event, converters.TypeStructured, lambda x: x)
new_headers = ujson.load(body)
assert isinstance(body, io.BytesIO)
new_headers = json.load(body)
assert new_headers is not None
assert "cloudEventsVersion" in new_headers
assert "eventType" in new_headers

View File

@ -13,7 +13,7 @@
# under the License.
import io
import ujson
import json
import copy
from cloudevents.sdk import converters
@ -32,7 +32,7 @@ def test_binary_event_to_request_upstream():
event = m.FromRequest(
v02.Event(),
{"Content-Type": "application/cloudevents+json"},
io.StringIO(ujson.dumps(data.ce)),
io.StringIO(json.dumps(data.ce)),
lambda x: x.read()
)
@ -51,7 +51,7 @@ def test_structured_event_to_request_upstream():
event = m.FromRequest(
v02.Event(),
{"Content-Type": "application/cloudevents+json"},
io.StringIO(ujson.dumps(data.ce)),
io.StringIO(json.dumps(data.ce)),
lambda x: x.read()
)
assert event is not None
@ -73,7 +73,7 @@ def test_structured_event_to_request_v01():
event = m.FromRequest(
v01.Event(),
{"Content-Type": "application/cloudevents+json"},
io.StringIO(ujson.dumps(data.ce)),
io.StringIO(json.dumps(data.ce)),
lambda x: x.read()
)
assert event is not None

View File

@ -1,3 +1,2 @@
pbr!=2.1.0,>=2.0.0 # Apache-2.0
ujson==1.35
Sphinx==1.8.2

76
samples/with_requests.py Normal file
View File

@ -0,0 +1,76 @@
# 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.
import json
import requests
import sys
from cloudevents.sdk import converters
from cloudevents.sdk import marshaller
from cloudevents.sdk.event import v02
def run_binary(event, url):
binary_headers, binary_data = http_marshaller.ToRequest(
event, converters.TypeBinary, json.dumps)
print("binary CloudEvent")
for k, v in binary_headers.items():
print("{0}: {1}\r\n".format(k, v))
print(binary_data.getvalue())
response = requests.post(url,
headers=binary_headers,
data=binary_data.getvalue())
response.raise_for_status()
def run_structured(event, url):
structured_headers, structured_data = http_marshaller.ToRequest(
event, converters.TypeStructured, json.dumps
)
print("structured CloudEvent")
print(structured_data.getvalue())
response = requests.post(url,
headers=structured_headers,
data=structured_data.getvalue())
response.raise_for_status()
if __name__ == "__main__":
if len(sys.argv) < 3:
sys.exit("Usage: python with_requests.py "
"[binary | structured] "
"<CloudEvents controller URL>")
fmt = sys.argv[1]
url = sys.argv[2]
http_marshaller = marshaller.NewDefaultHTTPMarshaller()
event = (
v02.Event().
SetContentType("application/json").
SetData({"name": "denis"}).
SetEventID("my-id").
SetSource("<event-source").
SetEventType("cloudevent.event.type")
)
if "structured" == fmt:
run_structured(event, url)
elif "binary" == fmt:
run_binary(event, url)
else:
sys.exit("unknown format: {0}".format(fmt))