Pinnochio
A dependency linter for Python projects using UV and pyproject.toml. Pinnochio
helps prevent accidental dependency upgrades that break APIs by enforcing best
practices for version pinning.
Features
- Upper Bound Enforcement: Ensures all dependencies have upper version
bounds (e.g.,
>=2.25.0,<2.26.0) to prevent breaking changes - Automatic Sorting: Keeps dependency groups alphabetically sorted for consistency
- Version Drift Detection: Identifies when the same package has different version constraints across dependency groups
- Redundancy Checks: Detects dependencies duplicated between core dependencies and optional groups
- Auto-fix Support: Automatically fixes many common issues with the
--fixflag
Installation
uv tool install pinnochio
# Or pipx install pinnochio
Usage
Run in your project directory:
# Check for issues
pinnochio
# Check and automatically fix issues
pinnochio --fix
# Override pinning strategy for this run
pinnochio --fix --pinning-strategy minor
Example Output
Warning! The following dependencies aren't pinned from above
dependencies:
requests>=2.25.0
numpy>=1.20.0
Warning: The following dependency groups aren't sorted:
dev
With --fix, pinnochio will automatically add upper bounds:
Fixing: Adding upper bounds to unpinned dependencies...
Fixed: requests>=2.25.0 -> requests>=2.25.0,<3.0.0
Fixed: numpy>=1.20.0 -> numpy>=1.20.0,<2.0.0
Fixed: Upper bounds have been added where possible.
Fixing: Sorting dependency groups...
Fixed: Dependency groups have been sorted.
Changes have been written to pyproject.toml
Configuration
Pinnochio can be configured via the [tool.pinnochio] section in your
pyproject.toml:
[tool.pinnochio]
pinning-strategy = "major" # Default: "major"
Pinning Strategies
The pinning-strategy option controls how upper bounds are added to
dependencies. You can set it in your config file or override it with the
--pinning-strategy CLI flag:
-
"major"(default): Allows minor and patch updates within the same major version- Example:
>=1.2.3becomes>=1.2.3,<2.0.0 - Follows semantic versioning: breaking changes at major version boundaries
- Recommended for most projects
- Example:
-
"minor": Only allows patch updates within the same minor version- Example:
>=1.2.3becomes>=1.2.3,<1.3.0 - More restrictive, useful for projects requiring high stability
- Prevents feature additions that might affect behavior
- Example:
-
"patch": No automatic updates, only the exact patch version- Example:
>=1.2.3becomes>=1.2.3,<1.2.4 - Most restrictive, useful for critical production systems
- Requires manual version bumps for any updates
- Example:
Note: The --pinning-strategy CLI flag always takes precedence over the
config file setting.
Checks Performed
-
Upper Bound Pinning: Dependencies with only lower bounds (e.g.,
>=1.0.0) are flagged and can be auto-fixed to include upper bounds based on your configured pinning strategy -
Dependency Sorting: All dependency groups must be alphabetically sorted
-
Version Consistency: The same package must have identical version constraints across all dependency groups
-
No Redundancy: Dependencies in the core
dependencieslist should not be duplicated inoptional-dependenciesordevgroups
Pre-commit Hook
Add pinnochio to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/BlakeJC94/pinnochio
rev: v1.0.0 # Use the latest version
hooks:
- id: pinnochio
This will run pinnochio automatically whenever you commit changes to
pyproject.toml. If issues are found, the commit will be blocked until they're
fixed.
To automatically fix issues during pre-commit, you can pass the --fix flag:
repos:
- repo: https://github.com/anomalyco/pinnochio
rev: v1.0.0
hooks:
- id: pinnochio
args: [--fix]
Requirements
- Python >=3.11
pyproject.tomlwith UV-style dependency groups
License
MIT
Metadata
Release files for pinnochio 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pinnochio-1.0.0.tar.gz | 16.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pinnochio-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.1 kB
Release files / pinnochio-1.0.0.tar.gz
| Download URL | pinnochio-1.0.0.tar.gz |
|---|---|
| Size | 16.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0375b015405f2983b8fbdb952bcd211032c1744dce57c842a45d0e18a5273a59
|
|
BLAKE2b-256 checksum How to use checksums |
e64fed195a7a3f5e4a1c5ad9697f54ecbe790a1aa789262469e92a355e9a309f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / pinnochio-1.0.0-py3-none-any.whl
| Download URL | pinnochio-1.0.0-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
de0b94c55d8d2a16490b3e4a24868cccea3c4368e072b95452bfce0c58bbe014
|
|
BLAKE2b-256 checksum How to use checksums |
64ee2140cf787b9a48294063bb1c1ca9170699071841ce410d73df5d244da756
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for pinnochio 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.