Comprehensive health assessments for Python project dependencies.
- Health Scoring: Weighted composite scores based on security, maintenance, community, and popularity
- Vulnerability Detection: Real-time scanning via OSV database with open vs fixed classification
- Maintenance Analysis: Identifies abandoned, deprecated, or archived packages
- License Evaluation: Categorizes licenses (permissive, copyleft, weak copyleft)
- Caching: SQLite-based caching reduces API calls and improves performance
- CI/CD Ready: Exit codes for pipeline integration
pip install dependency-health-monitorOr install from source:
git clone https://github.com/jeremylaratro/dhm.git
cd dhm
pip install -e ".[dev]"# Scan current project
dhm scan
# Check a single package
dhm check requests
# Find alternatives for a problematic package
dhm alternatives urllib3
# Output as JSON for CI/CD
dhm scan -f json -o report.json
# Fail CI if high+ severity issues found
dhm scan --fail-on highimport asyncio
from dhm import check, scan
async def main():
# Check a single package
report = await check("requests")
print(f"{report.package.name}: Grade {report.health.grade}")
print(f" Security: {report.health.security_score:.0f}")
print(f" Open vulnerabilities: {len(report.health.open_vulnerabilities)}")
# Scan a project directory
reports = await scan(".")
for r in reports:
if r.health.has_open_vulnerabilities:
print(f"⚠️ {r.package.name} has {len(r.health.open_vulnerabilities)} open vulns")
asyncio.run(main())Synchronous API (for non-async contexts):
from dhm import check_sync, scan_sync
report = check_sync("flask")
print(f"Flask health: {report.health.grade} ({report.health.overall:.0f}/100)")
reports = scan_sync("/path/to/project")
unhealthy = [r for r in reports if r.health.is_concerning]DHM calculates a composite health score using weighted components:
| Component | Weight | Data Sources |
|---|---|---|
| Security | 35% | OSV vulnerability database |
| Maintenance | 30% | PyPI release dates, GitHub activity |
| Community | 20% | Contributors, stars, PR merge rates |
| Popularity | 15% | pypistats.org download counts |
Grade Thresholds:
| Grade | Score | Meaning |
|---|---|---|
| A | ≥ 85 | Excellent - Well maintained, secure, popular |
| B | ≥ 75 | Good - Minor concerns, generally safe |
| C | ≥ 65 | Acceptable - Some issues, monitor closely |
| D | ≥ 55 | Concerning - Significant issues, consider alternatives |
| F | < 55 | Critical - Major problems, action required |
DHM distinguishes between open and fixed vulnerabilities:
- Open: Affects your installed version - action required
- Fixed: Was present in older versions but patched in yours - historical only
report = await check("aiohttp", version="3.13.3")
# Only shows vulnerabilities affecting version 3.13.3
for vuln in report.health.open_vulnerabilities:
print(f"🔴 {vuln.id}: {vuln.title}")
if vuln.fixed_version:
print(f" Fix: Upgrade to {vuln.fixed_version}")DHM caches API responses to improve performance and reduce rate limiting:
| Data Type | TTL | Rationale |
|---|---|---|
| GitHub repo data | 24 hours | Metrics change slowly |
| PyPI metadata | 1 hour | Releases are occasional |
| Download stats | 6 hours | Updated daily |
| Vulnerabilities | 6 hours | Security-critical, stay current |
# View cache statistics
dhm cache --stats
# Clear all cached data
dhm cache --clear
# Remove only expired entries
dhm cache --cleanup
# Invalidate specific data
dhm cache --invalidate 'github:%'Add to your pyproject.toml:
[tool.dhm]
include_transitive = true
cache_ttl = 3600
[tool.dhm.thresholds]
min_grade = "C"
max_vulnerabilities = 0
max_abandoned = 0# GitHub Actions example
- name: Check dependency health
run: |
pip install dependency-health-monitor
dhm scan --fail-on high -f json -o dhm-report.json
- name: Upload report
uses: actions/upload-artifact@v3
with:
name: dependency-health-report
path: dhm-report.json| Variable | Description |
|---|---|
GITHUB_TOKEN |
GitHub API token for higher rate limits (5000/hr vs 60/hr) |
MIT - See LICENSE for details.