Skip to main content

Python project dependency analyzer

Project description

pyproj_dep_analyze

CI CodeQL codecov PyPI PyPI - Downloads License: MIT Python 3.10+ Open in Codespaces Code Style: Ruff Maintainability Known Vulnerabilities security: bandit

Parses pyproject.toml to generate actionable dependency data for security audits, update automation, and LLM-powered code review.


Why pyproj_dep_analyze?

AI-assisted "vibe coding" creates apps fast, but dependencies are often unvetted.

When developers build applications rapidly with AI assistance, the focus is on functionality, not supply chain security. Dependencies get added without scrutiny, creating blind spots that attackers exploit:

Attack Vector Description
Typosquatting Malicious packages with names similar to popular ones (reqeusts vs requests)
Dependency Confusion Private package names hijacked on public PyPI
Malicious Updates Legitimate packages compromised via maintainer account takeover
Abandoned Package Takeover Unmaintained packages acquired by bad actors
Protestware / Sabotage Maintainers intentionally breaking their own packages
Hidden Malware Obfuscated code in install scripts or deep dependencies

pyproj_dep_analyze provides visibility into your dependency landscape, generating structured data that feeds into security workflows:

pyproj_dep_analyze  →  pyproj_dep_security  →  pyproj_dep_update
     (analyze)            (scan & audit)         (remediate)
  • pyproj_dep_analyze - Extracts and enriches dependency metadata from pyproject.toml
  • pyproj_dep_security - Scans installed environments for vulnerabilities and supply chain risks
  • pyproj_dep_update - Applies fixes by updating pyproject.toml based on security findings

Know your dependencies before they become your vulnerabilities.


Table of Contents


Overview

pyproj_dep_analyze analyzes Python project dependencies declared in pyproject.toml files:

  • Parses dependencies from PEP 621, Poetry, PDM, and Hatch formats
  • Checks for newer versions on PyPI and GitHub
  • Enriches with metadata: license, stars, release dates, download stats
  • Outputs structured JSON with human/LLM-readable recommendations

Scope & Boundaries

What pyproj_dep_analyze Does

Capability Description
Parse pyproject.toml Extract dependencies from PEP 621, Poetry, PDM, Hatch formats
Check for updates Query PyPI/GitHub for latest compatible versions
Enrich with metadata License, stars, forks, release dates, maintainers
Version metrics Release frequency, project age, abandonment indicators
Download statistics Popularity metrics from pypistats.org
Index detection Identify which package index serves each dependency
Direct dependencies Extract immediate dependencies from requires_dist

What Belongs in pyproj_dep_security (Separate Project)

Capability Reason
Full transitive dependency tree Requires installed environment (pipdeptree)
Vulnerability scanning Security-specific (OSV, Safety DB, Snyk integration)
License compliance checking Policy enforcement, not metadata
Dependency confusion detection Active security scanning
Supply chain risk scoring Requires vulnerability data + heuristics
Typosquatting detection Requires name similarity analysis

What Belongs in pyproj_dep_update (Separate Project)

Capability Reason
Update pyproject.toml Modifies project files (write operation)
Pin indirect dependencies Add transitive deps with CVEs to explicit deps
CVE-driven version bumps Requires vulnerability scan results (Bandit/OSV)
Generate constraints.txt Create pip constraints for indirect deps
Batch update operations Update all / security-only / major/minor/patch
Lock file regeneration Update poetry.lock, pdm.lock, uv.lock after changes
Update local libraries Bump versions of local/workspace dependencies

Design Principle:

  • pyproj_dep_analyze analyzes declared dependencies from project files
  • pyproj_dep_security analyzes installed environments (in a venv) for security issues
  • pyproj_dep_update modifies pyproject.toml based on analysis and security scan results

Installation

Via UV (Recommended)

uv pip install pyproj_dep_analyze

Via pip

pip install pyproj_dep_analyze

Requirements: Python 3.10+

Both pyproj_dep_analyze and pyproj-dep-analyze commands are available after installation.


Quick Start

# Basic analysis
pyproj-dep-analyze analyze

# Enriched analysis with full metadata
pyproj-dep-analyze analyze-enriched

# View configuration
pyproj-dep-analyze config

# Show package info
pyproj-dep-analyze info

CLI Reference

Global Options

Option Description Default
--traceback / --no-traceback Show full Python traceback on errors --no-traceback
-h, --help Show help message -
--version Show version and exit -

