# Path: cloudevents/http/event.py
# class CloudEvent:
#     """
#     Python-friendly cloudevent class supporting v1 events
#     Supports both binary and structured mode CloudEvents
#     """
# 
#     def __init__(
#         self, attributes: typing.Dict[str, str], data: typing.Any = None
#     ):
#         """
#         Event Constructor
#         :param attributes: a dict with cloudevent attributes. Minimally
#             expects the attributes 'type' and 'source'. If not given the
#             attributes 'specversion', 'id' or 'time', this will create
#             those attributes with default values.
#             e.g. {
#                 "content-type": "application/cloudevents+json",
#                 "id": "16fb5f0b-211e-1102-3dfe-ea6e2806f124",
#                 "source": "<event-source>",
#                 "type": "cloudevent.event.type",
#                 "specversion": "0.2"
#             }
#         :type attributes: typing.Dict[str, str]
#         :param data: The payload of the event, as a python object
#         :type data: typing.Any
#         """
#         self._attributes = {k.lower(): v for k, v in attributes.items()}
#         self.data = data
#         if "specversion" not in self._attributes:
#             self._attributes["specversion"] = "1.0"
#         if "id" not in self._attributes:
#             self._attributes["id"] = str(uuid.uuid4())
#         if "time" not in self._attributes:
#             self._attributes["time"] = datetime.datetime.now(
#                 datetime.timezone.utc
#             ).isoformat()
# 
#         if self._attributes["specversion"] not in _required_by_version:
#             raise cloud_exceptions.MissingRequiredFields(
#                 f"Invalid specversion: {self._attributes['specversion']}"
#             )
#         # There is no good way to default 'source' and 'type', so this
#         # checks for those (or any new required attributes).
#         required_set = _required_by_version[self._attributes["specversion"]]
#         if not required_set <= self._attributes.keys():
#             raise cloud_exceptions.MissingRequiredFields(
#                 f"Missing required keys: {required_set - self._attributes.keys()}"
#             )
# 
#     def __eq__(self, other):
#         return self.data == other.data and self._attributes == other._attributes
# 
#     # Data access is handled via `.data` member
#     # Attribute access is managed via Mapping type
#     def __getitem__(self, key):
#         return self._attributes[key]
# 
#     def __setitem__(self, key, value):
#         self._attributes[key] = value
# 
#     def __delitem__(self, key):
#         del self._attributes[key]
# 
#     def __iter__(self):
#         return iter(self._attributes)
# 
#     def __len__(self):
#         return len(self._attributes)
# 
#     def __contains__(self, key):
#         return key in self._attributes
# 
#     def __repr__(self):
#         return str({"attributes": self._attributes, "data": self.data})
# 
# Path: cloudevents/http/json_methods.py
# def from_json(
#     data: typing.Union[str, bytes],
#     data_unmarshaller: types.UnmarshallerType = None,
# ) -> CloudEvent:
#     """
#     Cast json encoded data into an CloudEvent
#     :param data: json encoded cloudevent data
#     :type event: typing.Union[str, bytes]
#     :param data_unmarshaller: Callable function which will cast data to a
#         python object
#     :type data_unmarshaller: typing.Callable
#     :returns: CloudEvent representing given cloudevent json object
#     """
#     return from_http(headers={}, data=data, data_unmarshaller=data_unmarshaller)
# 
# def to_json(
#     event: CloudEvent, data_marshaller: types.MarshallerType = None
# ) -> typing.Union[str, bytes]:
#     """
#     Cast an CloudEvent into a json object
#     :param event: CloudEvent which will be converted into a json object
#     :type event: CloudEvent
#     :param data_marshaller: Callable function which will cast event.data
#         into a json object
#     :type data_marshaller: typing.Callable
#     :returns: json object representing the given event
#     """
#     return to_structured(event, data_marshaller=data_marshaller)[1]


import base64
import json
import pytest
from cloudevents.http import CloudEvent, from_json, to_json
    assert event_dict["data"] == test_data


@pytest.mark.parametrize("specversion", ["0.3", "1.0"])
def test_to_json_base64(specversion):
    data = b"test123"

    event = CloudEvent(test_attributes, data)
    event_json = to_json(event)
    event_dict = json.loads(event_json)

    for key, val in test_attributes.items():
        assert event_dict[key] == val

    # test data was properly marshalled into data_base64
    data_base64 = event_dict["data_base64"].encode()
    test_data_base64 = base64.b64encode(data)

    assert data_base64 == test_data_base64


@pytest.mark.parametrize("specversion", ["0.3", "1.0"])
def test_from_json(specversion):
    payload = {
        "type": "com.example.string",
        "source": "https://example.com/event-producer",
        "id": "1234",
        "specversion": specversion,
        "data": {"data-key": "val"},
    }

