Skip to content

Commit 1f5af9e

Browse files
committed
Migrate to Pydantic V2, drop v1 shim, support Python 3.13 and 3.14
Fixes #452, #454. - Remove the try/except pydantic.v1 import shim in seven modules and import pydantic directly. - Replace .dict() with .model_dump() at nine call sites. - Add explicit = None defaults to 38 Optional fields. V1 treated Optional as implicitly defaulting to None; V2 does not. - Require pydantic>=2.0 and Python>=3.9. - Add 3.13 and 3.14 to the CI matrix, drop EOL 3.8. No behavior change: 158 tests pass before and after on 3.12.
1 parent d2956ff commit 1f5af9e

12 files changed

Lines changed: 57 additions & 78 deletions

File tree

‎.github/workflows/ci.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
strategy:
2222
fail-fast: false
2323
matrix:
24-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
24+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
2525

2626
defaults:
2727
run:

‎pyproject.toml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ description = "Python client for Replicate"
99
readme = "README.md"
1010
license = { file = "LICENSE" }
1111
authors = [{ name = "Replicate, Inc." }]
12-
requires-python = ">=3.8"
12+
requires-python = ">=3.9"
1313
dependencies = [
1414
"httpx>=0.21.0,<1",
1515
"packaging",
16-
"pydantic>1.10.7",
16+
"pydantic>=2.0",
1717
"typing_extensions>=4.5.0",
1818
]
1919

‎replicate/account.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Account(Resource):
1717
name: str
1818
"""The name of the account."""
1919

20-
github_url: Optional[str]
20+
github_url: Optional[str] = None
2121
"""The GitHub URL of the account."""
2222

2323

‎replicate/deployment.py‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313
)
1414
from replicate.resource import Namespace, Resource
1515

16-
try:
17-
from pydantic import v1 as pydantic # type: ignore
18-
except ImportError:
19-
import pydantic # type: ignore
16+
import pydantic
2017

2118

2219
if TYPE_CHECKING:
@@ -66,7 +63,7 @@ class Release(Resource):
6663
The time the release was created.
6764
"""
6865

69-
created_by: Optional[Account]
66+
created_by: Optional[Account] = None
7067
"""
7168
The account that created the release.
7269
"""
@@ -96,7 +93,7 @@ class Configuration(Resource):
9693
The deployment configuration.
9794
"""
9895

99-
current_release: Optional[Release]
96+
current_release: Optional[Release] = None
10097
"""
10198
The current release of the deployment.
10299
"""

‎replicate/exceptions.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@ class ReplicateError(ReplicateException):
2727
This class represents a problem details response as defined in RFC 7807.
2828
"""
2929

30-
type: Optional[str]
30+
type: Optional[str] = None
3131
"""A URI that identifies the error type."""
3232

33-
title: Optional[str]
33+
title: Optional[str] = None
3434
"""A short, human-readable summary of the error."""
3535

36-
status: Optional[int]
36+
status: Optional[int] = None
3737
"""The HTTP status code."""
3838

39-
detail: Optional[str]
39+
detail: Optional[str] = None
4040
"""A human-readable explanation specific to this occurrence of the error."""
4141

42-
instance: Optional[str]
42+
instance: Optional[str] = None
4343
"""A URI that identifies the specific occurrence of the error."""
4444

4545
def __init__( # pylint: disable=too-many-arguments

‎replicate/file.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class File(Resource):
4141
created_at: str
4242
"""The time the file was created."""
4343

44-
expires_at: Optional[str]
44+
expires_at: Optional[str] = None
4545
"""The time the file will expire."""
4646

4747
urls: Dict[str, str]

‎replicate/model.py‎

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
from replicate.resource import Namespace, Resource
1616
from replicate.version import Version, Versions
1717

18-
try:
19-
from pydantic import v1 as pydantic # type: ignore
20-
except ImportError:
21-
import pydantic # type: ignore
18+
import pydantic
2219

2320

2421
if TYPE_CHECKING:
@@ -48,7 +45,7 @@ class Model(Resource):
4845
The name of the model.
4946
"""
5047

51-
description: Optional[str]
48+
description: Optional[str] = None
5249
"""
5350
The description of the model.
5451
"""
@@ -58,17 +55,17 @@ class Model(Resource):
5855
The visibility of the model. Can be 'public' or 'private'.
5956
"""
6057

61-
github_url: Optional[str]
58+
github_url: Optional[str] = None
6259
"""
6360
The GitHub URL of the model.
6461
"""
6562

66-
paper_url: Optional[str]
63+
paper_url: Optional[str] = None
6764
"""
6865
The URL of the paper related to the model.
6966
"""
7067

71-
license_url: Optional[str]
68+
license_url: Optional[str] = None
7269
"""
7370
The URL of the license for the model.
7471
"""
@@ -78,17 +75,17 @@ class Model(Resource):
7875
The number of runs of the model.
7976
"""
8077

