Bumpcheck
Catch Pydantic runtime behavior changes before a dependency bump.
Bumpcheck runs one small application contract in two isolated Python environments and compares what users can observe: returned JSON, Pydantic validation errors, warnings, and captured output.
Quickstart
Install uv, then install Bumpcheck:
uv tool install bumpcheck
Create contract.py:
from collections.abc import Mapping
from typing import Annotated
from pydantic import BaseModel, ConfigDict, Field
MetadataKey = Annotated[str, Field(max_length=3)]
class Model(BaseModel):
model_config = ConfigDict(strict=True)
metadata: Mapping[MetadataKey, str]
def run():
return Model(metadata={"toolong": "b"}).model_dump(mode="json")
Run it against two versions:
$ bumpcheck check contract.py \
--baseline pydantic==2.10.6 \
--candidate pydantic==2.11.1 \
--python-version 3.12
BASELINE pydantic=2.10.6 @ .../pydantic/__init__.py
CANDIDATE pydantic=2.11.1 @ .../pydantic/__init__.py
CHANGED contract: ValidationError[string_too_long] -> return {"metadata":{"toolong":"b"}}
Exit code 0 means unchanged, 1 means behavior changed, and 2 means the capture was not trustworthy. This makes the command usable as a CI gate.
Check your application
A contract is a normal Python file exposing either run() or run(value).
Return a JSON-compatible value that represents the behavior your application
depends on.
Use --with . to install the current project into both isolated environments:
bumpcheck check contract.py \
--baseline pydantic==2.10.6 \
--candidate pydantic==2.11.1 \
--with .
Repeat --with for shared dependencies. Use --watch DIST[:MODULE] to record
their exact versions and import locations alongside the default pydantic and
pydantic-core records.
For real payloads, define run(value) and pass --inputs. Bumpcheck accepts a
JSON array, .jsonl or .ndjson, or a Pydantic Evals JSON document containing
a cases array. It preserves case names or JSON Lines source line numbers and
hashes the case and input bytes before comparing results.
If environments already exist, use --baseline-python and
--candidate-python instead of requirement targets. Use --json for a
machine-readable report and --exact when warning messages, exception messages,
stdout, and stderr must also match.
Scope and limits
Bumpcheck is a focused pre-upgrade gate, not a test runner or an API/schema diff. It is useful for data-dependent validation and serialization behavior that ordinary dependency tooling does not observe.
Cases are trusted code. The subprocess boundary enforces a timeout but is not a security sandbox. Receipts contain local interpreter and module paths, so review JSON output before sharing it. Imported project files are not hashed; run from an immutable revision when they are part of the contract.
Migration
Bumpcheck was previously named Pydantic Canary. The bumpcheck distribution
installs a temporary pydantic-canary command alias, but new code should import
bumpcheck and use the bumpcheck command.
Development
uv run --isolated --no-project --no-config --no-cache --with . -- \
python -B -m unittest discover -s tests -v
uv run --isolated --no-project --no-config --with ruff==0.16.4 -- ruff check .
uv build
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bumpcheck-0.2.0.tar.gz.
File metadata
- Download URL: bumpcheck-0.2.0.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81b8e597fde9e5b20188fc8a82fb6e8d06bf677d07e40512362842854e0f625b
|
|
| MD5 |
8c164006c3bbacbcb9295bc59809c49a
|
|
| BLAKE2b-256 |
7da786d4088db7136b492140c6e030a8884a75196962fafd40a7b30dc8fee73a
|
Provenance
The following attestation bundles were made for bumpcheck-0.2.0.tar.gz:
Publisher:
release.yml on smigolsmigol/bumpcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bumpcheck-0.2.0.tar.gz -
Subject digest:
81b8e597fde9e5b20188fc8a82fb6e8d06bf677d07e40512362842854e0f625b - Sigstore transparency entry: 2568432907
- Sigstore integration time:
-
Permalink:
smigolsmigol/bumpcheck@f396dc51ccb098d2dd7eb6d934870f70dfef11d6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/smigolsmigol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f396dc51ccb098d2dd7eb6d934870f70dfef11d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file bumpcheck-0.2.0-py3-none-any.whl.
File metadata
- Download URL: bumpcheck-0.2.0-py3-none-any.whl
- Upload date:
- Size: 13.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4e48b6aaefd8d0f6a8debbb51f5ed725ea801baf5f6aec7098c1f70ac6067e4
|
|
| MD5 |
f17fcff44cdb070bc251a655ed67ad19
|
|
| BLAKE2b-256 |
66d44034a5241af5de5c45ceea4b2f070031a9ee6aefd164fca460d36dcdc067
|
Provenance
The following attestation bundles were made for bumpcheck-0.2.0-py3-none-any.whl:
Publisher:
release.yml on smigolsmigol/bumpcheck
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bumpcheck-0.2.0-py3-none-any.whl -
Subject digest:
a4e48b6aaefd8d0f6a8debbb51f5ed725ea801baf5f6aec7098c1f70ac6067e4 - Sigstore transparency entry: 2568432910
- Sigstore integration time:
-
Permalink:
smigolsmigol/bumpcheck@f396dc51ccb098d2dd7eb6d934870f70dfef11d6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/smigolsmigol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f396dc51ccb098d2dd7eb6d934870f70dfef11d6 -
Trigger Event:
push
-
Statement type: