Skip to content

Commit 66337c4

Browse files
KludexDouweM
andauthored
ci: split test suite (#2436)
Co-authored-by: Douwe Maan <[email protected]>
1 parent ecafb25 commit 66337c4

File tree

9 files changed

+247
-216
lines changed

9 files changed

+247
-216
lines changed

.github/workflows/ci.yml

Lines changed: 79 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ jobs:
107107
with:
108108
model: qwen2:0.5b
109109

110+
- run: uv sync --only-dev
110111
- run: >
111112
uv run
112113
--package pydantic-ai-slim
@@ -130,13 +131,14 @@ jobs:
130131
CO_API_KEY: ${{ secrets.COHERE_API_KEY }}
131132
132133
test:
133-
name: test on ${{ matrix.python-version }}
134+
name: test on ${{ matrix.python-version }} (${{ matrix.install }})
134135
runs-on: ubuntu-latest
135136
timeout-minutes: 10
136137
strategy:
137138
fail-fast: false
138139
matrix:
139140
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
141+
install: ["slim", "standard", "all-extras"]
140142
env:
141143
UV_PYTHON: ${{ matrix.python-version }}
142144
CI: true
@@ -148,46 +150,98 @@ jobs:
148150
with:
149151
enable-cache: true
150152

151-
- uses: denoland/setup-deno@v2
152-
with:
153-
deno-version: v2.x
153+
- run: |
154+
if [ "${{ matrix.install }}" = "slim" ]; then
155+
echo "--package pydantic-ai-slim"
156+
elif [ "${{ matrix.install }}" = "standard" ]; then
157+
echo ""
158+
elif [ "${{ matrix.install }}" = "all-extras" ]; then
159+
echo "--all-extras"
160+
fi
161+
id: install-command
154162
155163
- run: mkdir .coverage
156164

157-
# run tests with just `pydantic-ai-slim` dependencies
158-
- run: uv run --package pydantic-ai-slim coverage run -m pytest -n auto --dist=loadgroup
165+
- run: uv sync --group dev
166+
- run: uv run ${{ steps.install-command.outputs.install-command }} coverage run -m pytest -n auto --dist=loadgroup
159167
env:
160-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-slim
168+
COVERAGE_FILE: .coverage/.coverage.${{ matrix.python-version }}-${{ matrix.install }}
161169

162-
- run: uv run coverage run -m pytest -n auto --dist=loadgroup
163-
env:
164-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-standard
170+
- name: store coverage files
171+
uses: actions/upload-artifact@v4
172+
if: matrix.python-version != '3.9'
173+
with:
174+
name: coverage-${{ matrix.python-version }}-${{ matrix.install }}
175+
path: .coverage
176+
include-hidden-files: true
165177

166-
- run: uv run --all-extras coverage run -m pytest -n auto --dist=loadgroup
167-
env:
168-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-all-extras
178+
test-lowest-versions:
179+
name: test on ${{ matrix.python-version }} (lowest-versions)
180+
runs-on: ubuntu-latest
181+
timeout-minutes: 10
182+
strategy:
183+
fail-fast: false
184+
matrix:
185+
python-version: ["3.10", "3.11", "3.12", "3.13"]
186+
env:
187+
UV_PYTHON: ${{ matrix.python-version }}
188+
CI: true
189+
COVERAGE_PROCESS_START: ./pyproject.toml
190+
steps:
191+
- uses: actions/checkout@v4
169192

170-
- run: uv run --all-extras python tests/import_examples.py
193+
- uses: astral-sh/setup-uv@v5
194+
with:
195+
enable-cache: true
171196

172-
# this must run last as it modifies the environment!
173-
- name: test lowest versions
174-
if: matrix.python-version != '3.9'
175-
run: |
176-
unset UV_FROZEN
177-
uv run --all-extras --resolution lowest-direct coverage run -m pytest -n auto --dist=loadgroup
197+
- uses: denoland/setup-deno@v2
198+
with:
199+
deno-version: v2.x
200+
201+
- run: mkdir .coverage
202+
203+
- run: uv sync --group dev
204+
205+
- run: unset UV_FROZEN
206+
207+
- run: uv run --all-extras --resolution lowest-direct coverage run -m pytest -n auto --dist=loadgroup
178208
env:
179-
COVERAGE_FILE: .coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }}-lowest-versions
209+
COVERAGE_FILE: .coverage/.coverage.${{matrix.python-version}}-lowest-versions
180210

