A dependency linter for Python projects using UV to enforce version pinning best practices
Project description
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
Project details
Release history Release notifications | RSS feed
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 pinnochio-1.0.0.tar.gz.
File metadata
- Download URL: pinnochio-1.0.0.tar.gz
- Upload date:
- Size: 16.5 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0375b015405f2983b8fbdb952bcd211032c1744dce57c842a45d0e18a5273a59
|
|
| MD5 |
b69c84892adc1885e0e8f5691582f40e
|
|
| BLAKE2b-256 |
e64fed195a7a3f5e4a1c5ad9697f54ecbe790a1aa789262469e92a355e9a309f
|
File details
Details for the file pinnochio-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pinnochio-1.0.0-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de0b94c55d8d2a16490b3e4a24868cccea3c4368e072b95452bfce0c58bbe014
|
|
| MD5 |
fa7e233dc9a8ceab1fd048ad13230ed4
|
|
| BLAKE2b-256 |
64ee2140cf787b9a48294063bb1c1ca9170699071841ce410d73df5d244da756
|