Skip to content

Commit

Permalink
Adds a pydantic V2 compatibility layer (#218)
Browse files Browse the repository at this point in the history
* feat: Pydantic V2 compatibility layer

Signed-off-by: Federico Busetti <[email protected]>

* Ignore incompatible import

Signed-off-by: Federico Busetti <[email protected]>

---------

Signed-off-by: Federico Busetti <[email protected]>
  • Loading branch information
febus982 authored Aug 28, 2023
1 parent 8104ce1 commit 739c71e
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 14 deletions.
28 changes: 17 additions & 11 deletions cloudevents/pydantic/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@
from cloudevents.exceptions import PydanticFeatureNotInstalled

try:
import pydantic
from pydantic import VERSION as PYDANTIC_VERSION

pydantic_major_version = PYDANTIC_VERSION.split(".")[0]
if pydantic_major_version == "2":
from pydantic.v1 import BaseModel, Field
else:
from pydantic import BaseModel, Field # type: ignore
except ImportError: # pragma: no cover # hard to test
raise PydanticFeatureNotInstalled(
"CloudEvents pydantic feature is not installed. "
Expand Down Expand Up @@ -84,7 +90,7 @@ def _ce_json_loads( # type: ignore[no-untyped-def]
return conversion.to_dict(http.from_json(data))


class CloudEvent(abstract.CloudEvent, pydantic.BaseModel): # type: ignore
class CloudEvent(abstract.CloudEvent, BaseModel): # type: ignore
"""
A Python-friendly CloudEvent representation backed by Pydantic-modeled fields.
Expand All @@ -97,7 +103,7 @@ def create(
) -> "CloudEvent":
return cls(attributes, data)

data: typing.Optional[typing.Any] = pydantic.Field(
data: typing.Optional[typing.Any] = Field(
title="Event Data",
description=(
"CloudEvents MAY include domain-specific information about the occurrence."
Expand All @@ -107,7 +113,7 @@ def create(
" when those respective attributes are present."
),
)
source: str = pydantic.Field(
source: str = Field(
title="Event Source",
description=(
"Identifies the context in which an event happened. Often this will include"
Expand All @@ -132,7 +138,7 @@ def create(
example="https://github.com/cloudevents",
)

id: str = pydantic.Field(
id: str = Field(
default_factory=attribute.default_id_selection_algorithm,
title="Event ID",
description=(
Expand All @@ -144,7 +150,7 @@ def create(
),
example="A234-1234-1234",
)
type: str = pydantic.Field(
type: str = Field(
title="Event Type",
description=(
"This attribute contains a value describing the type of event related to"
Expand All @@ -154,7 +160,7 @@ def create(
),
example="com.github.pull_request.opened",
)
specversion: attribute.SpecVersion = pydantic.Field(
specversion: attribute.SpecVersion = Field(
default=attribute.DEFAULT_SPECVERSION,
title="Specification Version",
description=(
Expand All @@ -168,7 +174,7 @@ def create(
),
example=attribute.DEFAULT_SPECVERSION,
)
time: typing.Optional[datetime.datetime] = pydantic.Field(
time: typing.Optional[datetime.datetime] = Field(
default_factory=attribute.default_time_selection_algorithm,
title="Occurrence Time",
description=(
Expand All @@ -182,7 +188,7 @@ def create(
example="2018-04-05T17:31:00Z",
)

subject: typing.Optional[str] = pydantic.Field(
subject: typing.Optional[str] = Field(
title="Event Subject",
description=(
"This describes the subject of the event in the context of the event"
Expand All @@ -202,7 +208,7 @@ def create(
),
example="123",
)
datacontenttype: typing.Optional[str] = pydantic.Field(
datacontenttype: typing.Optional[str] = Field(
title="Event Data Content Type",
description=(
"Content type of data value. This attribute enables data to carry any type"
Expand All @@ -211,7 +217,7 @@ def create(
),
example="text/xml",
)
dataschema: typing.Optional[str] = pydantic.Field(
dataschema: typing.Optional[str] = Field(
title="Event Data Schema",
description=(
"Identifies the schema that data adheres to. "
Expand Down
8 changes: 7 additions & 1 deletion cloudevents/tests/test_pydantic_cloudevent.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@
from json import loads

import pytest
from pydantic import ValidationError
from pydantic import VERSION as PYDANTIC_VERSION

from cloudevents.conversion import _json_or_string
from cloudevents.exceptions import IncompatibleArgumentsError
from cloudevents.pydantic import CloudEvent
from cloudevents.sdk.event.attribute import SpecVersion

pydantic_major_version = PYDANTIC_VERSION.split(".")[0]
if pydantic_major_version == "2":
from pydantic.v1 import ValidationError
else:
from pydantic import ValidationError

_DUMMY_SOURCE = "dummy:source"
_DUMMY_TYPE = "tests.cloudevents.override"
_DUMMY_TIME = "2022-07-16T11:20:34.284130+00:00"
Expand Down
2 changes: 1 addition & 1 deletion requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ aiohttp
Pillow
requests
flask
pydantic>=1.0.0,<2.0
pydantic>=1.0.0,<3.0
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ def get_version(rel_path):
include_package_data=True,
version=pypi_config["version_target"],
install_requires=["deprecation>=2.0,<3.0"],
extras_require={"pydantic": "pydantic>=1.0.0,<2.0"},
extras_require={"pydantic": "pydantic>=1.0.0,<3.0"},
zip_safe=True,
)

0 comments on commit 739c71e

Please sign in to comment.