culler 0.1.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,356 @@
1
+ Metadata-Version: 2.4
2
+ Name: culler
3
+ Version: 0.1.0
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Environment :: Console
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Programming Language :: Rust
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Classifier: Topic :: Software Development :: Testing
18
+ Classifier: Topic :: Utilities
19
+ License-File: LICENSE
20
+ Summary: A precise Python dead-code analyzer.
21
+ Keywords: dead-code,static-analysis,python,cli,rust
22
+ Author: Beau Hayes-Pollard
23
+ License-Expression: MIT
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
26
+ Project-URL: Benchmark, https://github.com/beaubhp/culler/tree/main/benchmark
27
+ Project-URL: Homepage, https://github.com/beaubhp/culler
28
+ Project-URL: Issues, https://github.com/beaubhp/culler/issues
29
+ Project-URL: Repository, https://github.com/beaubhp/culler
30
+
31
+ # Culler
32
+
33
+ [![PyPI](https://img.shields.io/pypi/v/culler.svg)](https://pypi.org/project/culler/)
34
+ [![Python versions](https://img.shields.io/pypi/pyversions/culler.svg)](https://pypi.org/project/culler/)
35
+ [![CI](https://github.com/beaubhp/culler/actions/workflows/ci.yml/badge.svg)](https://github.com/beaubhp/culler/actions/workflows/ci.yml)
36
+ [![Package Check](https://github.com/beaubhp/culler/actions/workflows/package-check.yml/badge.svg)](https://github.com/beaubhp/culler/actions/workflows/package-check.yml)
37
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/beaubhp/culler/blob/main/LICENSE)
38
+
39
+ Culler is a fast, high-confidence dead-code analyzer for Python projects.
40
+
41
+ It is built in Rust, distributed as a single command-line tool, and designed to
42
+ find dead Python code without turning ordinary public APIs, exports, tests, or
43
+ dynamic Python edges into noisy findings.
44
+
45
+ ```bash
46
+ culler check .
47
+ ```
48
+
49
+ <p align="center">
50
+ <picture>
51
+ <source
52
+ media="(prefers-color-scheme: dark)"
53
+ srcset="benchmark/assets/runtime-dark.png"
54
+ >
55
+ <source
56
+ media="(prefers-color-scheme: light)"
57
+ srcset="benchmark/assets/runtime-light.png"
58
+ >
59
+ <img
60
+ width="49%"
61
+ alt="Runtime benchmark comparing Culler, Vulture, and deadcode"
62
+ src="https://raw.githubusercontent.com/beaubhp/culler/main/benchmark/assets/runtime-dark.png"
63
+ >
64
+ </picture>
65
+ <picture>
66
+ <source
67
+ media="(prefers-color-scheme: dark)"
68
+ srcset="benchmark/assets/f1-dark.png"
69
+ >
70
+ <source
71
+ media="(prefers-color-scheme: light)"
72
+ srcset="benchmark/assets/f1-light.png"
73
+ >
74
+ <img
75
+ width="49%"
76
+ alt="F1 benchmark comparing Culler high-plus-review, Culler, Vulture, and deadcode"
77
+ src="https://raw.githubusercontent.com/beaubhp/culler/main/benchmark/assets/f1-dark.png"
78
+ >
79
+ </picture>
80
+ </p>
81
+
82
+ <p align="center">
83
+ <sub>
84
+ Left: median wall-clock runtime, where lower is better. Right: F1 score,
85
+ the balance between precision and recall, where higher is better.
86
+ </sub>
87
+ </p>
88
+
89
+ Benchmark: 15 realistic Python projects, 57,068 lines, 715 expected findings,
90
+ and comparisons against Vulture and deadcode. Results are corpus-specific; the
91
+ methodology and reproduction commands are below.
92
+
93
+ ## Highlights
94
+
95
+ - **High-confidence findings by default.** Culler reports the findings it can
96
+ support strongly, and keeps review-confidence findings available separately.
97
+ - **Whole-project reachability for applications.** Production roots let Culler
98
+ identify code that is unreachable from known entry points.
99
+ - **Conservative library analysis.** Exports, public surfaces, tests, and
100
+ dynamic behavior are handled carefully to avoid noisy reports.
101
+ - **Useful without heavy setup.** Basic unused-code checks work with little or
102
+ no configuration, and deeper reachability is enabled with `pyproject.toml`.
103
+ - **Automation-friendly output.** JSON output uses stable rule and diagnostic
104
+ identifiers for editors, dashboards, CI, and benchmark tooling.
105
+
106
+ ## Installation
107
+
108
+ The recommended installation methods for the CLI are `uv tool` and `pipx`:
109
+
110
+ ```bash
111
+ uv tool install culler
112
+ ```
113
+
114
+ ```bash
115
+ pipx install culler
116
+ ```
117
+
118
+ You can also install it into an existing Python environment:
119
+
120
+ ```bash
121
+ python -m pip install culler
122
+ ```
123
+
124
+ The PyPI package installs the compiled `culler` binary. It does not expose a
125
+ Python import API yet.
126
+
127
+ ## Quick Start
128
+
129
+ Run Culler on the current project:
130
+
131
+ ```bash
132
+ culler check .
133
+ ```
134
+
135
+ Emit machine-readable JSON:
136
+
137
+ ```bash
138
+ culler check . --format json
139
+ ```
140
+
141
+ Show review-confidence findings as well as high-confidence findings:
142
+
143
+ ```bash
144
+ culler check . --show-review
145
+ ```
146
+
147
+ Explain a specific candidate or finding:
148
+
149
+ ```bash
150
+ culler explain <candidate-or-finding-id> .
151
+ ```
152
+
153
+ Exit codes are intentionally small:
154
+
155
+ | Code | Meaning |
156
+ | --- | --- |
157
+ | `0` | Analysis completed without default-visible findings. |
158
+ | `1` | Analysis completed and default-visible findings were reported. |
159
+ | `2` | Input, configuration, parse, or completeness error. |
160
+
161
+ ## Configuration
162
+
163
+ Culler reads configuration from `pyproject.toml`.
164
+
165
+ ```toml
166
+ [tool.culler]
167
+ src = "src"
168
+ mode = "auto"
169
+ target-python = "3.12"
170
+ ```
171
+
172
+ For applications, declare production roots when you want reachability findings:
173
+
174
+ ```toml
175
+ [tool.culler]
176
+ src = "src"
177
+ mode = "application"
178
+ root_coverage = "complete"
179
+ roots = ["my_app.cli:main"]
180
+ ```
181
+
182
+ For libraries, Culler treats exported and externally visible surfaces more
183
+ conservatively:
184
+
185
+ ```toml
186
+ [tool.culler]
187
+ src = "src"
188
+ mode = "library"
189
+ ```
190
+
191
+ Useful fields:
192
+
193
+ | Field | Purpose |
194
+ | --- | --- |
195
+ | `src` | Source root or roots to analyze. |
196
+ | `mode` | `auto`, `application`, or `library`. |
197
+ | `root_coverage` | `partial` or `complete` when roots are known. |
198
+ | `roots` | Application entry points such as `pkg.cli:main`. |
199
+ | `tests` | Test paths when they are not discoverable conventionally. |
200
+ | `target-python` | Python syntax/semantic target, currently `3.10` through `3.15`. |
201
+ | `exclude` | Glob patterns to exclude from analysis. |
202
+ | `allow_partial` | Permit partial analysis without escalating to exit code `2`. |
203
+
204
+ ## Output and Rules
205
+
206
+ Text output is optimized for local development and CI logs. JSON output is
207
+ intended for editors, dashboards, benchmarks, and automation.
208
+
209
+ ```bash
210
+ culler check . --format json
211
+ ```
212
+
213
+ Rule IDs are stable machine-readable identifiers:
214
+
215
+ | Rule | Finding |
216
+ | --- | --- |
217
+ | `CULL001` | Unreferenced function. |
218
+ | `CULL002` | Unreferenced class. |
219
+ | `CULL003` | Root-unreachable function. |
220
+ | `CULL004` | Root-unreachable class. |
221
+ | `CULL005` | Unused import binding. |
222
+ | `CULL006` | Unused local binding. |
223
+ | `CULL007` | Unreachable statement range. |
224
+ | `CULL008` | Unused private method. |
225
+
226
+ Diagnostic IDs such as `CULL_P0101` describe analysis, parsing, or
227
+ configuration problems.
228
+
229
+ ## Benchmark Methodology
230
+
231
+ The benchmark compares Culler with Vulture and deadcode on one fixed corpus of
232
+ artificial but realistic Python projects. The projects are artificial because
233
+ precision and recall need ground truth; many real repositories contain little
234
+ confirmed dead code, and exhaustive manual labeling is subjective. The corpus is
235
+ designed to resemble code developers commonly inherit: services, libraries,
236
+ CLIs, workers, pipelines, plugin systems, configuration packages, and
237
+ utility-heavy AI-era codebases.
238
+
239
+ | Scope | Value |
240
+ | --- | ---: |
241
+ | Projects | 15 |
242
+ | Python files | 374 |
243
+ | Python LOC | 57,068 |
244
+ | Expected findings | 715 |
245
+ | Clean projects | 2 |
246
+ | Large or noisy projects | 2 |
247
+
248
+ The expected findings live under `benchmark/expected/` and use comparable
249
+ categories: unused imports, unused locals, unreachable statements, unused
250
+ functions, unused classes, and unused private methods.
251
+
252
+ ### Tool Scope
253
+
254
+ | Tool | Why included |
255
+ | --- | --- |
256
+ | Culler | Subject under evaluation. |
257
+ | Vulture | Classic Python dead-code detector. |
258
+ | deadcode | Newer whole-codebase Python unused-code detector. |
259
+
260
+ Ruff, Pylint, Pyflakes, Flake8, autoflake, pycln, and unimport are not included
261
+ in the headline comparison. They overlap on some unused-import or unused-local
262
+ checks, but they are linters or cleanup tools rather than direct whole-project
263
+ dead-code analyzers.
264
+
265
+ ### Scoring
266
+
267
+ Every expected finding not matched by a tool is a false negative. Every parsed
268
+ tool finding in a scoreable category that does not match an expected finding is
269
+ a false positive, including findings in clean projects. Matching is
270
+ deterministic by category, path, symbol name where relevant, and source span;
271
+ duplicate reports count once as a true positive and then as false positives.
272
+
273
+ Culler's headline score uses high-confidence findings. The benchmark also
274
+ reports a Culler high-plus-review aggregate, which includes review-confidence
275
+ findings from the same Culler JSON run. It does not represent a separate timed
276
+ CLI invocation.
277
+
278
+ ### Runtime
279
+
280
+ Runtime includes subprocess startup time. That reflects command-line user
281
+ experience and avoids special-casing tools written in different languages. By
282
+ default, each tool gets one warmup run and five measured runs per project; the
283
+ report uses median wall time. Result JSON records command lines, tool versions,
284
+ Python version, OS, CPU, memory, and the Culler commit.
285
+
286
+ Peak RSS is recorded where `/usr/bin/time -l` exposes it. If unavailable, the
287
+ result uses `null`.
288
+
289
+ ### Running the Benchmark
290
+
291
+ Validate the corpus and expected files:
292
+
293
+ ```bash
294
+ python3 benchmark/run.py --validate-only
295
+ ```
296
+
297
+ Run the benchmark runner self-tests:
298
+
299
+ ```bash
300
+ python3 benchmark/test_run.py
301
+ ```
302
+
303
+ Build Culler and run the full benchmark:
304
+
305
+ ```bash
306
+ cargo build --release
307
+ python3 benchmark/run.py \
308
+ --culler target/release/culler \
309
+ --tools culler,vulture,deadcode \
310
+ --runs 5 \
311
+ --results benchmark/results/latest.json
312
+ ```
313
+
314
+ Generated reports are written under `benchmark/results/` and ignored by
315
+ default. Raw tool outputs are retained under `benchmark/results/raw/`.
316
+
317
+ ## Development
318
+
319
+ Prerequisites:
320
+
321
+ - Rust 1.82 or newer
322
+ - Python 3.10 or newer
323
+ - `uv` for packaging and benchmark helper commands
324
+
325
+ Core checks:
326
+
327
+ ```bash
328
+ cargo fmt --all --check
329
+ cargo check
330
+ cargo clippy --all-targets --all-features -- -D warnings
331
+ cargo test
332
+ python3 benchmark/test_run.py
333
+ python3 benchmark/run.py --validate-only
334
+ ```
335
+
336
+ Build the PyPI package locally:
337
+
338
+ ```bash
339
+ uvx maturin build --release --out dist --sdist
340
+ uvx twine check dist/*
341
+ ```
342
+
343
+ ## Status
344
+
345
+ Culler is pre-1.0 software. Rule IDs are intended to be stable, but CLI,
346
+ configuration, and JSON output details may still evolve before `1.0`.
347
+
348
+ Releases use reviewed PRs and changelog updates. See
349
+ [`CONTRIBUTING.md`](https://github.com/beaubhp/culler/blob/main/CONTRIBUTING.md)
350
+ for commit and release guidance.
351
+
352
+ ## License
353
+
354
+ Culler is released under the MIT License. See
355
+ [`LICENSE`](https://github.com/beaubhp/culler/blob/main/LICENSE).
356
+
@@ -0,0 +1,6 @@
1
+ culler-0.1.0.data/scripts/culler.exe,sha256=mf6ZM6o1hB72EYvh7rmd1Ji6j0GkLkOETVnvnfeU60E,5691904
2
+ culler-0.1.0.dist-info/METADATA,sha256=b1LJjTIl8n10Huvk01m-7-mY5uRlHV4irZ-7VQzv3sM,11361
3
+ culler-0.1.0.dist-info/WHEEL,sha256=2zDlIYIdD4m4N3p5DVEG3iJhGLdhsBQgdH-FqVkAur8,94
4
+ culler-0.1.0.dist-info/licenses/LICENSE,sha256=OrV7tYI_7Ido1ujE-NbSnB22SEPOlf3YKjTonpFjw6E,1096
5
+ culler-0.1.0.dist-info/sboms/culler-cli.cyclonedx.json,sha256=VNq7z7EaLk7Rm-aDjohuEwPtfT7g55c2tDeOcPsJ1TU,125694
6
+ culler-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.14.1)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Beau Hayes-Pollard
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.