Python-native GazeCRAP analysis engine
Project description
gaze-py
gaze-py is a Python-native port of gaze, the GazeCRAP analysis engine. It detects observable side effects in Python functions using AST-only static analysis (no code execution, no imports of analysed modules), classifies each effect as contractual or incidental using a five-signal confidence engine, and computes CRAP and GazeCRAP scores to surface functions that are both complex and under-tested. The output is schema-compatible with the Go gaze implementation.
Requirements
- Python 3.11+
Installation
# Run without installing (recommended for one-off use)
uvx --from gaze-py gazepy --help
# Permanent install
uv tool install gaze-py
# Or with pip
pip install gaze-py
Basic usage
# Analyse a source directory (CRAP will be null — no coverage provided)
gazepy analyze src/
# JSON output (default)
gazepy analyze src/ --format=json
# Human-readable text output (one line per function)
gazepy analyze src/ --format=text
# CRAP scoring — auto-runs pytest for coverage
gazepy crap src/
# CRAP scoring with a pre-generated coverage report
gazepy crap src/ --coverprofile coverage.json
# Scaffold OpenCode agent and command files into .opencode/
gazepy init
CRAP scoring with gazepy crap
CRAP scoring requires line coverage data. The crap command can collect coverage
automatically by running pytest, or accept a pre-generated coverage.py JSON report:
# Auto-run pytest and collect coverage (requires pytest-cov)
gazepy crap src/
# Use a pre-generated coverage report (recommended in CI to avoid a double test run)
pytest --cov=your_package --cov-report=json:coverage.json
gazepy crap src/ --coverprofile coverage.json
When coverage is provided, the line_coverage and crap fields are populated in the
output. When omitted, those fields are null (not 0.0) — null means "not measured",
not "zero coverage". GazeCRAP and quadrant fields remain null until O1 ships.
The analyze command detects side effects only — it does not compute CRAP scores.
Use gazepy crap for CRAP scoring.
Understanding the output
Each function in the output includes:
| Field | Description |
|---|---|
side_effects |
List of detected observable side effects with type, tier, and classification |
complexity |
McCabe cyclomatic complexity |
line_coverage |
Fraction of lines covered (0.0–1.0), or null if not provided |
crap |
CRAP score (complexity² × (1 − coverage)³ + complexity), or null |
gaze_crap |
GazeCRAP score using contract coverage, or null (O1 deferred) |
quadrant |
Q1–Q4 classification based on CRAP and GazeCRAP, or null |
fix_strategy |
Recommended action: add_tests, decompose_and_test, or decompose |
contract_coverage |
Fraction of contractual effects covered by tests, or null |
The summary section includes recommended_actions — up to 20 functions sorted by
priority (add_tests → decompose_and_test → decompose) that exceed the CRAP threshold.
Current limitations
- GazeCRAP scoring deferred: The O1 quality/assertion mapping engine (which
computes
contract_coveragefrom test assertions) is not yet implemented. As a result,gaze_crap,contract_coverage, andquadrantare alwaysnullin this release. Thefix_strategyfield uses CRAP-only rules (Q3/add_assertions is unreachable without O1). - Effect confidence range deferred: The
effect_confidence_rangefield is present in the output schema (asnull) but not yet computed.
Releasing
Releases are published to PyPI via GitHub Actions using trusted publishing (OIDC — no stored secrets).
One-time setup (already done)
- PyPI trusted publisher: pypi.org → gaze-py project → Settings →
Publishing → publisher configured for
mpeter/gaze-py, workflowrelease.yml, environmentpypi. - GitHub environment: repo Settings → Environments →
pypi(optional approval gate).
Releasing a new version
- Bump
versioninpyproject.tomland__version__insrc/gaze_py/__init__.pyin a PR. Merge tomain. - Go to GitHub Actions → Release → Run workflow.
- Enter the tag matching the version (e.g.
v0.3.0). - Approve the
pypienvironment gate if configured. - The workflow validates, tags, builds, and publishes automatically.
Project details
Release history Release notifications | RSS feed
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 gaze_py-0.3.0.tar.gz.
File metadata
- Download URL: gaze_py-0.3.0.tar.gz
- Upload date:
- Size: 441.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
423bbc4582847711d70b63b4d15a882e363827519abbde7d40138b9096066abf
|
|
| MD5 |
296820b11afb1832a73f0bdf57b43b26
|
|
| BLAKE2b-256 |
cb6befeb5c040cf9d743783f014e9090a18df4789963a0ed671082ede08af1b5
|
Provenance
The following attestation bundles were made for gaze_py-0.3.0.tar.gz:
Publisher:
release.yml on mpeter/gaze-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gaze_py-0.3.0.tar.gz -
Subject digest:
423bbc4582847711d70b63b4d15a882e363827519abbde7d40138b9096066abf - Sigstore transparency entry: 1817884824
- Sigstore integration time:
-
Permalink:
mpeter/gaze-py@5c2bf5f951e6ef69a7a3c06844a442b4a82c33f3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mpeter
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5c2bf5f951e6ef69a7a3c06844a442b4a82c33f3 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file gaze_py-0.3.0-py3-none-any.whl.
File metadata
- Download URL: gaze_py-0.3.0-py3-none-any.whl
- Upload date:
- Size: 76.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05735b4db44f2997f2b26c79d5033135237ff7e1eee9ab159a4201d2c9d843f8
|
|
| MD5 |
f8c8a963b801b65b29b4402a8c5a29da
|
|
| BLAKE2b-256 |
6a334d2906178a03942efb8c59e5c555244f25d6d5d99a12b8e59b588c47d4f1
|
Provenance
The following attestation bundles were made for gaze_py-0.3.0-py3-none-any.whl:
Publisher:
release.yml on mpeter/gaze-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gaze_py-0.3.0-py3-none-any.whl -
Subject digest:
05735b4db44f2997f2b26c79d5033135237ff7e1eee9ab159a4201d2c9d843f8 - Sigstore transparency entry: 1817885061
- Sigstore integration time:
-
Permalink:
mpeter/gaze-py@5c2bf5f951e6ef69a7a3c06844a442b4a82c33f3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/mpeter
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5c2bf5f951e6ef69a7a3c06844a442b4a82c33f3 -
Trigger Event:
workflow_dispatch
-
Statement type: