Metadata-Version: 2.4
Name: vulture-rs
Version: 1.0.0
Classifier: License :: OSI Approved :: MIT License
License-File: LICENSE
Summary: Rust reimplementation of vulture (dead code finder) - output-identical to vulture 2.13
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# vulture-rs

A Rust reimplementation of
[vulture](https://github.com/jendrikseipp/vulture) (the Python
dead-code finder), built on the
[ruff](https://github.com/astral-sh/ruff) parser for performance.
Versioned independently; the upstream parity target (currently
**vulture 2.13**) is stated here, in the package description, and in
the `CHANGELOG` (a dated entry per release, enforced at release
time).
Drop-in compatible: the binary is named `vulture`, accepts the same
CLI, and produces byte-identical output — tools that shell out to
`vulture` via `PATH` pick it up unchanged (the one visible
difference: `--version` reports this package's own version, not
`2.13`).

## Install

```bash
pip install vulture-rs   # ships the `vulture` binary
```

Wheels for linux x86_64/aarch64 and macOS arm64, published via the
manually-dispatched `Release to PyPI` workflow (wheels only, no
sdist); every wheel is smoke-tested before it ships.

## Results

A large production codebase (6,553 files), 8 cores, median of 5:

| tool                   | wall time | speedup |
| ---------------------- | --------- | ------- |
| Python vulture 2.13    | 14.31 s   | 1x      |
| vulture-rs (8 threads) | 0.43 s    | 33x     |
| vulture-rs (1 thread)  | 1.06 s    | 13.5x   |

Peak memory is comparable (~100 MiB).

## Parity

Output is byte-identical (stdout + exit codes) to `vulture==2.13`:

- on the 6,553-file production codebase above — 2,687 findings,
  zero diff — across assorted flag combinations;
- across `tests/differential.sh`: an edge-case corpus (noqa quirks,
  whitelist masking, elif chains, encodings incl. latin-1/BOM/CRLF,
  unreachable code, invisible bindings, decorated defs) times a
  12-entry flag matrix;
- on two alien corpora: CPython 3.12's stdlib (2,621 findings,
  byte-identical incl. normalized stderr) and a 22,286-file
  `site-packages` corpus (58k findings, 137s -> 3.4s, 41x). There,
  144 of 58,008 stdout lines and 11 stderr lines differ - every one
  triaged to registered deviations (D1 type comments, D16 CPython
  `SyntaxWarning` chatter), zero parity bugs;
- on six popular open-source repos (requests, flask, click, rich,
  celery, django; 3,736 files, 25-54x) — byte-identical.

Known, deliberate deviations (error-message prose, type comments,
crash-path cleanups) are enumerated in
`docs/vulture-rust-spec.md` §1; the full behavioral contract lives in
`docs/vulture-spec.md`. Both specs were reverse-engineered from
vulture 2.13 and review-hardened before this implementation.

The parity reference is vulture 2.13 **on CPython 3.12**: the parser
is version-gated to 3.12, so syntax newer than that (PEP 696
type-param defaults, t-strings, …) is a syntax error here exactly as
it is there. Bumping the reference is a deliberate task.

## Build & test

```bash
cargo build --release            # target/release/vulture
cargo test                       # CPython-generated vector tests
tests/differential.sh <python-vulture> target/release/vulture
tests/og_corpus.sh <python-vulture> target/release/vulture
```

CI (`.github/workflows/ci.yml`) runs fmt, clippy, the vector tests,
and both differential harnesses against a pinned `vulture==2.13` on
every PR and push to `main`.

Regenerate the test vectors with `python3 tests/gen_vectors.py`
(needs CPython 3.12).

The `ruff_*` dependencies are git-pinned to a ruff release tag (the
crates.io releases under those names are stale placeholders). Treat
upgrades as a deliberate task gated on the differential suite.

## Usage

Same CLI as Python vulture:

```bash
vulture <paths> [--exclude PATTERNS] [--ignore-names PATTERNS]
        [--ignore-decorators PATTERNS] [--min-confidence N]
        [--sort-by-size] [--make-whitelist] [-v]
```

Exit codes: 0 clean, 1 invalid input, 2 invalid arguments, 3 dead
code found.

