chore: Add copyright and fix missing type info
Signed-off-by: Tudor Plugaru <plugaru.tudor@protonmail.com>
This commit is contained in:
parent
35dee7d2c1
commit
42b4fe1d3a
|
@ -1,3 +1,17 @@
|
||||||
|
# Copyright 2018-Present The CloudEvents Authors
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
CloudEvent implementation for v1.0
|
CloudEvent implementation for v1.0
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -12,34 +12,48 @@
|
||||||
# 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 typing import Any, Optional
|
from typing import Any, Optional, Final
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import re
|
import re
|
||||||
|
|
||||||
REQUIRED_ATTRIBUTES = {"id", "source", "type", "specversion"}
|
REQUIRED_ATTRIBUTES: Final[set[str]] = {"id", "source", "type", "specversion"}
|
||||||
OPTIONAL_ATTRIBUTES = {"datacontenttype", "dataschema", "subject", "time"}
|
OPTIONAL_ATTRIBUTES: Final[set[str]] = {
|
||||||
|
"datacontenttype",
|
||||||
|
"dataschema",
|
||||||
|
"subject",
|
||||||
|
"time",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class CloudEvent:
|
class CloudEvent:
|
||||||
def __init__(self, attributes: dict, data: Optional[dict] = None) -> None:
|
"""
|
||||||
|
The CloudEvent Python wrapper contract exposing generically-available
|
||||||
|
properties and APIs.
|
||||||
|
|
||||||
|
Implementations might handle fields and have other APIs exposed but are
|
||||||
|
obliged to follow this contract.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, attributes: dict[str, Any], data: Optional[dict] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Create a new CloudEvent instance.
|
Create a new CloudEvent instance.
|
||||||
|
|
||||||
:param attributes: The attributes of the CloudEvent instance.
|
:param attributes: The attributes of the CloudEvent instance.
|
||||||
:type attributes: dict
|
|
||||||
:param data: The payload of the CloudEvent instance.
|
:param data: The payload of the CloudEvent instance.
|
||||||
:type data: Optional[dict]
|
|
||||||
|
|
||||||
:raises ValueError: If any of the required attributes are missing or have invalid values.
|
:raises ValueError: If any of the required attributes are missing or have invalid values.
|
||||||
:raises TypeError: If any of the attributes have invalid types.
|
:raises TypeError: If any of the attributes have invalid types.
|
||||||
"""
|
"""
|
||||||
self._validate_attribute(attributes)
|
self._validate_attribute(attributes)
|
||||||
self._attributes = attributes
|
self._attributes: dict = attributes
|
||||||
self._data = data
|
self._data: Optional[dict] = data
|
||||||
|
|
||||||
def _validate_attribute(self, attributes: dict) -> None:
|
@staticmethod
|
||||||
|
def _validate_attribute(attributes: dict) -> None:
|
||||||
"""
|
"""
|
||||||
Private method that validates the attributes of the CloudEvent as per the CloudEvents specification.
|
Validates the attributes of the CloudEvent as per the CloudEvents specification.
|
||||||
|
|
||||||
|
See https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#required-attributes
|
||||||
"""
|
"""
|
||||||
missing_attributes = [
|
missing_attributes = [
|
||||||
attr for attr in REQUIRED_ATTRIBUTES if attr not in attributes
|
attr for attr in REQUIRED_ATTRIBUTES if attr not in attributes
|
||||||
|
@ -95,27 +109,22 @@ class CloudEvent:
|
||||||
if not attributes["dataschema"]:
|
if not attributes["dataschema"]:
|
||||||
raise ValueError("Attribute 'dataschema' must not be empty")
|
raise ValueError("Attribute 'dataschema' must not be empty")
|
||||||
|
|
||||||
for custom_extension in (
|
for extension_attributes in (
|
||||||
set(attributes.keys()) - REQUIRED_ATTRIBUTES - OPTIONAL_ATTRIBUTES
|
set(attributes.keys()) - REQUIRED_ATTRIBUTES - OPTIONAL_ATTRIBUTES
|
||||||
):
|
):
|
||||||
if custom_extension == "data":
|
if extension_attributes == "data":
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Extension attribute 'data' is reserved and must not be used"
|
"Extension attribute 'data' is reserved and must not be used"
|
||||||
)
|
)
|
||||||
|
|
||||||
if not custom_extension[0].isalpha():
|
if not (1 <= len(extension_attributes) <= 20):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Extension attribute '{custom_extension}' should start with a letter"
|
f"Extension attribute '{extension_attributes}' should be between 1 and 20 characters long"
|
||||||
)
|
)
|
||||||
|
|
||||||
if not (5 <= len(custom_extension) <= 20):
|
if not re.match(r"^[a-z0-9]+$", extension_attributes):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Extension attribute '{custom_extension}' should be between 5 and 20 characters long"
|
f"Extension attribute '{extension_attributes}' should only contain lowercase letters and numbers"
|
||||||
)
|
|
||||||
|
|
||||||
if not re.match(r"^[a-z0-9]+$", custom_extension):
|
|
||||||
raise ValueError(
|
|
||||||
f"Extension attribute '{custom_extension}' should only contain lowercase letters and numbers"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_attribute(self, attribute: str) -> Optional[Any]:
|
def get_attribute(self, attribute: str) -> Optional[Any]:
|
||||||
|
@ -123,10 +132,8 @@ class CloudEvent:
|
||||||
Retrieve a value of an attribute of the event denoted by the given `attribute`.
|
Retrieve a value of an attribute of the event denoted by the given `attribute`.
|
||||||
|
|
||||||
:param attribute: The name of the event attribute to retrieve the value for.
|
:param attribute: The name of the event attribute to retrieve the value for.
|
||||||
:type attribute: str
|
|
||||||
|
|
||||||
:return: The event attribute value.
|
:return: The event attribute value.
|
||||||
:rtype: Optional[Any]
|
|
||||||
"""
|
"""
|
||||||
return self._attributes[attribute]
|
return self._attributes[attribute]
|
||||||
|
|
||||||
|
@ -135,6 +142,5 @@ class CloudEvent:
|
||||||
Retrieve data of the event.
|
Retrieve data of the event.
|
||||||
|
|
||||||
:return: The data of the event.
|
:return: The data of the event.
|
||||||
:rtype: Optional[dict]
|
|
||||||
"""
|
"""
|
||||||
return self._data
|
return self._data
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright 2018-Present The CloudEvents Authors
|
||||||
|
#
|
||||||
|
# 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.
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Copyright 2018-Present The CloudEvents Authors
|
||||||
|
#
|
||||||
|
# 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.
|
|
@ -1,3 +1,17 @@
|
||||||
|
# Copyright 2018-Present The CloudEvents Authors
|
||||||
|
#
|
||||||
|
# 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.core.v1.event import CloudEvent
|
from cloudevents.core.v1.event import CloudEvent
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -162,14 +176,13 @@ def test_dataschema_validation(dataschema: Any, error: str) -> None:
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"extension_name,error",
|
"extension_name,error",
|
||||||
[
|
[
|
||||||
("123", "Extension attribute '123' should start with a letter"),
|
|
||||||
(
|
(
|
||||||
"shrt",
|
"",
|
||||||
"Extension attribute 'shrt' should be between 5 and 20 characters long",
|
"Extension attribute '' should be between 1 and 20 characters long",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"thisisaverylongextension",
|
"thisisaverylongextension",
|
||||||
"Extension attribute 'thisisaverylongextension' should be between 5 and 20 characters long",
|
"Extension attribute 'thisisaverylongextension' should be between 1 and 20 characters long",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"ThisIsNotValid",
|
"ThisIsNotValid",
|
||||||
|
|
Loading…
Reference in New Issue