Skip to main content

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, scores findings across quality pillars, and emits reports for terminals, CI annotations, SARIF consumers, static HTML, and a local dashboard. It is heuristic static analysis; run it beside ruff, mypy, pytest, security scanners, and code review, not instead of them.

Status At A Glance

Field Value
Release line Published 0.2.0 package line
Runtime Python 3.11+
Package gruff-py
Import package gruffpy with py.typed
Binary gruff-py
Rule catalogue 116 rules across 11 pillars
Primary config .gruff-py.yaml; [tool.gruff-py] in pyproject.toml is also supported
Analysis schema gruff-py.analysis.v1
Baseline schema gruff-py.baseline.v1; legacy gruff.baseline.v1 can be read
Severity gate --fail-on with none, advisory, warning, error; project default via minimumSeverity: in .gruff-py.yaml / pyproject.toml
Dashboard 127.0.0.1:8765 by default

Finding fingerprints are 16-character SHA-256 derivatives kept compatible with the PHP implementation where the rule identity and finding identity match. The Python schemas remain language-prefixed. Each JSON finding also exposes a stableIdentity field — a line-insensitive companion to fingerprint for external diff tooling that needs to match "the same logical finding across line shifts" without re-baselining a moved violation; see docs/reporting.md for the input set.

Requirements

  • Python 3.11+.
  • uv for source-checkout development.
  • Git only for diff and branch-review modes.
  • Optional external mutation tooling only when mutation flags are explicitly used.

Install

Install as a project dev dependency:

uv add --dev gruff-py
uv run gruff-py init
uv run gruff-py summary

From a source checkout:

uv sync
uv run gruff-py --help
./bin/gruff-py --help

Quick Start

# Create the project config.
uv run gruff-py init

# Review the current finding mix.
uv run gruff-py summary

# Explore without failing because of findings.
uv run gruff-py analyse src/ --fail-on none

# Gate on warning and error findings.
uv run gruff-py analyse src/ --fail-on warning

# Emit SARIF for code scanning.
uv run gruff-py analyse src/ --format sarif --fail-on none > gruff.sarif

# Generate a fresh-start baseline.
uv run gruff-py analyse src/ --generate-baseline-path gruff-baseline.json --fail-on none

# Start the local dashboard.
uv run gruff-py dashboard src/ --report-interactive

Open http://127.0.0.1:8765/ for the dashboard.

Commands

Command Purpose
analyse [paths...] Run the analyser and print findings.
summary [paths...] Print compact score, pillar, rule, and file summaries.
report [paths...] Render an HTML or JSON report to stdout or --output.
list-rules Print rule metadata as text or JSON.
dashboard [paths...] Serve the local browser dashboard.
completion [shell] Print a shell completion script.
list, help Show command lists and command-specific help.

Global options mirror the broader gruff CLI surface: --silent, --quiet, --version, --ansi / --no-ansi, --no-interaction, and --verbose.

Output Formats

analyse --format <fmt> accepts:

Format Use it for
text Human terminal output.
json Full gruff-py.analysis.v1 report.
html Self-contained inspection report.
markdown Pull-request or issue comment summary.
github GitHub Actions workflow annotations.
hotspot gruff-py.hotspot.v1 file-offender JSON.
sarif SARIF 2.1.0 for code scanning.

report --format <fmt> accepts html and json.

Exit Codes

Code Meaning
0 Run completed and no finding met --fail-on.
1 At least one finding met --fail-on.
2 Fatal diagnostic such as input, parse, configuration, baseline, or diff failure.

analyse defaults to --fail-on advisory. Set minimumSeverity.analyse in .gruff-py.yaml to change the default per-project (see docs/configuration.md).

CI Usage

Generic CI command:

uv run gruff-py analyse src tests --format github --fail-on warning

SARIF jobs can write an artifact for code scanning:

uv run gruff-py analyse src tests --format sarif --fail-on none > gruff-py.sarif

Use --no-baseline for security-focused gates where adoption baselines should not hide new error-severity findings.

Configuration

Config is optional. Precedence is:

  1. --config <path>
  2. .gruff-py.yaml in the project root
  3. [tool.gruff-py] in pyproject.toml
  4. Built-in defaults

Example .gruff-py.yaml:

schemaVersion: gruff-py.config.v0.1

paths:
  ignore:
    - "tests/fixtures/**"

