Skip to main content

Confucian-spirited dependency health checker for Python projects using pyproject + uv

Project description

AnimaDao

ci tagger PyPI version Python License: MIT

AnimaDao is a pragmatic dependency health checker for Python projects.
It compares declared dependencies with actual imports, flags unused ones, and checks pinned specs (==) against the latest PyPI releases.
Works with uv and supports three declaration styles.


One-liner GitHub Action

Use the official composite Action to run AnimaDao in one step.
It writes a Markdown report to the Job Summary, optionally uploads artifacts, and can fail the job on policy violations.

Repo: https://github.com/Absolentia/animadao-action
Recommended pin: uses: Absolentia/animadao-action@v1 (moving major tag).
For full reproducibility you can pin a concrete version, e.g. @v1.0.3.

Minimal usage (declared mode)

- name: AnimaDao (declared)
  uses: Absolentia/animadao-action@v1
  with:
    mode: declared
    # One root is enough for most repos; you can also pass multiple roots (e.g. "anima_dao tests")
    src: "."
    ignore: pip,setuptools,wheel,ruff
    fail-if-outdated: "true"
    max-unused: "0"
    format: md
    artifact-name: anima-report-${{ matrix.python-version }}
    python-version: ${{ matrix.python-version }}

Installed mode (checks currently installed packages; no “unused” check):

- name: AnimaDao (installed)
  uses: Absolentia/animadao-action@v1
  with:
    mode: installed
    fail-if-outdated: "true"
    ignore: pip,setuptools,wheel
    python-version: ${{ matrix.python-version }}

Full example job (with cache + matrix)

jobs:
  anima:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        python-version: [ "3.10","3.11","3.12","3.13" ]
    steps:
      - uses: actions/checkout@v4

      # Speed up uv by caching
      - uses: actions/cache@v4
        with:
          path: ~/.cache/uv
          key: uv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}

      - name: AnimaDao (declared)
        uses: Absolentia/animadao-action@v1
        with:
          mode: declared
          src: "."                                  # or: "anima_dao tests"
          ignore: pip,setuptools,wheel,ruff
          fail-if-outdated: "true"
          max-unused: "0"
          format: md
          artifact-name: anima-report-${{ matrix.python-version }}
          python-version: ${{ matrix.python-version }}

Notes & tips

  • Artifacts in matrix: artifact names must be unique per shard (use anima-report-${{ matrix.python-version }}), or merge them later to avoid 409 conflicts.
  • Report visibility: the Action appends the Markdown report to the Job Summary; HTML/JSON are attached as artifacts when upload-artifact: "true".
  • Policies: tune to your process:
    • allow a small number of unused deps: max-unused: "1"
    • ignore dev tools (e.g., ruff, black, mypy, build, twine) via ignore.
  • Multiple source roots: pass them space-separated in src (e.g., src: "anima_dao tests"). The Action expands this into repeated --src flags for the report.
    The gate runs against the project root and policy checks (works out of the box).
  • Pre-release Python: if you run on RC versions (e.g., 3.14-rc), set allow-prereleases: true on your own actions/setup-python step (outside of this Action).

Features

  • 🗂 Multiple sources of declared deps:
    1. pyproject.tomlPEP 621 [project].dependencies
    2. pyproject.tomlPoetry [tool.poetry.dependencies]
    3. requirements.txt (incl. nested -r includes)
  • 🔍 Import scan: walks your source tree and extracts top-level imports (AST).
  • 🧹 Unused deps: declared but not imported (heuristic, import-name ≈ normalized dist name).
  • Outdated pins: checks only ==-pinned requirements against PyPI latest.
  • ⚙️ Two modes: --mode declared (default) and --mode installed.
  • 🚫 Ignore lists: skip tool packages (e.g. pip, setuptools, wheel) or any custom names.
  • 🧩 Config file: project-level .animadao.toml with sane defaults and CLI overrides.
  • 🗃️ PyPI cache: TTL + ETag with configurable concurrency for faster checks.
  • 📄 Reports: --format json | md | html.

Requirements

  • Python 3.10+
  • uv (modern Python package/dependency manager)

Installation

With uv

pip install uv
uv pip install anima-dao

With pip

pip install anima-dao

From sources

  1. Clone:
git clone https://github.com/Absolentia/AnimaDao.git
cd AnimaDao
  1. Install uv:
pip install --upgrade pip
pip install uv
  1. Create a virtual env:
uv venv
  1. Install project deps:
uv sync

Configuration

Create .animadao.toml in your project root (optional):

[core]
mode = "declared"          # declared | installed
src = ["src", "app"]       # optional, source roots for import scan

# PyPI cache / concurrency
pypi_ttl_seconds = 86400   # default: 24h
pypi_concurrency = 8       # default: 8 parallel requests

[ignore]
distributions = ["pip", "setuptools", "wheel"]
imports = []

CLI flags always override config values.


Usage (CLI)

All commands accept a project root (where either pyproject.toml or requirements.txt resides) and an optional source root to scan imports.

Scan: declared vs imports

uv run animadao scan --project . --src src

Check against PyPI

Declared dependencies (default mode):

uv run animadao check --project . --mode declared --ignore pip --ignore setuptools

Installed packages in the current venv:

uv run animadao check --project . --mode installed --pypi-ttl 43200 --pypi-concurrency 16

Find unused deps (declared but not imported)