analyze - Analyze Dependencies

Analyze pyproject.toml and determine outdated dependencies for each Python version.

pyproj-dep-analyze analyze [PYPROJECT_PATH] [OPTIONS]

Arguments

Argument Description Default
PYPROJECT_PATH Path to pyproject.toml file pyproject.toml

Options

Option Description Env Variable Default
-o, --output Output file path - outdated.json
--github-token GitHub API token GITHUB_TOKEN, PYPROJ_DEP_ANALYZE_GITHUB_TOKEN None
--timeout Request timeout (seconds) PYPROJ_DEP_ANALYZE_TIMEOUT 30.0
--concurrency Max concurrent API requests PYPROJ_DEP_ANALYZE_CONCURRENCY 10
--format Output format - table

Format Options:

Format Description
table Summary statistics + lists of updates and manual checks
summary Only summary statistics
json Full analysis as JSON to stdout

Examples

# Analyze current directory
pyproj-dep-analyze analyze

# Analyze specific file
pyproj-dep-analyze analyze path/to/pyproject.toml

# Custom output file
pyproj-dep-analyze analyze -o results.json

# With GitHub token (for better rate limits)
pyproj-dep-analyze analyze --github-token ghp_xxxxx
GITHUB_TOKEN=ghp_xxxxx pyproj-dep-analyze analyze

# Output formats
pyproj-dep-analyze analyze --format summary
pyproj-dep-analyze analyze --format json

# Custom timeout and concurrency
pyproj-dep-analyze analyze --timeout 60 --concurrency 5

analyze-enriched - Enriched Analysis

Analyze with full metadata enrichment including PyPI info, repository data, and dependency graphs.

pyproj-dep-analyze analyze-enriched [PYPROJECT_PATH] [OPTIONS]

Arguments

Argument Description Default
PYPROJECT_PATH Path to pyproject.toml file pyproject.toml

Options

Option Description Env Variable Default
-o, --output Output file path - deps_enriched.json
--github-token GitHub API token GITHUB_TOKEN, PYPROJ_DEP_ANALYZE_GITHUB_TOKEN None
--timeout Request timeout (seconds) PYPROJ_DEP_ANALYZE_TIMEOUT 30.0
--concurrency Max concurrent API requests PYPROJ_DEP_ANALYZE_CONCURRENCY 10

Examples

# Enriched analysis
pyproj-dep-analyze analyze-enriched

# Custom output file
pyproj-dep-analyze analyze-enriched -o analysis.json

# With GitHub token for repository metadata
GITHUB_TOKEN=ghp_xxx pyproj-dep-analyze analyze-enriched

config - View Configuration

Display the current merged configuration from all sources.

pyproj-dep-analyze config [OPTIONS]

Options

Option Description Values Default
--format Output format human, json human
--section Show specific section only e.g., analyzer None

Examples

pyproj-dep-analyze config
pyproj-dep-analyze config --format json
pyproj-dep-analyze config --section analyzer

config-deploy - Deploy Configuration

Deploy default configuration files to system or user directories.

pyproj-dep-analyze config-deploy --target TARGET [OPTIONS]

Options

Option Description Values Default
--target Target layer(s) - can be repeated app, host, user Required
--force Overwrite existing files Flag False

Target Locations

Target Linux macOS / Windows
user ~/.config/pyproj-dep-analyze/config.toml Platform-specific user config
app /etc/xdg/pyproj-dep-analyze/config.toml Platform-specific system config
host /etc/pyproj-dep-analyze/hosts/{hostname}.toml Same as app

Examples

pyproj-dep-analyze config-deploy --target user
pyproj-dep-analyze config-deploy --target user --force
sudo pyproj-dep-analyze config-deploy --target app

info - Package Information

Display package metadata including version and installation details.

pyproj-dep-analyze info

hello / fail - Test Commands

Commands for testing CLI success and failure paths.

pyproj-dep-analyze hello                    # Success path
pyproj-dep-analyze fail                     # Failure path
pyproj-dep-analyze --traceback fail         # With full traceback

Python API

Main Functions

analyze_pyproject()

Analyze a pyproject.toml file and return outdated entries.

from pyproj_dep_analyze import analyze_pyproject, OutdatedEntry, Action

