Skip to content

Commit ae85a60

Browse files
release: 2.0.0-alpha.23 (#60)
* chore(internal): add Sequence related utils * feat(types): replace List[str] with SequenceNotStr in params * feat: improve future compat with pydantic v3 * chore(internal): move mypy configurations to `pyproject.toml` file * release: 2.0.0-alpha.23 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
1 parent 951d9c5 commit ae85a60

19 files changed

+560
-187
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "2.0.0-alpha.22"
2+
".": "2.0.0-alpha.23"
33
}

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Changelog
22

3+
## 2.0.0-alpha.23 (2025-09-04)
4+
5+
Full Changelog: [v2.0.0-alpha.22...v2.0.0-alpha.23](https://github.com/replicate/replicate-python-stainless/compare/v2.0.0-alpha.22...v2.0.0-alpha.23)
6+
7+
### Features
8+
9+
* add get_path_url() function support for migration compatibility ([#61](https://github.com/replicate/replicate-python-stainless/issues/61)) ([951d9c5](https://github.com/replicate/replicate-python-stainless/commit/951d9c5cf4c72bb9346e4bde0d545abb1ab84741))
10+
* improve future compat with pydantic v3 ([06dfa6b](https://github.com/replicate/replicate-python-stainless/commit/06dfa6b2adf4cd5cfcb18f2602ca7d67182296a8))
11+
* **types:** replace List[str] with SequenceNotStr in params ([56dc0f2](https://github.com/replicate/replicate-python-stainless/commit/56dc0f2a68e6eb989574e9053f09161096c86eb3))
12+
13+
14+
### Chores
15+
16+
* add agents files ([#59](https://github.com/replicate/replicate-python-stainless/issues/59)) ([b726483](https://github.com/replicate/replicate-python-stainless/commit/b726483034244776bf9b9c45504eb1eb1b2f3085))
17+
* **internal:** add Sequence related utils ([5a8f513](https://github.com/replicate/replicate-python-stainless/commit/5a8f513755a94211fa35b59527cf57965105ff6a))
18+
* **internal:** move mypy configurations to `pyproject.toml` file ([696d2c1](https://github.com/replicate/replicate-python-stainless/commit/696d2c18ebf0a38213371eb4fa1898fc85fc2581))
19+
320
## 2.0.0-alpha.22 (2025-08-28)
421

522
Full Changelog: [v2.0.0-alpha.21...v2.0.0-alpha.22](https://github.com/replicate/replicate-python-stainless/compare/v2.0.0-alpha.21...v2.0.0-alpha.22)

mypy.ini

Lines changed: 0 additions & 50 deletions
This file was deleted.

pyproject.toml

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "replicate"
3-
version = "2.0.0-alpha.22"
3+
version = "2.0.0-alpha.23"
44
description = "The official Python library for the replicate API"
55
dynamic = ["readme"]
66
license = "Apache-2.0"
@@ -158,6 +158,58 @@ reportOverlappingOverload = false
158158
reportImportCycles = false
159159
reportPrivateUsage = false
160160

161+
[tool.mypy]
162+
pretty = true
163+
show_error_codes = true
164+
165+
# Exclude _files.py because mypy isn't smart enough to apply
166+
# the correct type narrowing and as this is an internal module
167+
# it's fine to just use Pyright.
168+
#
169+
# We also exclude our `tests` as mypy doesn't always infer
170+
# types correctly and Pyright will still catch any type errors.
171+
exclude = ['src/replicate/_files.py', '_dev/.*.py', 'tests/.*']
172+
173+
strict_equality = true
174+
implicit_reexport = true
175+
check_untyped_defs = true
176+
no_implicit_optional = true
177+
178+
warn_return_any = true
179+
warn_unreachable = true
180+
warn_unused_configs = true
181+
182+
# Turn these options off as it could cause conflicts
183+
# with the Pyright options.
184+
warn_unused_ignores = false
185+
warn_redundant_casts = false
186+
187+
disallow_any_generics = true
188+
disallow_untyped_defs = true
189+
disallow_untyped_calls = true
190+
disallow_subclassing_any = true
191+
disallow_incomplete_defs = true
192+
disallow_untyped_decorators = true
193+
cache_fine_grained = true
194+
195+
# By default, mypy reports an error if you assign a value to the result
196+
# of a function call that doesn't return anything. We do this in our test
197+
# cases:
198+
# ```
199+
# result = ...
200+
# assert result is None
201+
# ```
202+
# Changing this codegen to make mypy happy would increase complexity
203+
# and would not be worth it.
204+
disable_error_code = "func-returns-value,overload-cannot-match"
205+
206+
# https://github.com/python/mypy/issues/12162
207+
[[tool.mypy.overrides]]
208+
module = "black.files.*"
209+
ignore_errors = true
210+
ignore_missing_imports = true
211+
212+
161213
[tool.ruff]
162214
line-length = 120
163215
output-format = "grouped"

src/replicate/_base_client.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
ModelBuilderProtocol,
6060
)
6161
from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping
62-
from ._compat import PYDANTIC_V2, model_copy, model_dump
62+
from ._compat import PYDANTIC_V1, model_copy, model_dump
6363
from ._models import GenericModel, FinalRequestOptions, validate_type, construct_type
6464
from ._response import (
6565
APIResponse,
@@ -232,7 +232,7 @@ def _set_private_attributes(
232232
model: Type[_T],
233233
options: FinalRequestOptions,
234234
) -> None:
235-
if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None:
235+
if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None:
236236
self.__pydantic_private__ = {}
237237

238238
self._model = model
@@ -320,7 +320,7 @@ def _set_private_attributes(
320320
client: AsyncAPIClient,
321321
options: FinalRequestOptions,
322322
) -> None:
323-
if PYDANTIC_V2 and getattr(self, "__pydantic_private__", None) is None:
323+
if (not PYDANTIC_V1) and getattr(self, "__pydantic_private__", None) is None:
324324
self.__pydantic_private__ = {}
325325

326326
self._model = model

src/replicate/_compat.py

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@
1212
_T = TypeVar("_T")
1313
_ModelT = TypeVar("_ModelT", bound=pydantic.BaseModel)
1414

15-
# --------------- Pydantic v2 compatibility ---------------
15+
# --------------- Pydantic v2, v3 compatibility ---------------
1616

1717
# Pyright incorrectly reports some of our functions as overriding a method when they don't
1818
# pyright: reportIncompatibleMethodOverride=false
1919

20-
PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
20+
PYDANTIC_V1 = pydantic.VERSION.startswith("1.")
2121

22-
# v1 re-exports
2322
if TYPE_CHECKING:
2423

2524
def parse_date(value: date | StrBytesIntFloat) -> date: # noqa: ARG001
@@ -44,90 +43,92 @@ def is_typeddict(type_: type[Any]) -> bool: # noqa: ARG001
4443
...
4544

4645
else:
47-
if PYDANTIC_V2:
48-
from pydantic.v1.typing import (
46+
# v1 re-exports
47+
if PYDANTIC_V1:
48+
from pydantic.typing import (
4949
get_args as get_args,
5050
is_union as is_union,
5151
get_origin as get_origin,
5252
is_typeddict as is_typeddict,
5353
is_literal_type as is_literal_type,
5454
)
55-
from pydantic.v1.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime
55+
from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime
5656
else:
57-
from pydantic.typing import (
57+
from ._utils import (
5858
get_args as get_args,
5959
is_union as is_union,
6060
get_origin as get_origin,
61+
parse_date as parse_date,
6162
is_typeddict as is_typeddict,
63+
parse_datetime as parse_datetime,
6264
is_literal_type as is_literal_type,
6365
)
64-
from pydantic.datetime_parse import parse_date as parse_date, parse_datetime as parse_datetime
6566

6667

6768
# refactored config
6869
if TYPE_CHECKING:
6970
from pydantic import ConfigDict as ConfigDict
7071
else:
71-
if PYDANTIC_V2:
72-
from pydantic import ConfigDict
73-
else:
72+
if PYDANTIC_V1:
7473
# TODO: provide an error message here?
7574
ConfigDict = None
75+
else:
76+
from pydantic import ConfigDict as ConfigDict
7677

7778

7879
# renamed methods / properties
7980
def parse_obj(model: type[_ModelT], value: object) -> _ModelT:
80-
if PYDANTIC_V2:
81-
return model.model_validate(value)
82-
else:
81+
if PYDANTIC_V1:
8382
return cast(_ModelT, model.parse_obj(value)) # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
83+
else:
84+
return model.model_validate(value)
8485

8586

8687
def field_is_required(field: FieldInfo) -> bool:
87-
if PYDANTIC_V2:
88-
return field.is_required()
89-
return field.required # type: ignore
88+
if PYDANTIC_V1:
89+
return field.required # type: ignore
90+
return field.is_required()
9091

9192

9293
def field_get_default(field: FieldInfo) -> Any:
9394
value = field.get_default()
94-
if PYDANTIC_V2:
95-
from pydantic_core import PydanticUndefined
96-
97-
if value == PydanticUndefined:
98-
return None
95+
if PYDANTIC_V1:
9996
return value
97+
from pydantic_core import PydanticUndefined
98+
99+
if value == PydanticUndefined:
100+
return None
100101
return value
101102

102103

103104
def field_outer_type(field: FieldInfo) -> Any:
104-
if PYDANTIC_V2:
105-
return field.annotation
106-
return field.outer_type_ # type: ignore
105+
if PYDANTIC_V1:
106+
return field.outer_type_ # type: ignore
107+
return field.annotation
107108

108109

109110
def get_model_config(model: type[pydantic.BaseModel]) -> Any:
110-
if PYDANTIC_V2:
111-
return model.model_config
112-
return model.__config__ # type: ignore
111+
if PYDANTIC_V1:
112+
return model.__config__ # type: ignore
113+
return model.model_config
113114

114115

115116
def get_model_fields(model: type[pydantic.BaseModel]) -> dict[str, FieldInfo]:
116-
if PYDANTIC_V2:
117-
return model.model_fields
118-
return model.__fields__ # type: ignore
117+
if PYDANTIC_V1:
118+
return model.__fields__ # type: ignore
119+
return model.model_fields
119120

120121

121122
def model_copy(model: _ModelT, *, deep: bool = False) -> _ModelT:
122-
if PYDANTIC_V2:
123-
return model.model_copy(deep=deep)
124-
return model.copy(deep=deep) # type: ignore
123+
if PYDANTIC_V1:
124+
return model.copy(deep=deep) # type: ignore
125+
return model.model_copy(deep=deep)
125126

126127

127128
def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str:
128-
if PYDANTIC_V2:
129-
return model.model_dump_json(indent=indent)
130-
return model.json(indent=indent) # type: ignore
129+
if PYDANTIC_V1:
130+
return model.json(indent=indent) # type: ignore
131+
return model.model_dump_json(indent=indent)
131132

132133

133134
def model_dump(
@@ -139,14 +140,14 @@ def model_dump(
139140
warnings: bool = True,
140141
mode: Literal["json", "python"] = "python",
141142
) -> dict[str, Any]:
142-
if PYDANTIC_V2 or hasattr(model, "model_dump"):
143+
if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
143144
return model.model_dump(
144145
mode=mode,
145146
exclude=exclude,
146147
exclude_unset=exclude_unset,
147148
exclude_defaults=exclude_defaults,
148149
# warnings are not supported in Pydantic v1
149-
warnings=warnings if PYDANTIC_V2 else True,
150+
warnings=True if PYDANTIC_V1 else warnings,
150151
)
151152
return cast(
152153
"dict[str, Any]",
@@ -159,9 +160,9 @@ def model_dump(
159160

160161

161162
def model_parse(model: type[_ModelT], data: Any) -> _ModelT:
162-
if PYDANTIC_V2:
163-
return model.model_validate(data)
164-
return model.parse_obj(data) # pyright: ignore[reportDeprecated]
163+
if PYDANTIC_V1:
164+
return model.parse_obj(data) # pyright: ignore[reportDeprecated]
165+
return model.model_validate(data)
165166

166167

167168
# generic models
@@ -170,17 +171,16 @@ def model_parse(model: type[_ModelT], data: Any) -> _ModelT:
170171
class GenericModel(pydantic.BaseModel): ...
171172

172173
else:
173-
if PYDANTIC_V2:
174+
if PYDANTIC_V1:
175+
import pydantic.generics
176+
177+
class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ...
178+
else:
174179
# there no longer needs to be a distinction in v2 but
175180
# we still have to create our own subclass to avoid
176181
# inconsistent MRO ordering errors
177182
class GenericModel(pydantic.BaseModel): ...
178183

179-
else:
180-
import pydantic.generics
181-
182-
class GenericModel(pydantic.generics.GenericModel, pydantic.BaseModel): ...
183-
184184

185185
# cached properties
186186
if TYPE_CHECKING:

0 commit comments

Comments
 (0)