uv run animadao unused --project . --src src --ignore pip --ignore wheel

Generate report

JSON:

uv run animadao report --project . --src src --out report.json --format json

Markdown:

uv run animadao report --project . --src src --out report.md --format md

HTML:

uv run animadao report --project . --src src --out report.html --format html

Example report.json:

{
  "summary": {
    "declared": 12,
    "imports_found": 34,
    "outdated": 2,
    "unpinned": 7,
    "unused": 3
  },
  "outdated": [
    {
      "name": "requests",
      "current": "2.31.0",
      "latest": "2.32.3"
    }
  ],
  "unpinned": [
    {
      "name": "numpy",
      "spec": ">=1.26"
    }
  ],
  "unused": [
    "rich",
    "typer"
  ],
  "imports": [
    "requests",
    "json",
    "..."
  ],
  "mode": "declared"
}

Supported dependency sources & priority

When resolving declared dependencies, AnimaDao uses the first matching source:

  1. pyproject.tomlPEP 621 [project].dependencies (+ [project.optional-dependencies] merged)
  2. pyproject.tomlPoetry [tool.poetry.dependencies]
    • python = "^3.10" is ignored
    • Exact versions become name==X.Y.Z
    • Caret ^ ranges are converted to PEP 440 intervals (best-effort)
    • Poetry dev/group deps are not included
  3. requirements.txt — plain lines + nested includes via -r / --requirement

Only the first detected source is used to avoid mixing ecosystems.


How it works (quick notes)

  • Import mapping: compares normalized distribution names (-_) with top-level imports. Known alias: beautifulsoup4bs4.
  • Modes:
    • declared: checks only == pins from declarations; non-pinned specs appear under unpinned.
    • installed: checks versions of packages currently installed in the environment.
  • Networking: PyPI queries via httpx with timeouts, using a TTL/ETag cache; failures fall back to cached data.

CI & Releases

  • CI (ci.yml): runs pytest with uv on every push/PR to main (matrix: Python 3.10–3.13).
  • Tagger (tag.yml): manual tagging vX.Y.Z.
  • Publish: recommended trigger by tag v* or via workflow_run after tagger.

Create a release:

# bump version in pyproject.toml
git commit -am "chore: bump version to 0.1.1"
git tag -a v0.1.1 -m "v0.1.1"
git push origin v0.1.1

Support matrix

  • Python: 3.10 / 3.11 / 3.12 / 3.13
  • OS: Linux, macOS, Windows
  • Packaging: PEP 621 (project), Poetry, requirements.txt
  • Manager: uv (install & run)

Troubleshooting

  • No module named build
    uv pip install build twine or uv sync --extra dev.

  • Hatch: “Unable to determine which files to ship”
    Ensure package directory exists and add to pyproject.toml:

    [tool.hatch.build.targets.wheel]
    packages = ["anima_dao"]
    
  • Publish doesn’t start after tagger
    Events from GITHUB_TOKEN don’t trigger other workflows. Push tag with a PAT or use workflow_run trigger.

  • 403 after moving repo to org
    Update remote: git remote set-url origin git@github.com:<ORG>/AnimaDao.git and check org permissions/SSO.


Contributing

pip install uv
uv sync --extra dev
uv run pytest -vvvv

Please keep type hints (3.10+), docstrings and comments in English, and add tests for new loaders/edge cases.

pre-commit

  1. Add AnimaDao hooks to .pre-commit-config.yaml:
repos:
  - repo: https://github.com/Absolentia/AnimaDao
    rev: v0.1.2        # <-- use the latest tag
    hooks:
      - id: animadao-check
        args: [ --ignore, pip, --ignore, setuptools ]
        files: '^(pyproject.toml|requirements.*txt|.*\.py)$'
      - id: animadao-report
        stages: [ manual ]  # optional: run on-demand via `pre-commit run -a animadao-report`
  1. Install and run:
pip install pre-commit
pre-commit install
pre-commit run -a

Policy examples:

  • Fail on outdated pins only:
    - id: animadao-check
      args: [--mode, declared, --fail-if-outdated]
    
  • Strict mode (declared): no outdated, no unpinned, no unused:
    - id: animadao-check
      args: [--mode, declared, --fail-if-outdated, --fail-if-unpinned, --max-unused, "0"]
    
  • Installed mode (CI on lockstep env):
    - id: animadao-check-installed
      args: [--fail-if-outdated]
    

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

anima_dao-0.2.0.tar.gz (17.0 kB view details)

Uploaded Source

Built Distribution

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

anima_dao-0.2.0-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: anima_dao-0.2.0.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for anima_dao-0.2.0.tar.gz
Algorithm Hash digest
SHA256 08a17e5a5ae1aface43c4acd4a35b5057b222f331070e42d202f5d08bc0dd85b
MD5 7a8c0f2f228fa472d6044737df0bfbd6
BLAKE2b-256 8706e73cb224750bb8113c9857813f3cc171d4b32d673191634e25acf6b01690

See more details on using hashes here.

File details

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

File metadata

  • Download URL: anima_dao-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 19.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for anima_dao-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e40015d8039ddad4a27ddbcb5c0f65a9b6ca2ebe473a5eb3539a5f26633fa16a
MD5 fb2a87643af4941555b0454dc41ba763
BLAKE2b-256 e8cfd450cc2dd754b8ebb481b8fc8c78ca8c088bdd46047c4cacd109bf950f49

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