81-
cover_image_url: Optional[str]
78+
cover_image_url: Optional[str] = None
8279
"""
8380
The URL of the cover image for the model.
8481
"""
8582

86-
default_example: Optional[Prediction]
83+
default_example: Optional[Prediction] = None
8784
"""
8885
The default example of the model.
8986
"""
9087

91-
latest_version: Optional[Version]
88+
latest_version: Optional[Version] = None
9289
"""
9390
The latest version of the model.
9491
"""
@@ -137,7 +134,7 @@ def reload(self) -> None:
137134
"""
138135

139136
obj = self._client.models.get(f"{self.owner}/{self.name}")
140-
for name, value in obj.dict().items():
137+
for name, value in obj.model_dump().items():
141138
setattr(self, name, value)
142139

143140

‎replicate/pagination.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
Union,
1212
)
1313

14-
try:
15-
from pydantic import v1 as pydantic # type: ignore
16-
except ImportError:
17-
import pydantic # type: ignore
14+
import pydantic
1815

1916
from replicate.resource import Resource
2017

‎replicate/prediction.py‎

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@
2727
from replicate.stream import EventSource
2828
from replicate.version import Version
2929

30-
try:
31-
from pydantic import v1 as pydantic # type: ignore
32-
except ImportError:
33-
import pydantic # type: ignore
30+
import pydantic
3431

3532
if TYPE_CHECKING:
3633
from replicate.client import Client
@@ -58,31 +55,31 @@ class Prediction(Resource):
5855
status: Literal["starting", "processing", "succeeded", "failed", "canceled"]
5956
"""The status of the prediction."""
6057

61-
input: Optional[Dict[str, Any]]
58+
input: Optional[Dict[str, Any]] = None
6259
"""The input to the prediction."""
6360

64-
output: Optional[Any]
61+
output: Optional[Any] = None
6562
"""The output of the prediction."""
6663

67-
logs: Optional[str]
64+
logs: Optional[str] = None
6865
"""The logs of the prediction."""
6966

70-
error: Optional[str]
67+
error: Optional[str] = None
7168
"""The error encountered during the prediction, if any."""
7269

73-
metrics: Optional[Dict[str, Any]]
70+
metrics: Optional[Dict[str, Any]] = None
7471
"""Metrics for the prediction."""
7572

76-
created_at: Optional[str]
73+
created_at: Optional[str] = None
7774
"""When the prediction was created."""
7875

79-
started_at: Optional[str]
76+
started_at: Optional[str] = None
8077
"""When the prediction was started."""
8178

82-
completed_at: Optional[str]
79+
completed_at: Optional[str] = None
8380
"""When the prediction was completed, if finished."""
8481

85-
urls: Optional[Dict[str, str]]
82+
urls: Optional[Dict[str, str]] = None
8683
"""
8784
URLs associated with the prediction.
8885
@@ -214,7 +211,7 @@ def cancel(self) -> None:
214211
"""
215212

216213
canceled = self._client.predictions.cancel(self.id)
217-
for name, value in canceled.dict().items():
214+
for name, value in canceled.model_dump().items():
218215
setattr(self, name, value)
219216

220217
async def async_cancel(self) -> None:
@@ -223,7 +220,7 @@ async def async_cancel(self) -> None:
223220
"""
224221

225222
canceled = await self._client.predictions.async_cancel(self.id)
226-
for name, value in canceled.dict().items():
223+
for name, value in canceled.model_dump().items():
227224
setattr(self, name, value)
228225

229226
def reload(self) -> None:
@@ -232,7 +229,7 @@ def reload(self) -> None:
232229
"""
233230

234231
updated = self._client.predictions.get(self.id)
235-
for name, value in updated.dict().items():
232+
for name, value in updated.model_dump().items():
236233
setattr(self, name, value)
237234

238235
async def async_reload(self) -> None:
@@ -241,7 +238,7 @@ async def async_reload(self) -> None:
241238
"""
242239

243240
updated = await self._client.predictions.async_get(self.id)
244-
for name, value in updated.dict().items():
241+
for name, value in updated.model_dump().items():
245242
setattr(self, name, value)
246243

247244
def output_iterator(self) -> Iterator[Any]:

‎replicate/resource.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import abc
22
from typing import TYPE_CHECKING
33

4-
try:
5-
from pydantic import v1 as pydantic # type: ignore
6-
except ImportError:
7-
import pydantic # type: ignore
4+
import pydantic
85

96
if TYPE_CHECKING:
107
from replicate.client import Client

0 commit comments

Comments
 (0)