# Path: cloudevents/http/event.py
# class CloudEvent:
#     """
#     Python-friendly cloudevent class supporting v1 events
#     Supports both binary and structured mode CloudEvents
#     """
# 
#     def __init__(
#         self, attributes: typing.Dict[str, str], data: typing.Any = None
#     ):
#         """
#         Event Constructor
#         :param attributes: a dict with cloudevent attributes. Minimally
#             expects the attributes 'type' and 'source'. If not given the
#             attributes 'specversion', 'id' or 'time', this will create
#             those attributes with default values.
#             e.g. {
#                 "content-type": "application/cloudevents+json",
#                 "id": "16fb5f0b-211e-1102-3dfe-ea6e2806f124",
#                 "source": "<event-source>",
#                 "type": "cloudevent.event.type",
#                 "specversion": "0.2"
#             }
#         :type attributes: typing.Dict[str, str]
#         :param data: The payload of the event, as a python object
#         :type data: typing.Any
#         """
#         self._attributes = {k.lower(): v for k, v in attributes.items()}
#         self.data = data
#         if "specversion" not in self._attributes:
#             self._attributes["specversion"] = "1.0"
#         if "id" not in self._attributes:
#             self._attributes["id"] = str(uuid.uuid4())
#         if "time" not in self._attributes:
#             self._attributes["time"] = datetime.datetime.now(
#                 datetime.timezone.utc
#             ).isoformat()
# 
#         if self._attributes["specversion"] not in _required_by_version:
#             raise cloud_exceptions.MissingRequiredFields(
#                 f"Invalid specversion: {self._attributes['specversion']}"
#             )
#         # There is no good way to default 'source' and 'type', so this
#         # checks for those (or any new required attributes).
#         required_set = _required_by_version[self._attributes["specversion"]]
#         if not required_set <= self._attributes.keys():
#             raise cloud_exceptions.MissingRequiredFields(
#                 f"Missing required keys: {required_set - self._attributes.keys()}"
#             )
# 
#     def __eq__(self, other):
#         return self.data == other.data and self._attributes == other._attributes
# 
#     # Data access is handled via `.data` member
#     # Attribute access is managed via Mapping type
#     def __getitem__(self, key):
#         return self._attributes[key]
# 
#     def __setitem__(self, key, value):
#         self._attributes[key] = value
# 
#     def __delitem__(self, key):
#         del self._attributes[key]
# 
#     def __iter__(self):
#         return iter(self._attributes)
# 
#     def __len__(self):
#         return len(self._attributes)
# 
#     def __contains__(self, key):
#         return key in self._attributes
# 
#     def __repr__(self):
#         return str({"attributes": self._attributes, "data": self.data})
# 
# Path: cloudevents/http/json_methods.py
# def from_json(
#     data: typing.Union[str, bytes],
#     data_unmarshaller: types.UnmarshallerType = None,
# ) -> CloudEvent:
#     """
#     Cast json encoded data into an CloudEvent
#     :param data: json encoded cloudevent data
#     :type event: typing.Union[str, bytes]
#     :param data_unmarshaller: Callable function which will cast data to a
#         python object
#     :type data_unmarshaller: typing.Callable
#     :returns: CloudEvent representing given cloudevent json object
#     """
#     return from_http(headers={}, data=data, data_unmarshaller=data_unmarshaller)
# 
# def to_json(
#     event: CloudEvent, data_marshaller: types.MarshallerType = None
# ) -> typing.Union[str, bytes]:
#     """
#     Cast an CloudEvent into a json object
#     :param event: CloudEvent which will be converted into a json object
#     :type event: CloudEvent
#     :param data_marshaller: Callable function which will cast event.data
#         into a json object
#     :type data_marshaller: typing.Callable
#     :returns: json object representing the given event
#     """
#     return to_structured(event, data_marshaller=data_marshaller)[1]


# Path: cloudevents/tests/test_http_json_methods.py
import base64
import json
import pytest
from cloudevents.http import CloudEvent, from_json, to_json

    assert event_dict["data"] == test_data


@pytest.mark.parametrize("specversion", ["0.3", "1.0"])
def test_to_json_base64(specversion):
    data = b"test123"

    event = CloudEvent(test_attributes, data)
    event_json = to_json(event)
    event_dict = json.loads(event_json)

    for key, val in test_attributes.items():
        assert event_dict[key] == val

    # test data was properly marshalled into data_base64
    data_base64 = event_dict["data_base64"].encode()
    test_data_base64 = base64.b64encode(data)

    assert data_base64 == test_data_base64


@pytest.mark.parametrize("specversion", ["0.3", "1.0"])
def test_from_json(specversion):
    payload = {
        "type": "com.example.string",
        "source": "https://example.com/event-producer",
        "id": "1234",
        "specversion": specversion,
        "data": {"data-key": "val"},
    }

    event = from_json(json.dumps(payload))