Skip to content

Commit 7212f67

Browse files
committed
Adds a pydantic V2 compatibility layer
1 parent 8104ce1 commit 7212f67

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

cloudevents/pydantic/event.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@
1818
from cloudevents.exceptions import PydanticFeatureNotInstalled
1919

2020
try:
21-
import pydantic
21+
from pydantic import VERSION as PYDANTIC_VERSION
22+
23+
pydantic_major_version = PYDANTIC_VERSION.split(".")[0]
24+
if pydantic_major_version == "2":
25+
from pydantic.v1 import BaseModel, Field
26+
else:
27+
from pydantic import BaseModel, Field
2228
except ImportError: # pragma: no cover # hard to test
2329
raise PydanticFeatureNotInstalled(
2430
"CloudEvents pydantic feature is not installed. "
@@ -84,7 +90,7 @@ def _ce_json_loads( # type: ignore[no-untyped-def]
8490
return conversion.to_dict(http.from_json(data))
8591

8692

87-
class CloudEvent(abstract.CloudEvent, pydantic.BaseModel): # type: ignore
93+
class CloudEvent(abstract.CloudEvent, BaseModel): # type: ignore
8894
"""
8995
A Python-friendly CloudEvent representation backed by Pydantic-modeled fields.
9096
@@ -97,7 +103,7 @@ def create(
97103
) -> "CloudEvent":
98104
return cls(attributes, data)
99105

100-
data: typing.Optional[typing.Any] = pydantic.Field(
106+
data: typing.Optional[typing.Any] = Field(
101107
title="Event Data",
102108
description=(
103109
"CloudEvents MAY include domain-specific information about the occurrence."
@@ -107,7 +113,7 @@ def create(
107113
" when those respective attributes are present."
108114
),
109115
)
110-
source: str = pydantic.Field(
116+
source: str = Field(
111117
title="Event Source",
112118
description=(
113119
"Identifies the context in which an event happened. Often this will include"
@@ -132,7 +138,7 @@ def create(
132138
example="https://github.com/cloudevents",
133139
)
134140

135-
id: str = pydantic.Field(
141+
id: str = Field(
136142
default_factory=attribute.default_id_selection_algorithm,
137143
title="Event ID",
138144
description=(
@@ -144,7 +150,7 @@ def create(
144150
),
145151
example="A234-1234-1234",
146152
)
147-
type: str = pydantic.Field(
153+
type: str = Field(
148154
title="Event Type",
149155
description=(
150156
"This attribute contains a value describing the type of event related to"
@@ -154,7 +160,7 @@ def create(
154160
),
155161
example="com.github.pull_request.opened",
156162
)
157-
specversion: attribute.SpecVersion = pydantic.Field(
163+
specversion: attribute.SpecVersion = Field(
158164
default=attribute.DEFAULT_SPECVERSION,
159165
title="Specification Version",
160166
description=(
@@ -168,7 +174,7 @@ def create(
168174
),
169175
example=attribute.DEFAULT_SPECVERSION,
170176
)
171-
time: typing.Optional[datetime.datetime] = pydantic.Field(
177+
time: typing.Optional[datetime.datetime] = Field(
172178
default_factory=attribute.default_time_selection_algorithm,
173179
title="Occurrence Time",
174180
description=(
@@ -182,7 +188,7 @@ def create(
182188
example="2018-04-05T17:31:00Z",
183189
)
184190

185-
subject: typing.Optional[str] = pydantic.Field(
191+
subject: typing.Optional[str] = Field(
186192
title="Event Subject",
187193
description=(
188194
"This describes the subject of the event in the context of the event"
@@ -202,7 +208,7 @@ def create(
202208
),
203209
example="123",
204210
)
205-
datacontenttype: typing.Optional[str] = pydantic.Field(
211+
datacontenttype: typing.Optional[str] = Field(
206212
title="Event Data Content Type",
207213
description=(
208214
"Content type of data value. This attribute enables data to carry any type"
@@ -211,7 +217,7 @@ def create(
211217
),
212218
example="text/xml",
213219
)
214-
dataschema: typing.Optional[str] = pydantic.Field(
220+
dataschema: typing.Optional[str] = Field(
215221
title="Event Data Schema",
216222
description=(
217223
"Identifies the schema that data adheres to. "

cloudevents/tests/test_pydantic_cloudevent.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,19 @@
1515
from json import loads
1616

1717
import pytest
18-
from pydantic import ValidationError
18+
from pydantic import VERSION as PYDANTIC_VERSION
1919

2020
from cloudevents.conversion import _json_or_string
2121
from cloudevents.exceptions import IncompatibleArgumentsError
2222
from cloudevents.pydantic import CloudEvent
2323
from cloudevents.sdk.event.attribute import SpecVersion
2424

25+
pydantic_major_version = PYDANTIC_VERSION.split(".")[0]
26+
if pydantic_major_version == "2":
27+
from pydantic.v1 import ValidationError
28+
else:
29+
from pydantic import ValidationError
30+
2531
_DUMMY_SOURCE = "dummy:source"
2632
_DUMMY_TYPE = "tests.cloudevents.override"
2733
_DUMMY_TIME = "2022-07-16T11:20:34.284130+00:00"

requirements/test.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ aiohttp
1010
Pillow
1111
requests
1212
flask
13-
pydantic>=1.0.0,<2.0
13+
pydantic>=1.0.0,<3.0

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,6 @@ def get_version(rel_path):
7979
include_package_data=True,
8080
version=pypi_config["version_target"],
8181
install_requires=["deprecation>=2.0,<3.0"],
82-
extras_require={"pydantic": "pydantic>=1.0.0,<2.0"},
82+
extras_require={"pydantic": "pydantic>=1.0.0,<3.0"},
8383
zip_safe=True,
8484
)

0 commit comments

Comments
 (0)