entries: list[OutdatedEntry] = analyze_pyproject(
    "pyproject.toml",           # Path to pyproject.toml (required)
    github_token=None,          # GitHub API token (default: None)
    timeout=30.0,               # Request timeout in seconds (default: 30.0)
    concurrency=10,             # Max concurrent requests (default: 10)
)

# Filter results
updates = [e for e in entries if e.action == Action.UPDATE]
for entry in updates:
    print(f"{entry.package}: {entry.current_version} -> {entry.latest_version}")

run_enriched_analysis()

Analyze with full metadata enrichment.

from pyproj_dep_analyze import run_enriched_analysis, write_enriched_json

result = run_enriched_analysis(
    "pyproject.toml",           # Path to pyproject.toml (required)
    github_token=None,          # GitHub API token (default: None)
    timeout=30.0,               # Request timeout in seconds (default: 30.0)
    concurrency=10,             # Max concurrent requests (default: 10)
)

# Access results
print(f"Total: {result.summary.total_packages}")
print(f"Updates: {result.summary.updates_available}")

for pkg in result.packages:
    print(f"{pkg.name}: {pkg.action.value}")
    if pkg.pypi_metadata:
        print(f"  License: {pkg.pypi_metadata.license}")
    if pkg.repo_metadata:
        print(f"  Stars: {pkg.repo_metadata.stars}")

# Save to file
write_enriched_json(result, "analysis.json")

write_outdated_json() / write_enriched_json()

Write analysis results to JSON files.

from pyproj_dep_analyze import (
    analyze_pyproject,
    run_enriched_analysis,
    write_outdated_json,
    write_enriched_json,
)

# Basic analysis
entries = analyze_pyproject("pyproject.toml")
write_outdated_json(entries, "outdated.json")

# Enriched analysis
result = run_enriched_analysis("pyproject.toml")
write_enriched_json(result, "deps_enriched.json")

Analyzer Class

For more control, use the Analyzer class directly.

from pyproj_dep_analyze import Analyzer
from pathlib import Path

analyzer = Analyzer(
    github_token="ghp_xxxxx",   # GitHub API token (default: None)
    timeout=60.0,               # Request timeout in seconds (default: 30.0)
    concurrency=20,             # Max concurrent requests (default: 10)
)

# Basic analysis
result = analyzer.analyze(Path("pyproject.toml"))
for entry in result.entries:
    print(f"{entry.package}: {entry.action.value}")

# Enriched analysis
enriched = analyzer.analyze_enriched(Path("pyproject.toml"))

Index Resolution

Detect and resolve package indexes.

from pyproj_dep_analyze import (
    IndexResolver,
    detect_configured_indexes,
    identify_index,
)

# Detect all configured indexes
indexes = detect_configured_indexes()
for idx in indexes:
    print(f"{idx.url} ({idx.index_type.value}, private={idx.is_private})")

# Identify index type from URL
info = identify_index("https://pypi.org/simple")
print(info.index_type)  # IndexType.PYPI

# Resolve which index serves a package (async)
resolver = IndexResolver(indexes=indexes, timeout=30.0)
index_info = await resolver.resolve("requests")

Repository Resolution

Resolve repository metadata from URLs.

from pyproj_dep_analyze import (
    RepoResolver,
    detect_repo_url,
    parse_repo_url,
    PyPIUrlMetadata,
)

# Parse repository URL
parsed = parse_repo_url("https://github.com/psf/requests")
print(f"{parsed.owner}/{parsed.name}")  # psf/requests

# Detect repo URL from PyPI metadata
urls = PyPIUrlMetadata(project_urls={"Source": "https://github.com/psf/requests"})
repo_url = detect_repo_url(urls)

# Fetch repository metadata (async)
resolver = RepoResolver(github_token="ghp_xxx", timeout=30.0)
metadata = await resolver.resolve("psf", "requests")
print(f"Stars: {metadata.stars}")

Download Statistics

Fetch download statistics from pypistats.org.

from pyproj_dep_analyze import StatsResolver

resolver = StatsResolver(timeout=15.0)

# Fetch stats for a single package (async)
stats = await resolver.fetch_stats_async("requests")
if stats:
    print(f"Last month: {stats.last_month_downloads}")
    print(f"Last week: {stats.last_week_downloads}")

# Fetch stats for multiple packages (async)
results = await resolver.fetch_many_async(
    ["requests", "httpx", "pydantic"],
    concurrency=5,
)

Data Models

Enums

Action

