Skip to main content

Compare Directional Graphs

Project description

PyPI - Version PyPI - Downloads

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:

Revision 1

Running again for revision2:

uv run main.py diff examples/revision2.deps --dark-mode --caption "Revision 2" -o docs/revision2.png

Revision 1

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:

Compare two dep files

  • :lib-b was removed altogether and the link from :app was therefore also removed (in red).
  • A new link from :lib-e to :lib-f was created (in green).
  • Transitive links are shown between :app and :lib-e because they are still connected by another part of the full graph, :lib-d which 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 

Compare two gradle outputs

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

Signal Diff

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:

  • NetworkX for graph analysis
  • Rich for CLI formatting
  • Click for CLI command line argument parsing

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

diff_dot-2025.3.11.1.tar.gz (153.3 kB view details)

Uploaded Source

Built Distribution

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

diff_dot-2025.3.11.1-py3-none-any.whl (18.2 kB view details)

Uploaded Python 3

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

Hashes for diff_dot-2025.3.11.1.tar.gz
Algorithm Hash digest
SHA256 15ca70bac13b3e7fc5e181fece3ea15021139803f9cc00c3573f0fbe65f58d28
MD5 d3926e5d64282d14435a890f34aa9510
BLAKE2b-256 cac6bff978c873504afb88ccf68764be878444c1e807275b398fbc489d9d8e0c

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for diff_dot-2025.3.11.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0fcd4de38e4343f866740444f8f81cb09c5b1a5ef366ad36b7f9270ae03310c4
MD5 eac4674026665ab6b08cdc7e75e0762b
BLAKE2b-256 06b3bc065d16afbf0ac2f3a10bc16d6a584dff696c39faaece74c3fe9156aada

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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