Python project quality analyser.
Project description
gruff-py
gruff-py is the Python implementation of gruff, an opinionated project
quality analyser. It walks Python projects, applies a broad rule catalogue, and
emits scored reports for local review, CI, code scanning, and a browser
dashboard.
It is heuristic static analysis. Use it beside tools such as ruff, mypy,
pytest, and security scanners, not as a replacement for them.
Status
0.1.0 is the first public release.
- Python 3.11+
- 116 rules across 10 active quality pillars
- Text, JSON, HTML, Markdown, GitHub annotation, hotspot, and SARIF reports
- Local dashboard served from
127.0.0.1by default .gruff-py.yamland[tool.gruff-py]configuration- PHP-compatible finding fingerprints
- Python import package
gruffpywith a typed package marker viapy.typed - MIT licensed (see
LICENSE.md)
Install
From this repository:
uv sync
./bin/gruff-py --help
The package entry point is gruff-py, so uv run gruff-py --help is
equivalent after uv sync.
After the package is published:
pipx install gruff-py
gruff-py --help
Quick Start
Analyse a project:
uv run gruff-py analyse src/
Emit JSON for automation:
uv run gruff-py analyse src/ --format json --fail-on error > gruff.json
Emit SARIF for code scanning:
uv run gruff-py analyse src/ --format sarif --fail-on none > gruff.sarif
Create a standalone HTML report:
uv run gruff-py analyse src/ --format html --report-interactive > gruff-report.html
Run the local dashboard:
uv run gruff-py dashboard src/ --report-interactive
Then open:
http://127.0.0.1:8765/
CLI
gruff-py [GLOBAL OPTIONS] <command>
gruff-py analyse [OPTIONS] [PATHS]...
gruff-py report [OPTIONS] [PATHS]...
gruff-py summary [OPTIONS] [PATHS]...
gruff-py list-rules [OPTIONS]
gruff-py dashboard [OPTIONS] [PATHS]...
gruff-py completion [SHELL]
Global options mirror the gruff-php CLI surface: --silent, --quiet,
--version, --ansi / --no-ansi, --no-interaction, and --verbose.
Common analyse and report options:
| Option | Meaning |
|---|---|
--format text |
Terminal summary, the default |
--format json |
Full gruff-py.analysis.v1 payload |
--format html |
Self-contained dark HTML report |
--format markdown |
Pull-request or issue comment summary |
--format github |
GitHub Actions annotation commands |
--format hotspot |
gruff-py.hotspot.v1 file offender JSON |
--format sarif |
SARIF 2.1.0 code-scanning output |
--fail-on error |
Exit non-zero for findings at or above the threshold |
--no-config |
Ignore .gruff-py.yaml and [tool.gruff-py] |
--include-ignored |
Scan default-ignored directories and .gitignore exclusions |
--min-severity warning |
Display only warning/error findings |
--include-pillar documentation |
Display only selected pillar findings |
--exclude-rule docs.missing-function-docstring |
Hide selected rule findings |
Additional commands:
| Command | Meaning |
|---|---|
gruff-py report --format html --output gruff.html |
Render an HTML or JSON report to a file or stdout |
gruff-py summary --format text |
Print compact per-pillar, top-rule, and top-file counts |
gruff-py list-rules --format json |
Print registered rule metadata |
gruff-py list |
List available commands |
gruff-py help analyse |
Display command help |
gruff-py completion bash |
Dump a shell completion script |
Exit codes:
| Code | Meaning |
|---|---|
0 |
Run completed and no finding reached --fail-on |
1 |
At least one finding reached --fail-on |
2 |
Input, parse, or configuration diagnostic |
Configuration
Config is optional. Precedence is:
--config <path>.gruff-py.yamlin the project root[tool.gruff-py]inpyproject.toml- Built-in defaults
Example .gruff-py.yaml:
paths:
ignore:
- "tests/fixtures/**"
selection:
excludeRules:
- docs.missing-module-docstring
rules:
size.file-length:
threshold: 900
severity: error
See Configuration for the full shape.
Quality Pillars
gruff-py scores findings across these active pillars:
sizecomplexitymaintainabilitydead-codenamingdocumentationsecuritysensitive-datatest-qualitydesign
modernisation, coupling, architecture, and mutation are reserved schema
or future catalogue names. They do not all have shipping rules in 0.1.
See Rules for the rule catalogue.
Reports And Dashboard
- Reports explains every output format and CI use case.
- Dashboard documents the local browser dashboard.
The JSON schema string is gruff-py.analysis.v1; hotspot output uses
gruff-py.hotspot.v1. Finding fingerprints are 16-character SHA-256 derivatives
kept compatible with the PHP implementation. SARIF is rendered from the same
native report data without changing native schemas or fingerprints; SARIF result
fingerprints use partialFingerprints.gruffFingerprint.
Development
uv sync --extra dev
uv run ruff check src tests
uv run ruff format --check src tests
uv run mypy src
uv run pytest
The Makefile mirrors these commands:
make check
Note that make check uses the lint target, which runs ruff check --fix.
Use the explicit commands above when you need non-mutating release verification.
Performance harness
scripts/test-performance.sh runs a fixed workload matrix (cold-start,
analyse on src//tests/, reporter variants, synthetic 100/1000-file
fixtures) with median/p95/min/max wall-clock, peak RSS via
/usr/bin/time -v, and per-rule cost attribution from cProfile. Baselines
live under scripts/performance-baselines/<host>.json; pass --baseline to
fail the script on regressions.
make perf-quick # CI smoke: cold-start + analyse-src vs baseline
make perf # full suite vs baseline
make perf-baseline # overwrite the linux-x86_64 baseline with the current run
Project Docs
Author
Built by Matthew Hansen.
License
Project details
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 gruff_py-0.1.0.tar.gz.
File metadata
- Download URL: gruff_py-0.1.0.tar.gz
- Upload date:
- Size: 395.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","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 |
8632f875d1f9c335020719aeab9718bba5af9fa4b8b62423c682588668843f7f
|
|
| MD5 |
309f4b0b7ecfb08b0e21c88b1bd0963c
|
|
| BLAKE2b-256 |
b7324fc6d938f3551475e0b934788c0892572b7557b1af2fff494c37a26ff58e
|
File details
Details for the file gruff_py-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gruff_py-0.1.0-py3-none-any.whl
- Upload date:
- Size: 392.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","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 |
5e921d60149c434b1a13b5b7354518e16caecde05098c9715ef849560d7ba60e
|
|
| MD5 |
42ca637ce592c0a9aecbd8d1fb6a37e7
|
|
| BLAKE2b-256 |
a36da4cf432574dc2379a2c6dd6c398f58fda5897e271b2763ef0ac28d8e0f39
|