181211
- name: store coverage files
182212
uses: actions/upload-artifact@v4
183213
with:
184-
name: coverage-${{ matrix.python-version }}
214+
name: coverage-${{ matrix.python-version }}-lowest-versions
185215
path: .coverage
186216
include-hidden-files: true
187217

218+
test-examples:
219+
name: test examples on ${{ matrix.python-version }}
220+
runs-on: ubuntu-latest
221+
timeout-minutes: 10
222+
strategy:
223+
fail-fast: false
224+
matrix:
225+
python-version: ["3.11", "3.12", "3.13"]
226+
env:
227+
UV_PYTHON: ${{ matrix.python-version }}
228+
CI: true
229+
steps:
230+
- uses: actions/checkout@v4
231+
232+
- uses: astral-sh/setup-uv@v5
233+
with:
234+
enable-cache: true
235+
236+
- uses: denoland/setup-deno@v2
237+
with:
238+
deno-version: v2.x
239+
240+
- run: uv run --all-extras python tests/import_examples.py
241+
188242
coverage:
189243
runs-on: ubuntu-latest
190-
needs: [test]
244+
needs: [test, test-lowest-versions]
191245
steps:
192246
- uses: actions/checkout@v4
193247
with:
@@ -204,8 +258,7 @@ jobs:
204258
with:
205259
enable-cache: true
206260

207-
- run: uv sync --package pydantic-ai-slim --only-dev
208-
- run: rm .coverage/.coverage.*-py3.9-* # Exclude 3.9 coverage as it gets the wrong line numbers, causing invalid failures.
261+
- run: uv sync --group dev
209262
- run: uv run coverage combine
210263
- run: uv run coverage report
211264

@@ -239,7 +292,7 @@ jobs:
239292
# https://github.com/marketplace/actions/alls-green#why used for branch protection checks
240293
check:
241294
if: always()
242-
needs: [lint, mypy, docs, test-live, test, coverage, test-mcp-run-python]
295+
needs: [lint, mypy, docs, test-live, test, test-lowest-versions, test-examples, coverage, test-mcp-run-python]
243296
runs-on: ubuntu-latest
244297

245298
steps:

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ typecheck-both: typecheck-pyright typecheck-mypy
6060

6161
.PHONY: test
6262
test: ## Run tests and collect coverage data
63-
COVERAGE_PROCESS_START=./pyproject.toml uv run coverage run -m pytest -n auto --dist=loadgroup
63+
uv run coverage run -m pytest -n auto --dist=loadgroup
6464
@uv run coverage combine
6565
@uv run coverage report
6666

