PyHealth Scanner
A unified Python project health analyzer.
PyHealth Scanner is a single command that inspects your Python project from every angle — code quality, security, dependencies, documentation, complexity, and more — and gives you an actionable health report.
Version
Current version: 2.0.0 — Production Ready
PyHealth Scanner 2.0.0 provides a unified analysis suite covering code quality, security, complexity, dependencies, documentation, Git health, health scoring, and multi-format reporting.
Project Status
| Feature | Status |
|---|---|
| Package foundation | ✅ Available |
CLI (pyhealth version, pyhealth scan) |
✅ Available |
| Code quality analysis (Ruff) | ✅ Available |
| Security scanning (Bandit + Native Scanner) | ✅ Available |
| Complexity analysis (Radon) | ✅ Available |
| Dependency analysis (pip-audit & AST) | ✅ Available |
| Documentation analysis | ✅ Available |
| Git health analysis | ✅ Available |
| Health scoring | ✅ Available |
| Reports (JSON, HTML, Markdown, CSV, SARIF) | ✅ Available |
Unified Report Engine
PyHealth includes a report generator capable of outputting reports in JSON, Markdown, HTML, CSV, and SARIF v2.1.0 formats.
# Render to console (default)
pyhealth report .
# Output formatted JSON
pyhealth report . --format json
# Output Markdown report
pyhealth report . --format markdown --output report.md
# Generate self-contained offline HTML report
pyhealth report . --format html --output report.html
# Export findings to CSV
pyhealth report . --format csv --output report.csv
# Export SARIF for GitHub Code Scanning / CI/CD
pyhealth report . --format sarif --output results.sarif
# Generate all report formats at once
pyhealth report . --format all --output reports/
Supported Report Formats
console: Rich CLI summary display (same aspyhealth scan .).json: Complete, deterministic JSON dataset of project metrics, health score, category scores, and sanitized issues.markdown: GitHub Flavored Markdown report with executive summary, category table, recommendations, and detailed findings.html: Self-contained, responsive, offline HTML report with embedded styling. Zero external network/CDN dependencies.csv: Standard CSV spreadsheet export with one row per issue (category,severity,code,message,file,line,column,tool,suggestion).sarif: Standard SARIF v2.1.0 JSON format for GitHub Security Scanning and CI/CD code analysis pipelines.all: Generatesreport.json,report.md,report.html,report.csv, andreport.sarifin one pass.
Single Analysis Execution & Privacy
When generating reports (including --format all), PyHealth Scanner executes project analyzers exactly once and feeds the unified ProjectReport model to the requested renderers. All report formats strictly preserve the secret-privacy guarantee: actual password, key, and token contents are never exposed.
Unified Health Score Engine
The Health Score Engine evaluates all analyzer results to calculate a weighted 0–100 overall score, PyHealth Grade, category scores, top priority issues, and deduplicated recommendations.
PyHealth Grade Interpretation
- 90–100: Excellent
- 80–89: Good
- 70–79: Fair
- 50–69: Needs Improvement
- 0–49: Poor
Disclaimer: The PyHealth score is an opinionated engineering metric designed to help prioritize improvements. It is not a formal or industry-standard software quality measurement.
Category Weights
Default category weights sum to 1.00:
| Category | Default Weight | Key Inputs |
|---|---|---|
| Security | 0.30 |
Bandit findings, native secret findings (PYSxxx) |
| Quality | 0.20 |
Ruff lints, long functions, deep nesting, TODO/FIXME, duplicates, syntax errors |
| Complexity | 0.15 |
Maintainability Index (MI), high complexity findings (PYH101) |
| Dependencies | 0.15 |
Vulnerabilities (PYH203), missing deps (PYH202), unused deps (PYH201) |
| Documentation | 0.10 |
Docstring coverage %, required doc files (README, LICENSE, etc.) |
| Structure | 0.05 |
Large files, empty directories, duplicate file groups |
| Git | 0.05 |
.gitignore presence, large tracked files, sensitive tracked files |
Custom Category Weights Configuration
Configure custom weights in pyproject.toml:
[tool.pyhealth.score]
security = 0.30
quality = 0.20
complexity = 0.15
dependencies = 0.15
documentation = 0.10
structure = 0.05
git = 0.05
Custom weights must be numeric, non-negative, and sum to 1.0 within 0.0001.
Unavailable Categories
If a category is unavailable (for instance, if the analysis path is not inside a Git repository), PyHealth marks Git: N/A and excludes its weight from the denominator rather than penalizing the project with a zero score.
Git Health Analysis
Analyze Git repository status, .gitignore presence, tracked/untracked file counts, branch/commit metadata, large tracked files (>= 10 MiB), and sensitive tracked filenames:
pyhealth git .
Features & Security Rules
- Read-Only Guarantee: PyHealth never modifies repository state, tracked files, or
.gitignore. It never creates commits, resets branches, or rewrites Git history. - Repository & Worktree Detection: Detects
.gitdirectories and Git worktrees safely. If the path is not inside a Git repository, PyHealth reportsRepository: ✗without crashing. .gitignoreCheck: EmitsPYH401if.gitignoreis missing at the project root.- Large Tracked Files: Flags tracked files whose size is $\ge 10\text{ MiB}$ ($10,485,760\text{ bytes}$) with
PYH402(MEDIUM severity). - Sensitive Tracked Filenames: Screens tracked filenames/paths against sensitive patterns (
.env,.env.*,credentials.json,secrets.json,*.pem,*.key,id_rsa,*.p12,*.pfx) and emitsPYH403(HIGH severity). File contents are never inspected or printed. - Safe Subprocess Execution: Executes
gitcommands safely usingsubprocess.runwith list arguments andshell=False. Parses NUL-delimited (\0) path lists to support spaces, tabs, and Unicode in filenames.
Git Health Limitations
- Filename-Based Screening Only: Sensitive file screening in Git health analysis is based on filename/path pattern matching. Deep content-based secret scanning is handled separately by Stage 4 (Security Analyzer).
- Local Environment Dependent: Git statistics (branch name, commit count, untracked files) rely on the local
gitCLI executable being installed and accessible inPATH.
Documentation Analysis
Analyze project documentation files (README.md, LICENSE, CHANGELOG.md, CONTRIBUTING.md) and Python docstring coverage for public APIs:
pyhealth docs .
Docstring Coverage Formula
Docstring coverage is calculated across all public objects as:
$$\text{Docstring Coverage} = \frac{\text{documented public objects}}{\text{total public objects}} \times 100$$
Where total public objects = public modules + public classes + public functions (including public methods).
Public vs. Private Object Rules
- Public Modules: Python files whose stem does not start with
_(analyzed under standardIGNORED_DIRSrules). - Public Classes: Classes defined at module level or inside public classes whose name does not start with
_. - Public Functions: Top-level functions whose name does not start with
_. Nested local functions inside another function are excluded from public API counts. - Public Methods: Methods defined directly inside a public class whose name does not start with
_(e.g.def run(self):is public;def _helper(self):is private). - Private Objects: Any object or file starting with an underscore
_(including dunder methods like__init__) is excluded from documentation requirements.
Documentation Analysis Limitations
- Static Metric Only: Docstring coverage is a simple static metric that checks for docstring presence; it does not grade the quality, accuracy, or clarity of the written text.
- File Matching: Documentation file presence checks for standard file names (
README.md,LICENSE, etc.) and common case-insensitive variations. Custom documentation layouts or non-standard file names may not be automatically detected. - README Quality: README completeness checks verify basic presence and structural content (description, setup, usage instructions) without performing natural-language understanding.
Dependency Analysis Limitations
Dependency analysis in PyHealth is designed to be safe, conservative, and non-destructive:
- Heuristic Unused Detection: "Unused dependency" findings are heuristic. Packages required indirectly, dynamically via
importlib, through plugins, or in optional features may not appear as direct imports in static AST code analysis. - Import vs. Distribution Mismatches: Top-level import names do not always match PyPI distribution names (e.g.
import PIL->Pillow). Common mismatches are mapped automatically, but custom or rare mappings may not be covered. - Dynamic Imports: Dynamic
__import__()orimportlib.import_module()calls are not evaluated statically. - Development & Optional Dependencies: Development dependencies (e.g.,
pytest,ruff) and optional extras are tracked separately and are not flagged as unused. - Safe
setup.pyParsing:setup.pyfiles are parsed statically using regex patterns. PyHealth never executes arbitrarysetup.pycode.
What PyHealth Will Do
Once fully implemented, a single pyhealth scan . will:
- Analyze code quality — lint errors, style violations, and complexity hotspots.
- Audit security — known vulnerability patterns and insecure coding practices.
- Inspect dependencies — outdated packages, missing pins, and license risks.
- Review documentation — missing docstrings, incomplete README, and coverage gaps.
- Assess Git health — stale branches, large files, and commit hygiene.
- Suggest cleanups — dead code, unused imports, and temporary files.
- Score overall health — a single 0–100 project health score with trend tracking.
- Export reports — Console, JSON, HTML, Markdown, CSV, and SARIF formats.
Installation
From PyPI
pip install pyhealth-scanner
From Source
git clone https://github.com/pyhealth-scanner/pyhealth-scanner.git
cd pyhealth-scanner
pip install .
Usage
# Show version
pyhealth version
# Scan the current directory (full analysis — available in Stage 2+)
pyhealth scan .
# Scan a specific project
pyhealth scan /path/to/your/project
# Show all commands and options
pyhealth --help
Development Setup
Requires Python 3.10 or later.
# Clone the repository
git clone https://github.com/pyhealth-scanner/pyhealth-scanner.git
cd pyhealth-scanner
# Create and activate a virtual environment (recommended)
python -m venv .venv
# On Linux/macOS:
source .venv/bin/activate
# On Windows:
.venv\Scripts\activate
# Install in editable mode with development dependencies
python -m pip install -e ".[dev]"
Running Tests
pytest
To run tests with a coverage report:
pytest --cov=pyhealth --cov-report=term-missing
Building the Package
python -m build
This produces:
dist/
├── pyhealth_scanner-2.0.0.tar.gz
└── pyhealth_scanner-2.0.0-py3-none-any.whl
Contributing
Contributions, bug reports, and feature requests are welcome!
- Fork the repository.
- Create a feature branch (
git checkout -b feature/your-feature). - Make your changes and add tests.
- Ensure all tests pass (
pytest). - Run the linter (
ruff check .). - Open a pull request.
License
This project is licensed under the MIT License.
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 pyhealth_scanner-2.0.0.tar.gz.
File metadata
- Download URL: pyhealth_scanner-2.0.0.tar.gz
- Upload date:
- Size: 77.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3981097ac8ca796ea7f3bc0026717c3e6480ce3fa6cadef55057de2fbf44807d
|
|
| MD5 |
33b3456b4f8a9ef63a0b2c322cd3ffc4
|
|
| BLAKE2b-256 |
9a80a2e7cd398893a813e2b1d5b901d1b1a2ca4a786ce2bdecdca29e5e5e74c4
|
File details
Details for the file pyhealth_scanner-2.0.0-py3-none-any.whl.
File metadata
- Download URL: pyhealth_scanner-2.0.0-py3-none-any.whl
- Upload date:
- Size: 60.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc703b93774d3d408bf0c35f194b2d036c76b7dcbf386237e677162d6c0c5a9d
|
|
| MD5 |
eec420dd7200484fab6c5d9c173b3b9f
|
|
| BLAKE2b-256 |
7fdaae01370390ecb7bf5509878c543bdea9ecb43ebc82bd22075a9c5a89560f
|