from pyproj_dep_analyze import Action

Action.UPDATE          # "update" - newer version exists
Action.DELETE          # "delete" - remove for this Python version
Action.NONE            # "none" - up to date
Action.CHECK_MANUALLY  # "check manually" - needs manual verification

Analysis Results

OutdatedEntry

Basic analysis entry for a single dependency.

Field Type Description
package str Package name
python_version str Python version (e.g., "3.11")
current_version str | None Currently specified version
latest_version str | None Latest available version
action Action Recommended action
note str Human/LLM-readable explanation

AnalysisResult

Complete result from basic analysis.

Field Type Description
entries list[OutdatedEntry] All analysis entries
python_versions list[str] Python versions analyzed
total_dependencies int Total unique dependencies
update_count int Dependencies needing updates
delete_count int Dependencies to delete
check_manually_count int Needs manual check

EnrichedAnalysisResult

Complete result from enriched analysis.

Field Type Description
analyzed_at str ISO timestamp
pyproject_path str Analyzed file path
python_versions list[str] Python versions
indexes_configured list[IndexInfo] Package indexes
packages list[EnrichedEntry] Enriched entries
dependency_graph dict[str, list[str]] Dependencies
summary EnrichedSummary Statistics

EnrichedEntry

Enriched package entry with full metadata.

Field Type Description
name str Package name
requested_version str | None Version constraint
resolved_version str | None Resolved version
latest_version str | None Latest version
action Action Recommended action
note str Human/LLM-readable explanation
source str Where declared
index_info IndexInfo | None Package index
python_compatibility dict[str, CompatibilityStatus] Per-version compatibility
pypi_metadata PyPIMetadata | None PyPI data
repo_metadata RepoMetadata | None Repository data
direct_dependencies list[str] Runtime dependencies only
optional_dependencies dict[str, list[str]] Optional deps grouped by extra (dev, test, docs)
required_by list[str] Reverse dependencies

Metadata Models

PyPIMetadata

Field Type Description
summary str | None One-line description
license str | None SPDX license
home_page str | None Project URL
project_urls dict[str, str] Labeled URLs
author str | None Author name
author_email str | None Author email
maintainer str | None Maintainer name
maintainer_email str | None Maintainer email
available_versions list[str] All versions
first_release_date str | None First release ISO date
latest_release_date str | None Latest release ISO date
requires_python str | None Python constraint
requires_dist list[str] Dependency specs
version_metrics VersionMetrics | None Release pattern metrics
download_stats DownloadStats | None Download statistics

VersionMetrics

Computed metrics from version history for quality assessment.

Field Type Description
release_count int Total number of releases
latest_release_age_days int | None Days since latest release
first_release_age_days int | None Project age in days
avg_days_between_releases float | None Average release frequency
min_days_between_releases int | None Shortest gap (detect rapid releases)
max_days_between_releases int | None Longest gap (detect abandonment)
releases_last_year int Recent activity indicator
release_dates list[str] All release timestamps

DownloadStats

Download statistics from pypistats.org.

Field Type Description
total_downloads int | None Lifetime downloads
last_month_downloads int | None Last 30 days
last_week_downloads int | None Last 7 days
last_day_downloads int | None Last 24 hours
fetched_at str | None When stats were retrieved

RepoMetadata

Field Type Description
repo_type RepoType github, gitlab, etc.
url str | None Repository URL
owner str | None Owner/organization
name str | None Repository name
stars int | None Star count
forks int | None Fork count
open_issues int | None Open issue count
default_branch str | None Default branch
last_commit_date str | None Last commit ISO date
created_at str | None Creation ISO date
description str | None Repository description

IndexInfo

Field Type Description
url str Index URL
index_type IndexType pypi, testpypi, artifactory, etc.
is_private bool Whether private/internal

Utility Models

DependencyInfo

Parsed dependency information.

Field Type Description
name str Normalized package name
raw_spec str Original specification
version_constraints str Version constraints
python_markers str | None Python version markers
extras list[str] Requested extras
source str Source location
is_git_dependency bool Is git dependency
git_url str | None Git URL
git_ref str | None Git ref (tag/branch/commit)

PythonVersion

from pyproj_dep_analyze import PythonVersion

pv = PythonVersion.from_string("3.11")
pv.major  # 3
pv.minor  # 11
str(pv)   # "3.11"

