Skip to content

Commit 043236b

Browse files
committed
Consolidating return types
Closes: cloudevents#6 Closes: cloudevents#4 Signed-off-by: Denis Makogon <denys.makogon@oracle.com>
1 parent f4a3c05 commit 043236b

8 files changed

+106
-19
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ headers, body = m.ToRequest(event, converters.TypeStructured, lambda x: x)
7070

7171
```
7272

73+
## HOWTOs with various Python HTTP frameworks
74+
75+
In this topic you'd find various example how to integrate an SDK with various HTTP frameworks.
76+
77+
### Python requests
78+
79+
80+
7381
The goal of this package is to provide support for all released versions of CloudEvents, ideally while maintaining
7482
the same API. It will use semantic versioning with following rules:
7583
* MAJOR version increments when backwards incompatible changes is introduced.

cloudevents/sdk/converters/binary.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ def write(self, event: event_base.BaseEvent,
3939
if not isinstance(data_marshaller, typing.Callable):
4040
raise exceptions.InvalidDataMarshaller()
4141

42-
hs, data = event.MarshalBinary()
43-
return hs, data_marshaller(data)
42+
return event.MarshalBinary(data_marshaller)
4443

4544

4645
def NewBinaryHTTPCloudEventConverter() -> BinaryHTTPCloudEventConverter:

cloudevents/sdk/event/base.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# under the License.
1414

1515
import io
16-
import ujson
16+
import json
1717
import typing
1818

1919

@@ -117,11 +117,11 @@ def Set(self, key: str, value: object):
117117
def MarshalJSON(self, data_marshaller: typing.Callable) -> typing.IO:
118118
props = self.Properties()
119119
props["data"] = data_marshaller(props.get("data"))
120-
return io.StringIO(ujson.dumps(props))
120+
return io.BytesIO(json.dumps(props).encode("utf-8"))
121121

122122
def UnmarshalJSON(self, b: typing.IO,
123123
data_unmarshaller: typing.Callable):
124-
raw_ce = ujson.load(b)
124+
raw_ce = json.load(b)
125125
for name, value in raw_ce.items():
126126
if name == "data":
127127
value = data_unmarshaller(value)
@@ -143,7 +143,8 @@ def UnmarshalBinary(self, headers: dict, body: typing.IO,
143143
self.Set("extensions", exts)
144144
self.Set("data", data_unmarshaller(body))
145145

146-
def MarshalBinary(self) -> (dict, object):
146+
def MarshalBinary(
147+
self, data_marshaller: typing.Callable) -> (dict, object):
147148
headers = {}
148149
props = self.Properties()
149150
for key, value in props.items():
@@ -156,4 +157,5 @@ def MarshalBinary(self) -> (dict, object):
156157
headers.update(**exts)
157158

158159
data, _ = self.Get("data")
159-
return headers, data
160+
return headers, io.BytesIO(
161+
str(data_marshaller(data)).encode("utf-8"))

cloudevents/tests/test_event_from_request_converter.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15+
import json
1516
import pytest
1617
import io
17-
import ujson
1818

1919
from cloudevents.sdk import exceptions
2020
from cloudevents.sdk import marshaller
@@ -49,7 +49,7 @@ def test_structured_converter_upstream():
4949
event = m.FromRequest(
5050
v02.Event(),
5151
{"Content-Type": "application/cloudevents+json"},
52-
io.StringIO(ujson.dumps(data.ce)),
52+
io.StringIO(json.dumps(data.ce)),
5353
lambda x: x.read()
5454
)
5555

@@ -81,7 +81,7 @@ def test_structured_converter_v01():
8181
event = m.FromRequest(
8282
v01.Event(),
8383
{"Content-Type": "application/cloudevents+json"},
84-
io.StringIO(ujson.dumps(data.ce)),
84+
io.StringIO(json.dumps(data.ce)),
8585
lambda x: x.read()
8686
)
8787

@@ -96,7 +96,7 @@ def test_default_http_marshaller():
9696
event = m.FromRequest(
9797
v02.Event(),
9898
{"Content-Type": "application/cloudevents+json"},
99-
io.StringIO(ujson.dumps(data.ce)),
99+
io.StringIO(json.dumps(data.ce)),
100100
lambda x: x.read()
101101
)
102102
assert event is not None

cloudevents/tests/test_event_pipeline.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414

15-
import ujson
15+
import io
16+
import json
1617

1718
from cloudevents.sdk.event import v01
1819
from cloudevents.sdk.event import v02
@@ -43,7 +44,8 @@ def test_event_pipeline_upstream():
4344
assert "ce-id" in new_headers
4445
assert "ce-time" in new_headers
4546
assert "ce-contenttype" in new_headers
46-
assert data.body == body
47+
assert isinstance(body, io.BytesIO)
48+
assert data.body == body.read().decode("utf-8")
4749

4850

4951
def test_event_pipeline_v01():
@@ -63,7 +65,8 @@ def test_event_pipeline_v01():
6365
)
6466

6567
_, body = m.ToRequest(event, converters.TypeStructured, lambda x: x)
66-
new_headers = ujson.load(body)
68+
assert isinstance(body, io.BytesIO)
69+
new_headers = json.load(body)
6770
assert new_headers is not None
6871
assert "cloudEventsVersion" in new_headers
6972
assert "eventType" in new_headers

cloudevents/tests/test_event_to_request_converter.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# under the License.
1414

1515
import io
16-
import ujson
16+
import json
1717
import copy
1818

1919
from cloudevents.sdk import converters
@@ -32,7 +32,7 @@ def test_binary_event_to_request_upstream():
3232
event = m.FromRequest(
3333
v02.Event(),
3434
{"Content-Type": "application/cloudevents+json"},
35-
io.StringIO(ujson.dumps(data.ce)),
35+
io.StringIO(json.dumps(data.ce)),
3636
lambda x: x.read()
3737
)
3838

@@ -51,7 +51,7 @@ def test_structured_event_to_request_upstream():
5151
event = m.FromRequest(
5252
v02.Event(),
5353
{"Content-Type": "application/cloudevents+json"},
54-
io.StringIO(ujson.dumps(data.ce)),
54+
io.StringIO(json.dumps(data.ce)),
5555
lambda x: x.read()
5656
)
5757
assert event is not None
@@ -73,7 +73,7 @@ def test_structured_event_to_request_v01():
7373
event = m.FromRequest(
7474
v01.Event(),
7575
{"Content-Type": "application/cloudevents+json"},
76-
io.StringIO(ujson.dumps(data.ce)),
76+
io.StringIO(json.dumps(data.ce)),
7777
lambda x: x.read()
7878
)
7979
assert event is not None

requirements.txt

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
pbr!=2.1.0,>=2.0.0 # Apache-2.0
2-
ujson==1.35
32
Sphinx==1.8.2

samples/with_requests.py

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
15+
import json
16+
import requests
17+
import sys
18+
19+
from cloudevents.sdk import converters
20+
from cloudevents.sdk import marshaller
21+
22+
from cloudevents.sdk.event import v02
23+
24+
25+
def run_binary(event, url):
26+
binary_headers, binary_data = http_marshaller.ToRequest(
27+
event, converters.TypeBinary, json.dumps)
28+
29+
print("binary CloudEvent")
30+
for k, v in binary_headers.items():
31+
print("{0}: {1}\r\n".format(k, v))
32+
print(binary_data.getvalue())
33+
response = requests.post(url,
34+
headers=binary_headers,
35+
data=binary_data.getvalue())
36+
response.raise_for_status()
37+
38+
39+
def run_structured(event, url):
40+
structured_headers, structured_data = http_marshaller.ToRequest(
41+
event, converters.TypeStructured, json.dumps
42+
)
43+
print("structured CloudEvent")
44+
print(structured_data.getvalue())
45+
46+
response = requests.post(url,
47+
headers=structured_headers,
48+
data=structured_data.getvalue())
49+
response.raise_for_status()
50+
51+
52+
if __name__ == "__main__":
53+
54+
if len(sys.argv) < 3:
55+
sys.exit("Usage: python with_requests.py "
56+
"[binary | structured] "
57+
"<CloudEvents controller URL>")
58+
59+
fmt = sys.argv[1]
60+
url = sys.argv[2]
61+
62+
http_marshaller = marshaller.NewDefaultHTTPMarshaller()
63+
event = (
64+
v02.Event().
65+
SetContentType("application/json").
66+
SetData({"name": "denis"}).
67+
SetEventID("my-id").
68+
SetSource("<event-source").
69+
SetEventType("cloudevent.event.type")
70+
)
71+
if "structured" == fmt:
72+
run_structured(event, url)
73+
elif "binary" == fmt:
74+
run_binary(event, url)
75+
else:
76+
sys.exit("unknown format: {0}".format(fmt))

0 commit comments

Comments
 (0)