Dependency graph and boundary enforcement for Python Polylith workspaces.
Project description
polydep
Dependency graph and boundary enforcement for Python Polylith workspaces.
polydep analyzes inter-brick imports in a Python Polylith monorepo and outputs a Mermaid dependency graph. It complements the poly CLI by adding graph visualization, dependency chain explanation, and CI-friendly boundary checks.
Read-only — never modifies workspace files.
Install
pip install polydep
# or
uv tool install polydep
Requires Python 3.11+.
Quick start
# Generate a dependency graph as Mermaid
polydep graph
# Specify a workspace root
polydep graph --root /path/to/workspace
# Save to polydep.expected.mermaid
polydep graph --save
Example output:
graph LR
subgraph bases
consumer
greet_api
end
subgraph components
database
greeting
kafka
log
end
consumer --> kafka
consumer --> log
greet_api --> greeting
greet_api --> log
kafka --> log
Commands
polydep graph
Print the dependency graph as a Mermaid diagram to stdout.
polydep graph [--root <path>] [--save]
| Flag | Default | Description |
|---|---|---|
--root <path> |
. |
Workspace root directory |
--save |
Write to polydep.expected.mermaid instead of printing |
polydep why
Explain why brick A depends on brick B — shows all dependency paths with exact file and line provenance.
polydep why <source_brick> <target_brick> [--root <path>]
Example output:
consumer depends on log via 2 paths:
Path 1 (direct):
consumer -> log
bases/example/consumer/core.py:3 from example import kafka, log
Path 2 (transitive, length 2):
consumer -> kafka -> log
bases/example/consumer/core.py:3 from example import kafka, log
components/example/kafka/consumer.py:5 from example import log
components/example/kafka/producer.py:3 from example import log
polydep check
Compare actual dependencies against an expected graph file. Designed for CI — exits non-zero on mismatch.
polydep check [--expected <path>] [--root <path>]
| Flag | Default | Description |
|---|---|---|
--expected <path> |
polydep.expected.mermaid |
Path to expected graph file |
--root <path> |
. |
Workspace root directory |
The expected graph file is a Mermaid file, typically generated by polydep graph --save. Strict comparison — unexpected edges (boundary violations) and missing edges (stale graph) cause failure. Unexpected edges include file and line provenance.
| Exit code | Meaning |
|---|---|
| 0 | Actual graph matches expected graph |
| 1 | Mismatch detected |
| 2 | Error (file not found, parse error, etc.) |
CI integration
Bootstrap an expected graph
polydep graph --save
git add polydep.expected.mermaid && git commit -m "Add expected dependency graph"
GitHub Actions
- uses: astral-sh/setup-uv@v5
- run: uv tool install polydep
- run: polydep check
Pre-commit hook
# .pre-commit-config.yaml
- repo: local
hooks:
- id: polydep-check
name: polydep boundary check
entry: uv run polydep check
language: system
pass_filenames: false
How it works
- Workspace discovery — finds
workspace.toml(orpyproject.tomlwith[tool.polylith]) and reads the namespace - Brick enumeration — scans
components/<namespace>/*/andbases/<namespace>/*/ - Import extraction — parses every
.pyfile with Python'sastmodule, collecting all absolute imports (relative imports are skipped as they're internal to a brick) - Graph construction — filters imports to those targeting known bricks (matching
<namespace>.<brick_name>), excludes self-imports, and builds a deduplicated edge set - Output — renders the graph as a Mermaid diagram with subgraph grouping by brick type
Comparison with poly CLI
| Feature | poly CLI |
polydep |
|---|---|---|
| Dependency table | poly deps |
-- |
| Dependency graph (Mermaid) | -- | polydep graph |
| Dependency explanation | -- | polydep why |
| Boundary enforcement | -- | polydep check |
| Missing deps in project | poly check |
-- |
| Library analysis | poly libs |
-- |
polydep complements rather than replaces poly. It focuses on the inter-brick dependency graph.
Development
Setup
git clone https://github.com/aulme/polydep.git
cd polydep
uv sync
Common commands
uv run pytest # Run tests
uv run ruff check . # Lint
uv run ruff format . # Format
uv run ty check src/ tests/ # Type check
uv run polydep graph --root sample_project # Smoke test
CI
GitHub Actions runs three parallel jobs on every push and PR:
- test —
pytest - lint —
ruff check+ruff format --check - typecheck —
ty check
Test strategy
Tests use two approaches:
- Unit tests construct
Workspace/DependencyGraphobjects directly in memory — fast, no filesystem - Integration tests use a
sample_project/fixture (a real Polylith workspace with 10 bricks and known dependencies)
Dependencies
| Dependency | Purpose |
|---|---|
click |
CLI framework |
ast (stdlib) |
Import extraction |
tomllib (stdlib) |
Config parsing |
Dev tools: uv, pytest, ruff, ty
Project details
Release history Release notifications | RSS feed
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 polydep-0.1.0.tar.gz.
File metadata
- Download URL: polydep-0.1.0.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c33bd6042cef1aacd4f41aaf6e3b7ae40c5ad6f302d3d85c47d06379a26cd0dd
|
|
| MD5 |
e14d4273f3e74b6a157c30d290e3c778
|
|
| BLAKE2b-256 |
f090dbdd0d6dadd3438244dab072976b36077912ac640da8b7f58ba31e4a3bbe
|
Provenance
The following attestation bundles were made for polydep-0.1.0.tar.gz:
Publisher:
ci.yml on aulme/polydep
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polydep-0.1.0.tar.gz -
Subject digest:
c33bd6042cef1aacd4f41aaf6e3b7ae40c5ad6f302d3d85c47d06379a26cd0dd - Sigstore transparency entry: 953467010
- Sigstore integration time:
-
Permalink:
aulme/polydep@6abb339d9236eb2261cd40919f1f89a0ee8efd70 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/aulme
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@6abb339d9236eb2261cd40919f1f89a0ee8efd70 -
Trigger Event:
push
-
Statement type:
File details
Details for the file polydep-0.1.0-py3-none-any.whl.
File metadata
- Download URL: polydep-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d516a17da985818df710c618466019ef09901bba751676566704f7e581c03e34
|
|
| MD5 |
d1735ae893c7a04e4dd207ae8608130b
|
|
| BLAKE2b-256 |
739ad0733b4ba6efb73e3367b0cd9e8337ed2ef5b29ced3364f6375abfcc70f4
|
Provenance
The following attestation bundles were made for polydep-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on aulme/polydep
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polydep-0.1.0-py3-none-any.whl -
Subject digest:
d516a17da985818df710c618466019ef09901bba751676566704f7e581c03e34 - Sigstore transparency entry: 953467011
- Sigstore integration time:
-
Permalink:
aulme/polydep@6abb339d9236eb2261cd40919f1f89a0ee8efd70 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/aulme
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@6abb339d9236eb2261cd40919f1f89a0ee8efd70 -
Trigger Event:
push
-
Statement type: