Compare Directional Graphs
Project description
This library compares two directional graphs and outputs the diff result as a dot file. Primary intended use is to compare changes in software dependencies, for example in gradle projects though it is designed to not be limited to gradle.
Github action
This repo contains an action that can be used to generate diagrams of local project dependency changes on pull requests, please see example_workflow/test_action.yml
"Deps" Input Format
The input for one graph is just multiple lines in the format:
a -> b
This line denotes that a depends on b.
You can also chain nodes:
a -> b -> c
This line denotes that a depends on b, and that b depends on c.
And is the same as two entries:
a -> b
b -> c
Files of this format have the .deps suffix. See the examples folder.
The set of dependencies in a file is then loaded in to a graph format, this is a NetworkX DiGraph under the hood.
With two DiGraphs loaded (or otherwise created) you can compare them to create a diff.
Orphaned nodes can be denoted a single line with just their name on it, e.g.
a
The Diff
The diff of two DiGraphs A and B is another DiGraph that includes:
- All removed connections (present in A but not B)
- All added connections (present in B but not A)
- All removed nodes
- All added nodes
- All nodes at either end of an included connection
- All unchanging connections between all included nodes
- All transitive connections between all included nodes
Elements have metadata to describe which rule they are included under, such as "added"/"removed"/"transitive".
Output
The output is a dot file, properties in the DiGraph describing the added/removed/transitive state of elements are converted to color coding/line formats.
Gradle Input
This library contains code to parse a gradle dependency output into the deps format.
An example of generating this input is:
cd sample
./gradlew -q :app:dependencies --configuration runtimeClasspath > ../examples/dependencies.txt
For your own project you may need to edit the command for your main app name (:app) and configuration name (runtimeClasspath) to match your project. Also see git_gradle_diff section below for an end-to-end example.
Setup
Install uv.
Install dot if not present, this is used to create the images from the .dot file.
On mac you can do:
brew install graphviz
For other environments see https://graphviz.org/download/
Running
Pass a single file into the diff.
uv run main.py diff examples/revision1.deps --dark-mode --caption "Revision 1" -o docs/revision1.png
And it will create a png output for the one file:
Running again for revision2:
uv run main.py diff examples/revision2.deps --dark-mode --caption "Revision 2" -o docs/revision2.png
If you look carefully, you will be able to make out the changes, but if we pass the two deps files, it will output the diff them:
uv run main.py diff examples/revision1.deps examples/revision2.deps --dark-mode --caption "Diff of Revision 1 & 2" -o docs/compare_two_dep_files.png
Now we can clearly see just the changes:
:lib-bwas removed altogether and the link from:appwas therefore also removed (in red).- A new link from
:lib-eto:lib-fwas created (in green). - Transitive links are shown between
:appand:lib-ebecause they are still connected by another part of the full graph,:lib-dwhich is not shown as it has not changed.
You can also pass in the output of the gradle dependencies query:
uv run main.py diff examples/dependencies.txt examples/dependencies2.txt --dark-mode --caption "Diff of dependency files" -o docs/compare_two_gradle_outputs.png
git_gradle_diff
The following command given a copy of the Signal git repository, will diff two commits on signal and produce a png. It works by creating its own worktree and won't affect the repository otherwise. Note that it leaves this worktree behind afterward.
This is not yet working on windows.
uv run main.py git_gradle_diff ~/workspace/Signal-Android 1fc119e027d 4bbed2601cf -a :Signal-Android -c playProdReleaseRuntimeClasspath --dark-mode --caption "Signal {old} vs {new}" -o docs/signal_diff.png
This is just one example integration, you can create your own scripts to generate intermediary gradle outputs or .deps files and just call the diff command with those.
Testing
The library has its own test runner which discovers and runs test files under the test/ path.
You can run them like so:
uv run main.py tests
The dot file output is committed to this repo as the expected result.
If the output changes expectedly, you can run python main.py tests -u to update the output.
Also run:
uv run pytest
For regular code tests.
Requirements
This project uses the following libraries for these purposes:
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 diff_dot-2025.3.11.1.tar.gz.
File metadata
- Download URL: diff_dot-2025.3.11.1.tar.gz
- Upload date:
- Size: 153.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15ca70bac13b3e7fc5e181fece3ea15021139803f9cc00c3573f0fbe65f58d28
|
|
| MD5 |
d3926e5d64282d14435a890f34aa9510
|
|
| BLAKE2b-256 |
cac6bff978c873504afb88ccf68764be878444c1e807275b398fbc489d9d8e0c
|
Provenance
The following attestation bundles were made for diff_dot-2025.3.11.1.tar.gz:
Publisher:
publish-to-test-pypi.yml on westonal/graph-diff
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diff_dot-2025.3.11.1.tar.gz -
Subject digest:
15ca70bac13b3e7fc5e181fece3ea15021139803f9cc00c3573f0fbe65f58d28 - Sigstore transparency entry: 180232796
- Sigstore integration time:
-
Permalink:
westonal/graph-diff@5f37cd8c90ef3804782a58f19ef9e07942d2404a -
Branch / Tag:
refs/tags/2025.3.11.1 - Owner: https://github.com/westonal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-test-pypi.yml@5f37cd8c90ef3804782a58f19ef9e07942d2404a -
Trigger Event:
push
-
Statement type:
File details
Details for the file diff_dot-2025.3.11.1-py3-none-any.whl.
File metadata
- Download URL: diff_dot-2025.3.11.1-py3-none-any.whl
- Upload date:
- Size: 18.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fcd4de38e4343f866740444f8f81cb09c5b1a5ef366ad36b7f9270ae03310c4
|
|
| MD5 |
eac4674026665ab6b08cdc7e75e0762b
|
|
| BLAKE2b-256 |
06b3bc065d16afbf0ac2f3a10bc16d6a584dff696c39faaece74c3fe9156aada
|
Provenance
The following attestation bundles were made for diff_dot-2025.3.11.1-py3-none-any.whl:
Publisher:
publish-to-test-pypi.yml on westonal/graph-diff
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diff_dot-2025.3.11.1-py3-none-any.whl -
Subject digest:
0fcd4de38e4343f866740444f8f81cb09c5b1a5ef366ad36b7f9270ae03310c4 - Sigstore transparency entry: 180232802
- Sigstore integration time:
-
Permalink:
westonal/graph-diff@5f37cd8c90ef3804782a58f19ef9e07942d2404a -
Branch / Tag:
refs/tags/2025.3.11.1 - Owner: https://github.com/westonal
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-test-pypi.yml@5f37cd8c90ef3804782a58f19ef9e07942d2404a -
Trigger Event:
push
-
Statement type: