Skip to content

Commit c362820

Browse files
authored
Merge pull request #223 from DanCardin/dc/3.14
feat: Test against python 3.14.
2 parents 537753a + 1338f7a commit c362820

6 files changed

Lines changed: 46 additions & 45 deletions

File tree

.github/workflows/test.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ jobs:
1818
strategy:
1919
fail-fast: false
2020
matrix:
21-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
22-
pydantic-version: ["1.0", "2.0"]
21+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
22+
pydantic-version: ["1.0", ""]
2323

2424
# No need to matrix test pydantic versions. But the matrix syntax still
2525
# keeps the file DRY.
@@ -28,12 +28,14 @@ jobs:
2828
pydantic-version: "1.0"
2929
- python-version: "3.9"
3030
pydantic-version: "1.0"
31-
- python-version: "3.11"
31+
- python-version: "3.10"
3232
pydantic-version: "1.0"
33-
- python-version: "3.12"
33+
- python-version: "3.11"
3434
pydantic-version: "1.0"
3535
- python-version: "3.13"
3636
pydantic-version: "1.0"
37+
- python-version: "3.14"
38+
pydantic-version: "1.0"
3739

3840
env:
3941
UV_CACHE_DIR: /tmp/.uv-cache
@@ -63,7 +65,8 @@ jobs:
6365
- name: Minimize uv cache
6466
run: uv cache prune --ci
6567

66-
- name: Install pydantic matrix version
68+
- if: ${{ matrix.pydantic-version != '' }}
69+
name: Install pydantic matrix version
6770
run: uv pip install 'pydantic~=${{ matrix.pydantic-version }}'
6871

6972
- name: Run Linters

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
## Unreleased: 0.29.0
66

7+
- feat: Test against python 3.14.
8+
- fix: Apply pyright strict typing.
79
- fix: Function callables ability to depend on implicit Deps.
810
- docs: Improve docs relating to `Output`.
911
## 0.28

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ dev-dependencies = [
3535
"types-docutils >= 0.20.0",
3636

3737
"attrs",
38-
"pydantic",
38+
"pydantic; python_version < '3.14'",
3939
"msgspec >= 0.19.0; python_version >= '3.9'",
4040
]
4141

src/cappa/class_inspect.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ def from_cls(cls, obj: type) -> ClassTypes | None:
204204
return cls.msgspec
205205

206206
try:
207-
import pydantic
208-
from pydantic import BaseModel
207+
import pydantic # pyright: ignore
208+
from pydantic import BaseModel # pyright: ignore
209209
except ImportError: # pragma: no cover
210210
pass
211211
else:
@@ -215,7 +215,7 @@ def from_cls(cls, obj: type) -> ClassTypes | None:
215215
is_base_model = False
216216

217217
if is_base_model:
218-
if pydantic.__version__.startswith("1."):
218+
if pydantic.__version__.startswith("1."): # pyright: ignore
219219
return cls.pydantic_v1
220220
return cls.pydantic_v2
221221

tests/test_pydantic.py

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,48 @@
11
from __future__ import annotations
22

3+
import sys
34
from typing import Optional
45

5-
from pydantic import BaseModel, dataclasses
66
from typing_extensions import Annotated
77

88
import cappa
99
from tests.utils import Backend, backends, parse
1010

11+
if sys.version_info < (3, 14):
12+
from pydantic import BaseModel, dataclasses
1113

12-
class PydanticCommand(BaseModel):
13-
name: str
14-
foo: Annotated[int, cappa.Arg(short=True)]
14+
class PydanticCommand(BaseModel):
15+
name: str
16+
foo: Annotated[int, cappa.Arg(short=True)]
1517

18+
@backends
19+
def test_base_model(backend: Backend):
20+
result = parse(PydanticCommand, "meow", "-f", "4", backend=backend)
21+
assert result == PydanticCommand(name="meow", foo=4)
1622

17-
@backends
18-
def test_base_model(backend: Backend):
19-
result = parse(PydanticCommand, "meow", "-f", "4", backend=backend)
20-
assert result == PydanticCommand(name="meow", foo=4)
23+
@dataclasses.dataclass
24+
class DataclassCommand:
25+
name: str
26+
foo: Annotated[int, cappa.Arg(short=True)]
2127

28+
@backends
29+
def test_dataclass(backend: Backend):
30+
result = parse(DataclassCommand, "meow", "-f", "4", backend=backend)
31+
assert result == DataclassCommand(name="meow", foo=4)
2232

23-
@dataclasses.dataclass
24-
class DataclassCommand:
25-
name: str
26-
foo: Annotated[int, cappa.Arg(short=True)]
33+
class OptSub(BaseModel):
34+
name: Optional[str] = None
2735

36+
class OptionalSubcommand(BaseModel):
37+
sub: cappa.Subcommands[Optional[OptSub]] = None
2838

29-
@backends
30-
def test_dataclass(backend: Backend):
31-
result = parse(DataclassCommand, "meow", "-f", "4", backend=backend)
32-
assert result == DataclassCommand(name="meow", foo=4)
39+
@backends
40+
def test_optional_subcommand(backend: Backend):
41+
result = parse(OptionalSubcommand, backend=backend)
42+
assert result == OptionalSubcommand(sub=None)
3343

44+
result = parse(OptionalSubcommand, "opt-sub", backend=backend)
45+
assert result == OptionalSubcommand(sub=OptSub(name=None))
3446

35-
class OptSub(BaseModel):
36-
name: Optional[str] = None
37-
38-
39-
class OptionalSubcommand(BaseModel):
40-
sub: cappa.Subcommands[Optional[OptSub]] = None
41-
42-
43-
@backends
44-
def test_optional_subcommand(backend: Backend):
45-
result = parse(OptionalSubcommand, backend=backend)
46-
assert result == OptionalSubcommand(sub=None)
47-
48-
result = parse(OptionalSubcommand, "opt-sub", backend=backend)
49-
assert result == OptionalSubcommand(sub=OptSub(name=None))
50-
51-
result = parse(OptionalSubcommand, "opt-sub", "foo", backend=backend)
52-
assert result == OptionalSubcommand(sub=OptSub(name="foo"))
47+
result = parse(OptionalSubcommand, "opt-sub", "foo", backend=backend)
48+
assert result == OptionalSubcommand(sub=OptSub(name="foo"))

uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)