diff --git a/cloudevents/sdk/converters/base.py b/cloudevents/sdk/converters/base.py index 18c9206..69bf8cb 100644 --- a/cloudevents/sdk/converters/base.py +++ b/cloudevents/sdk/converters/base.py @@ -21,8 +21,13 @@ class Converter(object): TYPE = None - def read(self, event, headers: dict, body: typing.IO, - data_unmarshaller: typing.Callable) -> base.BaseEvent: + def read( + self, + event, + headers: dict, + body: typing.IO, + data_unmarshaller: typing.Callable + ) -> base.BaseEvent: raise Exception("not implemented") def event_supported(self, event: object) -> bool: @@ -31,6 +36,9 @@ class Converter(object): def can_read(self, content_type: str) -> bool: raise Exception("not implemented") - def write(self, event: base.BaseEvent, - data_marshaller: typing.Callable) -> (dict, typing.IO): + def write( + self, + event: base.BaseEvent, + data_marshaller: typing.Callable + ) -> (dict, object): raise Exception("not implemented") diff --git a/cloudevents/sdk/converters/binary.py b/cloudevents/sdk/converters/binary.py index c313fda..84f4d4c 100644 --- a/cloudevents/sdk/converters/binary.py +++ b/cloudevents/sdk/converters/binary.py @@ -23,7 +23,7 @@ from cloudevents.sdk.event import v02 class BinaryHTTPCloudEventConverter(base.Converter): TYPE = "binary" - SUPPORTED_VERSIONS = [v02.Event, ] + SUPPORTED_VERSIONS = [v02.Event] def can_read(self, content_type: str) -> bool: return True @@ -31,17 +31,21 @@ class BinaryHTTPCloudEventConverter(base.Converter): def event_supported(self, event: object) -> bool: return type(event) in self.SUPPORTED_VERSIONS - def read(self, - event: event_base.BaseEvent, - headers: dict, body: typing.IO, - data_unmarshaller: typing.Callable) -> event_base.BaseEvent: + def read( + self, + event: event_base.BaseEvent, + headers: dict, + body: typing.IO, + data_unmarshaller: typing.Callable, + ) -> event_base.BaseEvent: if type(event) not in self.SUPPORTED_VERSIONS: raise exceptions.UnsupportedEvent(type(event)) event.UnmarshalBinary(headers, body, data_unmarshaller) return event - def write(self, event: event_base.BaseEvent, - data_marshaller: typing.Callable) -> (dict, typing.IO): + def write( + self, event: event_base.BaseEvent, data_marshaller: typing.Callable + ) -> (dict, typing.IO): return event.MarshalBinary(data_marshaller) diff --git a/cloudevents/sdk/converters/structured.py b/cloudevents/sdk/converters/structured.py index 1627376..589a977 100644 --- a/cloudevents/sdk/converters/structured.py +++ b/cloudevents/sdk/converters/structured.py @@ -30,17 +30,20 @@ class JSONHTTPCloudEventConverter(base.Converter): # structured format supported by both spec 0.1 and 0.2 return True - def read(self, event: event_base.BaseEvent, - headers: dict, - body: typing.IO, - data_unmarshaller: typing.Callable) -> event_base.BaseEvent: + def read( + self, + event: event_base.BaseEvent, + headers: dict, + body: typing.IO, + data_unmarshaller: typing.Callable, + ) -> event_base.BaseEvent: event.UnmarshalJSON(body, data_unmarshaller) return event - def write(self, - event: event_base.BaseEvent, - data_marshaller: typing.Callable) -> (dict, typing.IO): - http_headers = {'content-type': self.MIME_TYPE} + def write( + self, event: event_base.BaseEvent, data_marshaller: typing.Callable + ) -> (dict, typing.IO): + http_headers = {"content-type": self.MIME_TYPE} return http_headers, event.MarshalJSON(data_marshaller) diff --git a/cloudevents/sdk/event/base.py b/cloudevents/sdk/event/base.py index cd176d7..83b2e2a 100644 --- a/cloudevents/sdk/event/base.py +++ b/cloudevents/sdk/event/base.py @@ -18,7 +18,6 @@ import typing class EventGetterSetter(object): - def CloudEventVersion(self) -> str: raise Exception("not implemented") @@ -76,18 +75,13 @@ class EventGetterSetter(object): class BaseEvent(EventGetterSetter): - def Properties(self, with_nullable=False) -> dict: props = dict() for name, value in self.__dict__.items(): if str(name).startswith("ce__"): v = value.get() if v is not None or with_nullable: - props.update( - { - str(name).replace("ce__", ""): value.get() - } - ) + props.update({str(name).replace("ce__", ""): value.get()}) return props @@ -119,33 +113,38 @@ class BaseEvent(EventGetterSetter): props["data"] = data_marshaller(props.get("data")) return io.BytesIO(json.dumps(props).encode("utf-8")) - def UnmarshalJSON(self, b: typing.IO, - data_unmarshaller: typing.Callable): + def UnmarshalJSON(self, b: typing.IO, data_unmarshaller: typing.Callable): raw_ce = json.load(b) for name, value in raw_ce.items(): if name == "data": value = data_unmarshaller(value) self.Set(name, value) - def UnmarshalBinary(self, headers: dict, body: typing.IO, - data_unmarshaller: typing.Callable): - BINARY_MAPPING = { - 'content-type': 'contenttype', + def UnmarshalBinary( + self, + headers: dict, + body: typing.IO, + 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(): header = header.lower() - if header in BINARY_MAPPING: - self.Set(BINARY_MAPPING[header], value) + if header in binary_mapping: + self.Set(binary_mapping[header], value) elif header.startswith("ce-"): self.Set(header[3:], value) self.Set("data", data_unmarshaller(body)) def MarshalBinary( - self, data_marshaller: typing.Callable) -> (dict, object): + self, + data_marshaller: typing.Callable + ) -> (dict, object): headers = {} if self.ContentType(): headers["content-type"] = self.ContentType() @@ -159,5 +158,4 @@ class BaseEvent(EventGetterSetter): headers["ce-{0}".format(key)] = value data, _ = self.Get("data") - return headers, io.BytesIO( - str(data_marshaller(data)).encode("utf-8")) + return headers, data_marshaller(data) diff --git a/cloudevents/sdk/event/opt.py b/cloudevents/sdk/event/opt.py index ca2a9e6..2a18a52 100644 --- a/cloudevents/sdk/event/opt.py +++ b/cloudevents/sdk/event/opt.py @@ -14,7 +14,6 @@ class Option(object): - def __init__(self, name, value, is_required): self.name = name self.value = value @@ -25,7 +24,9 @@ class Option(object): if self.is_required and is_none: raise ValueError( "Attribute value error: '{0}', " - "invalid new value.".format(self.name)) + "" "invalid new value." + .format(self.name) + ) self.value = new_value diff --git a/cloudevents/sdk/event/v01.py b/cloudevents/sdk/event/v01.py index bc05670..beaf37c 100644 --- a/cloudevents/sdk/event/v01.py +++ b/cloudevents/sdk/event/v01.py @@ -12,25 +12,62 @@ # License for the specific language governing permissions and limitations # under the License. -from cloudevents.sdk.event import opt from cloudevents.sdk.event import base +from cloudevents.sdk.event import opt class Event(base.BaseEvent): - def __init__(self): self.ce__cloudEventsVersion = opt.Option( - "cloudEventsVersion", "0.1", True) - self.ce__eventType = opt.Option("eventType", None, True) + "cloudEventsVersion", + "0.1", + True + ) + self.ce__eventType = opt.Option( + "eventType", + None, + True + ) self.ce__eventTypeVersion = opt.Option( - "eventTypeVersion", None, False) - self.ce__source = opt.Option("source", None, True) - self.ce__eventID = opt.Option("eventID", None, True) - self.ce__eventTime = opt.Option("eventTime", None, True) - self.ce__schemaURL = opt.Option("schemaURL", None, False) - self.ce__contentType = opt.Option("contentType", None, False) - self.ce__data = opt.Option("data", None, False) - self.ce__extensions = opt.Option("extensions", dict(), False) + "eventTypeVersion", + None, + False + ) + self.ce__source = opt.Option( + "source", + None, + True + ) + self.ce__eventID = opt.Option( + "eventID", + None, + True + ) + self.ce__eventTime = opt.Option( + "eventTime", + None, + True + ) + self.ce__schemaURL = opt.Option( + "schemaURL", + None, + False + ) + self.ce__contentType = opt.Option( + "contentType", + 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__cloudEventsVersion.get() diff --git a/cloudevents/sdk/event/v02.py b/cloudevents/sdk/event/v02.py index 8da19c7..6871a93 100644 --- a/cloudevents/sdk/event/v02.py +++ b/cloudevents/sdk/event/v02.py @@ -12,12 +12,11 @@ # License for the specific language governing permissions and limitations # under the License. -from cloudevents.sdk.event import opt 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.2", True) self.ce__type = opt.Option("type", None, True) diff --git a/cloudevents/sdk/exceptions.py b/cloudevents/sdk/exceptions.py index 3c3e374..2f30db0 100644 --- a/cloudevents/sdk/exceptions.py +++ b/cloudevents/sdk/exceptions.py @@ -14,34 +14,34 @@ class UnsupportedEvent(Exception): - def __init__(self, event_class): - super().__init__("Invalid CloudEvent class: " - "'{0}'".format(event_class)) + super().__init__( + "Invalid CloudEvent class: '{0}'".format(event_class) + ) class InvalidDataUnmarshaller(Exception): - def __init__(self): - super().__init__( - "Invalid data unmarshaller, is not a callable") + super().__init__("Invalid data unmarshaller, is not a callable") class InvalidDataMarshaller(Exception): - def __init__(self): super().__init__( - "Invalid data marshaller, is not a callable") + "Invalid data marshaller, is not a callable" + ) class NoSuchConverter(Exception): def __init__(self, converter_type): super().__init__( - "No such converter {0}".format(converter_type)) + "No such converter {0}".format(converter_type) + ) class UnsupportedEventConverter(Exception): def __init__(self, content_type): super().__init__( "Unable to identify valid event converter " - "for content-type: '{0}'".format(content_type)) + "for content-type: '{0}'".format(content_type) + ) diff --git a/cloudevents/sdk/marshaller.py b/cloudevents/sdk/marshaller.py index 6dd2f68..22a2b70 100644 --- a/cloudevents/sdk/marshaller.py +++ b/cloudevents/sdk/marshaller.py @@ -35,14 +35,16 @@ class HTTPMarshaller(object): :param converters: a list of HTTP-to-CloudEvent-to-HTTP constructors :type converters: typing.List[base.Converter] """ - self.__converters = (c for c in converters) + self.__converters = [c for c in converters] self.__converters_by_type = {c.TYPE: c for c in converters} - def FromRequest(self, event: event_base.BaseEvent, - headers: dict, - body: typing.IO, - data_unmarshaller: - typing.Callable) -> event_base.BaseEvent: + def FromRequest( + self, + event: event_base.BaseEvent, + headers: dict, + body: typing.IO, + data_unmarshaller: typing.Callable, + ) -> event_base.BaseEvent: """ Reads a CloudEvent from an HTTP headers and request body :param event: CloudEvent placeholder @@ -59,8 +61,7 @@ class HTTPMarshaller(object): if not isinstance(data_unmarshaller, typing.Callable): raise exceptions.InvalidDataUnmarshaller() - content_type = headers.get( - "content-type", headers.get("Content-Type")) + content_type = headers.get("content-type", headers.get("Content-Type")) for cnvrtr in self.__converters: if cnvrtr.can_read(content_type) and cnvrtr.event_supported(event): @@ -68,11 +69,16 @@ class HTTPMarshaller(object): raise exceptions.UnsupportedEventConverter( "No registered marshaller for {0} in {1}".format( - content_type, self.__converters)) + content_type, self.__converters + ) + ) - def ToRequest(self, event: event_base.BaseEvent, - converter_type: str, - data_marshaller: typing.Callable) -> (dict, typing.IO): + def ToRequest( + self, + event: event_base.BaseEvent, + converter_type: str, + data_marshaller: typing.Callable, + ) -> (dict, typing.IO): """ Writes a CloudEvent into a HTTP-ready form of headers and request body :param event: CloudEvent @@ -101,14 +107,17 @@ def NewDefaultHTTPMarshaller() -> HTTPMarshaller: :return: an instance of HTTP marshaller :rtype: cloudevents.sdk.marshaller.HTTPMarshaller """ - return HTTPMarshaller([ - structured.NewJSONHTTPCloudEventConverter(), - binary.NewBinaryHTTPCloudEventConverter(), - ]) + return HTTPMarshaller( + [ + structured.NewJSONHTTPCloudEventConverter(), + binary.NewBinaryHTTPCloudEventConverter(), + ] + ) def NewHTTPMarshaller( - converters: typing.List[base.Converter]) -> HTTPMarshaller: + converters: typing.List[base.Converter] +) -> HTTPMarshaller: """ Creates the default HTTP marshaller with both structured and binary converters diff --git a/cloudevents/tests/data.py b/cloudevents/tests/data.py index 47c2a8d..534bb2f 100644 --- a/cloudevents/tests/data.py +++ b/cloudevents/tests/data.py @@ -25,7 +25,7 @@ headers = { "ce-id": ce_id, "ce-time": eventTime, "ce-source": source, - "Content-Type": contentType + "Content-Type": contentType, } ce = { "specversion": specversion, @@ -33,5 +33,5 @@ ce = { "id": ce_id, "time": eventTime, "source": source, - "contenttype": contentType + "contenttype": contentType, } diff --git a/cloudevents/tests/test_event_from_request_converter.py b/cloudevents/tests/test_event_from_request_converter.py index c0072f8..ea3baec 100644 --- a/cloudevents/tests/test_event_from_request_converter.py +++ b/cloudevents/tests/test_event_from_request_converter.py @@ -30,10 +30,7 @@ from cloudevents.tests import data def test_binary_converter_upstream(): m = marshaller.NewHTTPMarshaller( - [ - binary.NewBinaryHTTPCloudEventConverter() - ] - ) + [binary.NewBinaryHTTPCloudEventConverter()]) event = m.FromRequest(v02.Event(), data.headers, None, lambda x: x) assert event is not None assert event.Get("type") == (data.ce_type, True) @@ -42,15 +39,12 @@ def test_binary_converter_upstream(): def test_structured_converter_upstream(): m = marshaller.NewHTTPMarshaller( - [ - structured.NewJSONHTTPCloudEventConverter() - ] - ) + [structured.NewJSONHTTPCloudEventConverter()]) event = m.FromRequest( v02.Event(), {"Content-Type": "application/cloudevents+json"}, io.StringIO(json.dumps(data.ce)), - lambda x: x.read() + lambda x: x.read(), ) assert event is not None @@ -60,41 +54,40 @@ def test_structured_converter_upstream(): def test_binary_converter_v01(): m = marshaller.NewHTTPMarshaller( - [ - binary.NewBinaryHTTPCloudEventConverter() - ] - ) + [binary.NewBinaryHTTPCloudEventConverter()]) pytest.raises( exceptions.UnsupportedEventConverter, m.FromRequest, - v01.Event, {}, None, lambda x: x) + v01.Event, + {}, + None, + lambda x: x, + ) def test_unsupported_converter_v01(): m = marshaller.NewHTTPMarshaller( - [ - structured.NewJSONHTTPCloudEventConverter() - ] - ) + [structured.NewJSONHTTPCloudEventConverter()]) pytest.raises( exceptions.UnsupportedEventConverter, m.FromRequest, - v01.Event, {}, None, lambda x: x) + v01.Event, + {}, + None, + lambda x: x, + ) def test_structured_converter_v01(): m = marshaller.NewHTTPMarshaller( - [ - structured.NewJSONHTTPCloudEventConverter() - ] - ) + [structured.NewJSONHTTPCloudEventConverter()]) event = m.FromRequest( v01.Event(), {"Content-Type": "application/cloudevents+json"}, io.StringIO(json.dumps(data.ce)), - lambda x: x.read() + lambda x: x.read(), ) assert event is not None @@ -109,7 +102,7 @@ def test_default_http_marshaller_with_structured(): v02.Event(), {"Content-Type": "application/cloudevents+json"}, io.StringIO(json.dumps(data.ce)), - lambda x: x.read() + lambda x: x.read(), ) assert event is not None assert event.Get("type") == (data.ce_type, True) @@ -120,8 +113,7 @@ def test_default_http_marshaller_with_binary(): m = marshaller.NewDefaultHTTPMarshaller() event = m.FromRequest( - v02.Event(), - data.headers, + v02.Event(), data.headers, io.StringIO(json.dumps(data.body)), json.load ) @@ -133,17 +125,14 @@ def test_default_http_marshaller_with_binary(): def test_unsupported_event_configuration(): m = marshaller.NewHTTPMarshaller( - [ - binary.NewBinaryHTTPCloudEventConverter() - ] - ) + [binary.NewBinaryHTTPCloudEventConverter()]) pytest.raises( exceptions.UnsupportedEventConverter, m.FromRequest, v01.Event(), {"Content-Type": "application/cloudevents+json"}, io.StringIO(json.dumps(data.ce)), - lambda x: x.read() + lambda x: x.read(), ) @@ -152,12 +141,12 @@ def test_invalid_data_unmarshaller(): pytest.raises( exceptions.InvalidDataUnmarshaller, m.FromRequest, - v01.Event(), {}, None, None) + v01.Event(), {}, None, None + ) def test_invalid_data_marshaller(): m = marshaller.NewDefaultHTTPMarshaller() pytest.raises( - exceptions.InvalidDataMarshaller, - m.ToRequest, - v01.Event(), "blah", None) + exceptions.InvalidDataMarshaller, m.ToRequest, v01.Event(), "blah", None + ) diff --git a/cloudevents/tests/test_event_pipeline.py b/cloudevents/tests/test_event_pipeline.py index 7326c63..ddfa298 100644 --- a/cloudevents/tests/test_event_pipeline.py +++ b/cloudevents/tests/test_event_pipeline.py @@ -27,13 +27,13 @@ from cloudevents.tests import data def test_event_pipeline_upstream(): event = ( - v02.Event(). - SetContentType(data.contentType). - SetData(data.body). - SetEventID(data.ce_id). - SetSource(data.source). - SetEventTime(data.eventTime). - SetEventType(data.ce_type) + v02.Event() + .SetContentType(data.contentType) + .SetData(data.body) + .SetEventID(data.ce_id) + .SetSource(data.source) + .SetEventTime(data.eventTime) + .SetEventType(data.ce_type) ) m = marshaller.NewDefaultHTTPMarshaller() new_headers, body = m.ToRequest(event, converters.TypeBinary, lambda x: x) @@ -44,29 +44,25 @@ def test_event_pipeline_upstream(): assert "ce-id" in new_headers assert "ce-time" in new_headers assert "content-type" in new_headers - assert isinstance(body, io.BytesIO) - assert data.body == body.read().decode("utf-8") + assert isinstance(body, str) + assert data.body == body def test_event_pipeline_v01(): event = ( - v01.Event(). - SetContentType(data.contentType). - SetData(data.body). - SetEventID(data.ce_id). - SetSource(data.source). - SetEventTime(data.eventTime). - SetEventType(data.ce_type) - ) - m = marshaller.NewHTTPMarshaller( - [ - structured.NewJSONHTTPCloudEventConverter() - ] + v01.Event() + .SetContentType(data.contentType) + .SetData(data.body) + .SetEventID(data.ce_id) + .SetSource(data.source) + .SetEventTime(data.eventTime) + .SetEventType(data.ce_type) ) + m = marshaller.NewHTTPMarshaller([structured.NewJSONHTTPCloudEventConverter()]) _, body = m.ToRequest(event, converters.TypeStructured, lambda x: x) assert isinstance(body, io.BytesIO) - new_headers = json.load(io.TextIOWrapper(body, encoding='utf-8')) + new_headers = json.load(io.TextIOWrapper(body, encoding="utf-8")) assert new_headers is not None assert "cloudEventsVersion" in new_headers assert "eventType" in new_headers diff --git a/cloudevents/tests/test_event_to_request_converter.py b/cloudevents/tests/test_event_to_request_converter.py index 6f543e9..ebbaa6e 100644 --- a/cloudevents/tests/test_event_to_request_converter.py +++ b/cloudevents/tests/test_event_to_request_converter.py @@ -33,7 +33,7 @@ def test_binary_event_to_request_upstream(): v02.Event(), {"Content-Type": "application/cloudevents+json"}, io.StringIO(json.dumps(data.ce)), - lambda x: x.read() + lambda x: x.read(), ) assert event is not None @@ -50,10 +50,7 @@ def test_structured_event_to_request_upstream(): m = marshaller.NewDefaultHTTPMarshaller() http_headers = {"content-type": "application/cloudevents+json"} event = m.FromRequest( - v02.Event(), - http_headers, - io.StringIO(json.dumps(data.ce)), - lambda x: x.read() + v02.Event(), http_headers, io.StringIO(json.dumps(data.ce)), lambda x: x.read() ) assert event is not None assert event.Get("type") == (data.ce_type, True) @@ -69,17 +66,10 @@ def test_structured_event_to_request_upstream(): def test_structured_event_to_request_v01(): copy_of_ce = copy.deepcopy(data.ce) - m = marshaller.NewHTTPMarshaller( - [ - structured.NewJSONHTTPCloudEventConverter() - ] - ) + m = marshaller.NewHTTPMarshaller([structured.NewJSONHTTPCloudEventConverter()]) http_headers = {"content-type": "application/cloudevents+json"} 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.ce)), lambda x: x.read() ) assert event is not None assert event.Get("type") == (data.ce_type, True) diff --git a/cloudevents/tests/test_with_sanic.py b/cloudevents/tests/test_with_sanic.py new file mode 100644 index 0000000..d60196e --- /dev/null +++ b/cloudevents/tests/test_with_sanic.py @@ -0,0 +1,77 @@ +# 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 import marshaller +from cloudevents.sdk import converters +from cloudevents.sdk.event import v02 + +from sanic import Sanic +from sanic import response + +from cloudevents.tests import data as test_data + + +m = marshaller.NewDefaultHTTPMarshaller() +app = Sanic(__name__) + + +@app.route("/is-ok", ["POST"]) +async def is_ok(request): + m.FromRequest( + v02.Event(), + dict(request.headers), + request.body, + lambda x: x + ) + return response.text("OK") + + +@app.route("/echo", ["POST"]) +async def echo(request): + event = m.FromRequest( + v02.Event(), + dict(request.headers), + request.body, + lambda x: x + ) + hs, body = m.ToRequest(event, converters.TypeBinary, lambda x: x) + return response.text(body, headers=hs) + + +def test_reusable_marshaller(): + for i in range(10): + _, r = app.test_client.post( + "/is-ok", headers=test_data.headers, data=test_data.body + ) + assert r.status == 200 + + +def test_web_app_integration(): + _, r = app.test_client.post( + "/is-ok", headers=test_data.headers, data=test_data.body + ) + assert r.status == 200 + + +def test_web_app_echo(): + _, r = app.test_client.post("/echo", headers=test_data.headers, data=test_data.body) + assert r.status == 200 + event = m.FromRequest(v02.Event(), dict(r.headers), r.body, lambda x: x) + assert event is not None + props = event.Properties() + for key in test_data.headers.keys(): + if key == "Content-Type": + assert "contenttype" in props + else: + assert key.lstrip("ce-") in props diff --git a/test-requirements.txt b/test-requirements.txt index 1515f34..e9df186 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,10 @@ -flake8<2.7.0,>=2.6.0 -hacking==1.1.0 +flake8 +pep8-naming==0.5.0 +flake8-import-order +flake8-print +flake8-strict pytest==4.0.0 pytest-cov==2.4.0 +# web app tests +sanic +aiohttp \ No newline at end of file diff --git a/tox.ini b/tox.ini index 43768cf..75225fe 100644 --- a/tox.ini +++ b/tox.ini @@ -18,7 +18,8 @@ whitelist_externals = find go docker [testenv:pep8] -commands = flake8 +commands = + flake8 [testenv:venv] commands = {posargs} @@ -30,6 +31,6 @@ commands = pytest -v -s --tb=long --cov=cloudevents {toxinidir}/cloudevents/test commands = pytest -v -s --tb=long --cov=cloudevents {toxinidir}/cloudevents/tests [flake8] -ignore = H405,H404,H403,H401,H306 +ignore = H405,H404,H403,H401,H306,S101,N802,N803,N806,I202,I201 show-source = True -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,docs,venv,.venv,docs,etc +exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,docs,venv,.venv,docs,etc,samples,tests