Metadata-Version: 2.4
Name: uv-override-prune
Version: 0.0.8
Summary: Detect redundant override-dependencies / constraint-dependencies in uv projects
Project-URL: Repository, https://github.com/iwamot/uv-override-prune
Project-URL: Issues, https://github.com/iwamot/uv-override-prune/issues
Author: Takashi Iwamoto
License-Expression: MIT
License-File: LICENSE
Keywords: audit,dependencies,override,prune,uv
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development
Requires-Python: >=3.11
Requires-Dist: packaging
Requires-Dist: tomlkit
Provides-Extra: dev
Requires-Dist: pip-licenses==5.5.5; extra == 'dev'
Requires-Dist: pytest-cov==7.1.0; extra == 'dev'
Requires-Dist: pytest==9.0.3; extra == 'dev'
Description-Content-Type: text/markdown

# uv-override-prune

[![CI](https://github.com/iwamot/uv-override-prune/actions/workflows/validate.yml/badge.svg)](https://github.com/iwamot/uv-override-prune/actions/workflows/validate.yml)
[![codecov](https://codecov.io/gh/iwamot/uv-override-prune/graph/badge.svg)](https://codecov.io/gh/iwamot/uv-override-prune)
[![PyPI](https://img.shields.io/pypi/v/uv-override-prune.svg)](https://pypi.org/project/uv-override-prune/)
[![Python](https://img.shields.io/pypi/pyversions/uv-override-prune.svg)](https://pypi.org/project/uv-override-prune/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Detect prunable `override-dependencies` / `constraint-dependencies` entries in uv projects.

## Install

```bash
uv tool install uv-override-prune
```

Or run it without installing — useful for one-off checks:

```bash
uvx uv-override-prune
```

## Usage

```bash
# Detect prunable entries (default)
uv-override-prune                          # checks ./pyproject.toml
uv-override-prune path/to/pyproject.toml   # checks given file

# Remove prunable entries in place
uv-override-prune --fix
```

Example output:

```
=== override-dependencies (3 entries) ===
[KEEP]  aiohttp>=3.13.5    3.13.3
[PRUNE] httpx>=0.1.0       0.28.1
[SKIP]  foo==1.0           -

Run with --fix to prune entries marked [PRUNE].
```

Exit codes:

| Code | Meaning |
|------|---------|
| `0`  | No prunable entries (or `--fix` succeeded) |
| `1`  | Prunable entries found (without `--fix`) |
| `2`  | `pyproject.toml` not found |

## Why

uv lets you pin a transitive dependency version via `[tool.uv] override-dependencies` and `constraint-dependencies`.

A common reason to reach for these is CVE mitigation: a vulnerability is disclosed in a transitive package, and you force the patched minimum version while direct deps catch up.

Once they do, the entry is no longer doing anything — but it's easy to forget which ones are still load-bearing. Stale overrides become a judgment cost at every audit or upgrade ("is this still needed, or just history?").

`uv-override-prune` answers that mechanically: it checks whether each entry's lower bound is already satisfied by what `uv lock` would resolve without the override.

## How it works

For each candidate entry, the tool removes it in a temp copy of `pyproject.toml`, runs `uv lock` there, and checks whether the resulting natural resolution still satisfies the entry's specifier. If yes, the entry is `[PRUNE]`.

## Scope

- Targets entries in `[tool.uv] override-dependencies` and `constraint-dependencies`.
- Only specifiers using `>=` and/or `>` are checked. Entries using `==`, `~=`, `<`, `<=`, `!=` (alone or mixed) are skipped.

## Known limitations

- Projects with a `[build-system]` section may fail to lock in the temp dir if they depend on source files (e.g. `setuptools.packages.find`, Hatch dynamic version from source). `[tool.uv.sources]` path deps, workspace members, and `[project] readme` are rewritten automatically; other build-backend-specific references are not.
- One-at-a-time evaluation: if overrides interact (e.g. cascade redundancy, shared transitive deps), individual runs may miss some prunable entries. Re-run after applying removals to surface the next layer.

## License

MIT