# Comparisons
pv < PythonVersion(3, 12)   # True
pv >= PythonVersion(3, 10)  # True

Configuration

Configuration Precedence (lowest to highest)

  1. Default config (bundled)
  2. Application config (/etc/xdg/pyproj-dep-analyze/config.toml)
  3. Host config (/etc/pyproj-dep-analyze/hosts/{hostname}.toml)
  4. User config (~/.config/pyproj-dep-analyze/config.toml)
  5. .env files
  6. Environment variables (PYPROJ_DEP_ANALYZE_*)
  7. CLI options

Analyzer Settings

Setting Type Default Environment Variable
github_token string "" PYPROJ_DEP_ANALYZE_GITHUB_TOKEN
timeout float 30.0 PYPROJ_DEP_ANALYZE_TIMEOUT
concurrency integer 10 PYPROJ_DEP_ANALYZE_CONCURRENCY

GitHub Token

Mode Rate Limit Notes
Unauthenticated 60 requests/hour Easily exhausted
Authenticated 5,000 requests/hour Recommended for regular use

Sample Config File

# ~/.config/pyproj-dep-analyze/config.toml

[analyzer]
timeout = 30.0
concurrency = 10
# github_token = ""  # Use env var instead

Sample .env File

PYPROJ_DEP_ANALYZE_GITHUB_TOKEN=ghp_xxxxx
PYPROJ_DEP_ANALYZE_TIMEOUT=60.0
PYPROJ_DEP_ANALYZE_CONCURRENCY=20
LOG_CONSOLE_LEVEL=DEBUG

Output Examples

outdated.json

[
  {
    "package": "requests",
    "python_version": "3.11",
    "current_version": "2.28.0",
    "latest_version": "2.32.0",
    "action": "update",
    "note": "Package 'requests' can be updated from 2.28.0 to 2.32.0."
  },
  {
    "package": "tomli",
    "python_version": "3.11",
    "current_version": "2.0.0",
    "latest_version": null,
    "action": "delete",
    "note": "Package 'tomli' has a Python version marker that excludes Python 3.11."
  }
]

deps_enriched.json

{
  "analyzed_at": "2025-12-04T10:30:00Z",
  "pyproject_path": "pyproject.toml",
  "python_versions": ["3.11", "3.12", "3.13"],
  "indexes_configured": [
    {"url": "https://pypi.org/simple", "index_type": "pypi", "is_private": false}
  ],
  "summary": {
    "total_packages": 25,
    "updates_available": 5,
    "up_to_date": 18,
    "check_manually": 2,
    "from_pypi": 23,
    "from_private_index": 2
  },
  "packages": [
    {
      "name": "requests",
      "requested_version": ">=2.28.0",
      "latest_version": "2.32.0",
      "action": "update",
      "pypi_metadata": {
        "license": "Apache-2.0",
        "latest_release_date": "2024-05-29T...",
        "version_metrics": {
          "release_count": 150,
          "latest_release_age_days": 180,
          "releases_last_year": 5
        }
      },
      "repo_metadata": {
        "stars": 52345,
        "forks": 9234
      }
    }
  ]
}

Further Documentation

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

pyproj_dep_analyze-4.0.1.tar.gz (4.6 MB view details)

Uploaded Source

Built Distribution

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

pyproj_dep_analyze-4.0.1-py3-none-any.whl (82.8 kB view details)

Uploaded Python 3

File details

Details for the file pyproj_dep_analyze-4.0.1.tar.gz.

File metadata

  • Download URL: pyproj_dep_analyze-4.0.1.tar.gz
  • Upload date:
  • Size: 4.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyproj_dep_analyze-4.0.1.tar.gz
Algorithm Hash digest
SHA256 86126a526f642c11dc9c313dd39c91d67c888e4a3855318980153a815cf3765d
MD5 320a2ffd50562527179a3084977d9510
BLAKE2b-256 b4c9c6307746f92523925a6a89e1beef95f11dd19c1430493761167209ff5dc2

See more details on using hashes here.

File details

Details for the file pyproj_dep_analyze-4.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pyproj_dep_analyze-4.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7a049db84883d9a5aed310f9476fe366aa6c46c54f6daad9d4e48f31e6a972e1
MD5 fcdd54d26c6a451f41b515b28d8d595f
BLAKE2b-256 04cee8cba279b9e7e8e7f405989f1619ce9b0d362f375d3aa2841426abf5b363

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