examples/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ dependencies = [
5252
"pydantic-evals=={{ version }}",
5353
"asyncpg>=0.30.0",
5454
"fastapi>=0.115.4",
55-
"logfire[asyncpg,fastapi,sqlite3,httpx]>=2.6",
55+
"logfire[asyncpg,fastapi,sqlite3,httpx]>=3.14.1",
5656
"python-multipart>=0.0.17",
5757
"rich>=13.9.2",
5858
"uvicorn>=0.32.0",

pydantic_ai_slim/pyproject.toml

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ dependencies = [
6060

6161
[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies]
6262
# WARNING if you add optional groups, please update docs/install.md
63-
logfire = ["logfire>=3.11.0"]
63+
logfire = ["logfire>=3.14.1"]
6464
# Models
6565
openai = ["openai>=1.92.0"]
6666
cohere = ["cohere>=5.16.0; platform_system != 'Emscripten'"]
@@ -87,27 +87,6 @@ ag-ui = ["ag-ui-protocol>=0.1.8", "starlette>=0.45.3"]
8787
# Retries
8888
retries = ["tenacity>=8.2.3"]
8989

90-
[dependency-groups]
91-
dev = [
92-
"anyio>=4.5.0",
93-
"asgi-lifespan>=2.1.0",
94-
"devtools>=0.12.2",
95-
"coverage[toml]>=7.10.2",
96-
"dirty-equals>=0.9.0",
97-
"duckduckgo-search>=7.0.0",
98-
"inline-snapshot>=0.19.3",
99-
"pytest>=8.3.3",
100-
"pytest-examples>=0.0.14",
101-
"pytest-mock>=3.14.0",
102-
"pytest-pretty>=1.3.0",
103-
"pytest-recording>=0.13.2",
104-
"diff-cover>=9.2.0",
105-
"boto3-stubs[bedrock-runtime]",
106-
"strict-no-cover @ git+https://github.com/pydantic/strict-no-cover.git@7fc59da2c4dff919db2095a0f0e47101b657131d",
107-
"pytest-xdist>=3.6.1",
108-
"coverage-enable-subprocess>=0.1.0",
109-
]
110-
11190
[tool.hatch.metadata]
11291
allow-direct-references = true
11392

pydantic_evals/pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ requires-python = ">=3.9"
4949
[tool.hatch.metadata.hooks.uv-dynamic-versioning]
5050
dependencies = [
5151
"rich>=13.9.4",
52-
"logfire-api>=1.2.0",
52+
"logfire-api>=3.14.1",
5353
"pydantic>=2.10",
5454
"pydantic-ai-slim=={{ version }}",
5555
"anyio>=0",
@@ -58,7 +58,7 @@ dependencies = [
5858
]
5959

6060
[project.optional-dependencies]
61-
logfire = ["logfire>=2.3"]
61+
logfire = ["logfire>=3.14.1"]
6262

6363
[project.urls]
6464
Homepage = "https://ai.pydantic.dev/evals"

pydantic_graph/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ classifiers = [
4747
requires-python = ">=3.9"
4848
dependencies = [
4949
"httpx>=0.27",
50-
"logfire-api>=1.2.0",
50+
"logfire-api>=3.14.1",
5151
"pydantic>=2.10",
5252
"typing-inspection>=0.4.0",
5353
]

pyproject.toml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ dependencies = [
5252

5353
[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies]
5454
examples = ["pydantic-ai-examples=={{ version }}"]
55-
logfire = ["logfire>=3.11.0"]
55+
logfire = ["logfire>=3.14.1"]
5656
a2a = ["fasta2a>=0.4.1"]
5757

5858
[project.urls]
@@ -81,8 +81,28 @@ members = [
8181
"examples",
8282
]
8383

84+
[tool.uv]
85+
default-groups = ["dev", "lint", "docs"]
86+
8487
[dependency-groups]
85-
# dev dependencies are defined in `pydantic-ai-slim/pyproject.toml` to allow for minimal testing
88+
dev = [
89+
"anyio>=4.5.0",
90+
"asgi-lifespan>=2.1.0",
91+
"devtools>=0.12.2",
92+
"coverage[toml]>=7.10.3",
93+
"dirty-equals>=0.9.0",
94+
"duckduckgo-search>=7.0.0",
95+
"inline-snapshot>=0.19.3",
96+
"pytest>=8.3.3",
97+
"pytest-examples>=0.0.18",
98+
"pytest-mock>=3.14.0",
99+
"pytest-pretty>=1.3.0",
100+
"pytest-recording>=0.13.2",
101+
"diff-cover>=9.2.0",
102+
"boto3-stubs[bedrock-runtime]",
103+
"strict-no-cover @ git+https://github.com/pydantic/strict-no-cover.git@7fc59da2c4dff919db2095a0f0e47101b657131d",
104+
"pytest-xdist>=3.6.1",
105+
]
86106
lint = ["mypy>=1.11.2", "pyright>=1.1.390", "ruff>=0.6.9"]
87107
docs = [
88108
"pydantic-ai[a2a]",
@@ -216,7 +236,7 @@ filterwarnings = [
216236

217237
# https://coverage.readthedocs.io/en/latest/config.html#run
218238
[tool.coverage.run]
219-
parallel = true
239+
patch = ["subprocess"]
220240
concurrency = ["multiprocessing", "thread"]
221241
# We use a subdirectory for coverage data to avoid noisy coverage data files.
222242
data_file = ".coverage/.coverage"

tests/test_logfire.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -558,10 +558,7 @@ def get_model():
558558
@pytest.mark.skipif(not logfire_installed, reason='logfire not installed')
559559
@pytest.mark.anyio
560560
async def test_feedback(capfire: CaptureLogfire) -> None:
561-
try:
562-
from logfire.experimental.annotations import record_feedback
563-
except ImportError: # pragma: lax no cover
564-
pytest.skip('Requires recent version of logfire')
561+
from logfire.experimental.annotations import record_feedback
565562

566563
my_agent = Agent(model=TestModel(), instrument=True)
567564

0 commit comments

Comments
 (0)