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.
Mostly read-only — polydep project --fix can rewrite [tool.polylith.bricks] sections.
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
message_api
end
subgraph components
database
dictionaries
greeting
kafka
log
message
schema
end
consumer --> kafka
consumer --> log
greet_api --> greeting
greet_api --> log
kafka --> log
message --> database
message --> dictionaries
message --> kafka
message --> schema
message_api --> database
message_api --> log
message_api --> message
message_api --> schema
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 project
Check that each project's pyproject.toml declares exactly the bricks it needs — no missing, no stale extras. Computes the full transitive closure from the project's base bricks.
polydep project [<project_path>] [--fix] [--root <path>]
| Flag | Default | Description |
|---|---|---|
<project_path> |
Single project directory to check (omit to scan all projects/*/) |
|
--fix |
Rewrite [tool.polylith.bricks] with the correct set |
|
--root <path> |
. |
Workspace root directory |
Example output (issues found):
consumer_app: 2 issue(s)
Missing (needed but not declared):
log
Extra (declared but not needed):
greeting
messaging: OK
The --fix flag rewrites the bricks section in place, grouping entries into # direct (base bricks and their immediate imports) and # transitive (everything else), with # via annotations showing which bricks pull each transitive one in:
[tool.polylith.bricks]
# direct
"../../bases/example/message_api" = "example/message_api"
"../../components/example/database" = "example/database"
"../../components/example/log" = "example/log"
"../../components/example/message" = "example/message"
"../../components/example/schema" = "example/schema"
# transitive
"../../components/example/dictionaries" = "example/dictionaries" # via message
"../../components/example/kafka" = "example/kafka" # via message
| Exit code | Meaning |
|---|---|
| 0 | All projects OK (or --fix applied) |
| 1 | Issues found (without --fix) |
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.
When the graph matches:
Check passed.
When there are violations:
Check failed.
Unexpected dependencies:
consumer --> database
bases/example/consumer/core.py:3 from example import database, kafka, log
Missing dependencies:
greet_api --> log
| 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/extra deps in project | poly check |
polydep project |
| Library analysis | poly libs |
-- |
polydep complements rather than replaces poly. It focuses on the inter-brick dependency graph.
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.9.tar.gz.
File metadata
- Download URL: polydep-0.1.9.tar.gz
- Upload date:
- Size: 216.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d18bf1c35c655bdf2ab8ba5b2c35b6ab1eb6e61b33ba94ba64500399729900e5
|
|
| MD5 |
c5928d441eabfc018c78645faeabf4fa
|
|
| BLAKE2b-256 |
7bd585a9564b9928e0de71fd259c0088dfe421b4583b11b0d95409a5d6e03eb5
|
Provenance
The following attestation bundles were made for polydep-0.1.9.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.9.tar.gz -
Subject digest:
d18bf1c35c655bdf2ab8ba5b2c35b6ab1eb6e61b33ba94ba64500399729900e5 - Sigstore transparency entry: 992419867
- Sigstore integration time:
-
Permalink:
aulme/polydep@b57d44cda806268d3945322321a639b90cf594a6 -
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@b57d44cda806268d3945322321a639b90cf594a6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file polydep-0.1.9-py3-none-any.whl.
File metadata
- Download URL: polydep-0.1.9-py3-none-any.whl
- Upload date:
- Size: 198.1 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 |
6e7d7bafa526ea03bd1a59866508f72af41f9cf9d2bf69d527f155a9efe33193
|
|
| MD5 |
b7e13417120a5d427fca3166e6e1fb15
|
|
| BLAKE2b-256 |
dede47f6e5286e95ba33c49f7a2fb1d7f478685bba0e4677bdb71ebc164e2b1f
|
Provenance
The following attestation bundles were made for polydep-0.1.9-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.9-py3-none-any.whl -
Subject digest:
6e7d7bafa526ea03bd1a59866508f72af41f9cf9d2bf69d527f155a9efe33193 - Sigstore transparency entry: 992419871
- Sigstore integration time:
-
Permalink:
aulme/polydep@b57d44cda806268d3945322321a639b90cf594a6 -
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@b57d44cda806268d3945322321a639b90cf594a6 -
Trigger Event:
push
-
Statement type: