AnimaDao
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) viaignore.
- allow a small number of unused deps:
- Multiple source roots: pass them space-separated in
src(e.g.,src: "anima_dao tests"). The Action expands this into repeated--srcflags 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: trueon your ownactions/setup-pythonstep (outside of this Action).
Features
- 🗂 Multiple sources of declared deps:
pyproject.toml— PEP 621[project].dependenciespyproject.toml— Poetry[tool.poetry.dependencies]requirements.txt(incl. nested-rincludes)
- 🔍 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.tomlwith 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
- Clone:
git clone https://github.com/Absolentia/AnimaDao.git
cd AnimaDao
- Install
uv:
pip install --upgrade pip
pip install uv
- Create a virtual env:
uv venv
- 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:
pyproject.toml— PEP 621[project].dependencies(+[project.optional-dependencies]merged)pyproject.toml— Poetry[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
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:beautifulsoup4↔bs4. - Modes:
declared: checks only==pins from declarations; non-pinned specs appear underunpinned.installed: checks versions of packages currently installed in the environment.
- Networking: PyPI queries via
httpxwith timeouts, using a TTL/ETag cache; failures fall back to cached data.
CI & Releases
- CI (
ci.yml): runspytestwithuvon every push/PR tomain(matrix: Python 3.10–3.13). - Tagger (
tag.yml): manual taggingvX.Y.Z. - Publish: recommended trigger by tag
v*or viaworkflow_runafter 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 twineoruv sync --extra dev. -
Hatch: “Unable to determine which files to ship”
Ensure package directory exists and add topyproject.toml:[tool.hatch.build.targets.wheel] packages = ["anima_dao"]
-
Publish doesn’t start after tagger
Events fromGITHUB_TOKENdon’t trigger other workflows. Push tag with a PAT or useworkflow_runtrigger. -
403 after moving repo to org
Update remote:git remote set-url origin git@github.com:<ORG>/AnimaDao.gitand 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
- 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`
- 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]
Metadata
Release files for anima-dao 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| anima_dao-0.2.0.tar.gz | 17.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| anima_dao-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 36.7 kB
Release files / anima_dao-0.2.0.tar.gz
| Download URL | anima_dao-0.2.0.tar.gz |
|---|---|
| Size | 17.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
08a17e5a5ae1aface43c4acd4a35b5057b222f331070e42d202f5d08bc0dd85b
|
|
BLAKE2b-256 checksum How to use checksums |
8706e73cb224750bb8113c9857813f3cc171d4b32d673191634e25acf6b01690
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.3
|
Release files / anima_dao-0.2.0-py3-none-any.whl
| Download URL | anima_dao-0.2.0-py3-none-any.whl |
|---|---|
| Size | 19.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e40015d8039ddad4a27ddbcb5c0f65a9b6ca2ebe473a5eb3539a5f26633fa16a
|
|
BLAKE2b-256 checksum How to use checksums |
e8cfd450cc2dd754b8ebb481b8fc8c78ca8c088bdd46047c4cacd109bf950f49
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.3
|