selection:
  excludeRules:
    - docs.missing-module-docstring

rules:
  size.file-length:
    threshold: 900
    severity: error

See Configuration for the full shape.

Rules And Pillars

The v0.1 catalogue contains 115 rules across 11 pillars:

Pillar Rules
size 7
complexity 5
maintainability 1
dead-code 10
modernisation 1
naming 9
documentation 13
security 26
sensitive-data 9
test-quality 33
design 1

coupling, architecture, and mutation are reserved schema or future catalogue names; they do not have shipping rules in 0.1. See Rules for rule IDs, defaults, and remediation guidance.

Baselines And Changed-Code Scans

Baselines suppress reviewed findings by fingerprint:

uv run gruff-py analyse src/ --generate-baseline-path gruff-baseline.json --fail-on none
uv run gruff-py analyse src/ --baseline-path gruff-baseline.json --fail-on warning
uv run gruff-py analyse src/ --no-baseline --fail-on none

Changed-code scans can filter to changed lines or compare against a base ref:

uv run gruff-py analyse src/ --diff staged --format github --fail-on warning
uv run gruff-py analyse src/ --diff-vs origin/main --changed-only --fail-on none

Display filters such as --min-severity, --include-pillar, and --exclude-rule reduce rendered output without changing which rules execute.

Dashboard

uv run gruff-py dashboard src/ --host 127.0.0.1 --port 8765 --report-interactive

The dashboard serves a local browser UI for repeated scans. It has no authentication and is intended for local development; keep it on loopback unless the network is trusted. See Dashboard for supported controls and safety notes.

In polyglot repositories, remember that gruff-go, gruff-php, and gruff-py all default to port 8765; use --port when running multiple dashboards at the same time.

Trust Boundary

Default scans are local source inspections. gruff-py parses Python source and selected project metadata; it does not execute target application code, run tests, query vulnerability feeds, or contact package registries. Git is used only for explicit diff modes. External mutation tooling is used only when explicitly requested by mutation flags. Sensitive-data previews are redacted before they reach terminal, JSON, SARIF, GitHub, Markdown, hotspot, or HTML output.

Stability Contract

The 0.1.x line treats rule IDs, finding fingerprints, baseline identity, gruff-py.analysis.v1, gruff-py.baseline.v1, gruff-py.hotspot.v1, SARIF rendering, and CLI exit semantics as compatibility-sensitive. Breaking changes should be tagged as a future minor release and recorded in CHANGELOG.md.

How It Compares

Tool Relationship
ruff Fast linting and formatting. gruff-py adds scoring, baselines, reports, dashboard, and project-quality rules.
mypy / Pyright Type checking. gruff-py does not prove type correctness.
pytest Runtime tests. gruff-py can flag test-quality smells but does not prove behavior.
Bandit / Semgrep / vulnerability scanners Security-focused checks. gruff-py reports local static signals and does not replace specialized scanners.
Vulture / dead-code tools Focused unused-code detection. gruff-py includes broader quality scoring and reporting.

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
make check

make check uses the lint target, which runs ruff check --fix. Use the explicit commands above when you need non-mutating release verification.

Documentation

Author

Built by Matthew Hansen.

License

MIT

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

gruff_py-0.2.0.tar.gz (456.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gruff_py-0.2.0-py3-none-any.whl (413.0 kB view details)

Uploaded Python 3

File details

Details for the file gruff_py-0.2.0.tar.gz.

File metadata

  • Download URL: gruff_py-0.2.0.tar.gz
  • Upload date:
  • Size: 456.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

Hashes for gruff_py-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9162e583456efca65ba24a76662c29edeace8deaa4a035bf02ab4110b4d07170
MD5 e797e40072b6d93f74553de4ba952893
BLAKE2b-256 cb09392e2c67b9424db9dd5c85964780705a4c423f5032fe568d04185c87e51a

See more details on using hashes here.

File details

Details for the file gruff_py-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: gruff_py-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 413.0 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

Hashes for gruff_py-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3544bd0cb58c6882286e7faa5b0725540b7da4d7ce5b54a015aa68b7dee96aa6
MD5 94500b0dcd36fd11813df5d25ff63d3a
BLAKE2b-256 46a503cdd934ae8a7989ad90263ab694929bc2b7e8ffbac9efec1fe7523703ff

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page