Skip to main content

Graphworks

Python package

A Python module for efficient graph theoretic programming

Wiki

Quick Start

pip install graphworks
from graphworks import Graph, to_text
from graphworks.algorithms import find_path, is_connected

graph = Graph("roads").add_edge("A", "B", weight=2).add_edge("B", "C", label="toll")
print(graph.neighbors("B"))        # ['A', 'C'] — undirected edges work both ways
print(find_path(graph, "C", "A"))  # ['C', 'B', 'A']
print(is_connected(graph))         # True
print(to_text(graph))

Graphs can also be loaded from JSON (Graph(input_file=...) / Graph(input_graph=...)); a neighbor may be a bare name or an object carrying edge data:

{
  "label": "roads",
  "directed": false,
  "weighted": true,
  "vertices": { "A": { "label": "Alpha" } },
  "graph": { "A": ["B", { "target": "C", "weight": 2.5, "label": "toll" }], "B": [], "C": [] }
}

save_to_json writes this same format, so weights, labels, and attributes round-trip.

API conventions

  • Graph is the only class; algorithms (graphworks.algorithms) and exporters (graphworks.export) are free functions that take a Graph.
  • A vertex name that is not in the graph raises KeyError (graph[v], neighbors, and every algorithm). The dict.get-style graph.vertex(name) and graph.edge(u, v) return None.
  • Predicates are vacuously true on an empty graph; metrics that are undefined there (min_degree, max_degree, diameter) raise ValueError.
  • Algorithms whose precondition fails raise ValueError rather than returning a wrong answer (topological_sort on a cyclic graph, find_circuit on a non-Eulerian graph, diameter on a disconnected graph).
  • Degree counts every incident edge (in + out for directed graphs; a self-loop counts twice).

Optional extras:

pip install graphworks[matrix]   # numpy adjacency matrix support
pip install graphworks[viz]      # graphviz export
pip install graphworks[docs]     # generate documentation

Development

Requirements

  • Python 3.13+
  • uv (>= 0.10.12)

Setup

uv sync --extra all

Running Tests

# Run all tests (includes coverage; fails under 90%)
uv run pytest

# Run a single test file
uv run pytest tests/test_graph.py

# Run a single test by name
uv run pytest tests/test_graph.py -k "test_method_name"

Linting and Formatting

# Lint
uv run ruff check --fix src/ tests/

# Format
uv run black src/ tests/
uv run isort src/ tests/

# Type checking
uv run ty check

# Code complexity
uv run xenon --max-average=A --max-modules=B --max-absolute=B src/

# Run all pre-commit hooks
prek run --all-files

Publishing

Version is managed automatically via git tags using hatchling-vcs.

  • Tag a commit: git tag -a X.Y.Z -m 'release message'
  • Push the tag: git push --tags
  • The GitHub Actions workflow will build and publish to PyPI automatically.

Roadmap

Tier 1: Data model

  • Vertex class with name, optional label, and immutable attribute mapping
  • Edge dataclass with source, target, directed flag, optional weight, label, and attributes
  • Both classes are frozen (immutable) with identity-based equality and hashing

Tier 2: Graph refactor

  • Internal storage uses dict[str, Vertex] for vertex lookup
  • Adjacency structure uses dict[str, dict[str, Edge]] for O(1) edge access
  • Edge weights, labels, and attributes survive union, complement (vertices), and JSON/DOT export
  • add_edge supports weight and label keyword arguments
  • edge() lookup method for direct O(1) edge retrieval
  • remove_vertex() / remove_edge() (chainable; removing a vertex drops its incident edges)
  • copy() (independent structure, shared immutable Vertex/Edge objects)
  • predecessors() for directed graphs (O(V); same as neighbors() when undirected)

Tier 3: Lossless conversions

  • to_adjacency_matrix() / from_adjacency_matrix() round-trips that preserve vertex names via an index mapping
  • complement preserves original vertex names and the directed flag
  • to_edge_list() / from_edge_list() conversions
  • Weighted JSON format ({"target": ..., "weight": ...} neighbor objects, see g4.json)

Tier 4: Algorithms

  • Unweighted shortest path via BFS (find_path returns a path, not the shortest; diameter already computes BFS distances internally)
  • Dijkstra's shortest path (weighted)
  • Prim's / Kruskal's minimum spanning tree
  • Strongly connected components (Tarjan or Kosaraju) and is_strongly_connected

Tier 5: Export and CLI

  • JSON export (save_to_json, lossless round-trip)
  • Graphviz DOT export (save_to_dot, with vertex/edge labels and weights)
  • Text tree and 2-D ASCII rendering (to_text, to_ascii)
  • Rich-based demo script (uv run demo)
  • CLI application for common graph operations
  • Rich rendering integration for interactive graph display

Tier 6: Cross-cutting quality

  • Iterative traversals: find_path, find_all_paths, and topological_sort are recursive and raise RecursionError on a ~3,000-vertex chain
  • Input validation hardening:
    • Reject non-list neighbor values in JSON ({"A": "B"} is silently read as the characters of "B")
    • Raise when more than one of input_file / input_graph / input_matrix is given (extras are silently ignored)
  • Read-only graph view (instead of locking for thread safety)
  • Performance benchmarks
  • Reverse adjacency index so predecessors() is O(in-degree) instead of O(V); then switch is_connected, find_circuit, and find_isolated_vertices to it (they currently rebuild in-edges by hand, which is faster than calling the O(V) predecessors() per vertex). Every add/remove path and copy() must maintain the index.
  • Run docstring examples as tests (--doctest-modules) so examples cannot go stale

Tier 7: Docs and releases

  • CHANGELOG.md (linked from the PyPI metadata but missing), starting with the 0.10.0 breaking changes
  • Hosted API documentation (Sphinx deps exist in the [docs] extra, but there is no docs/ source and the Read the Docs site does not exist)

Metadata

Release files for graphworks 0.11.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for graphworks 0.11.1
File Size Uploaded
graphworks-0.11.1.tar.gz 36.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for graphworks 0.11.1
File Interpreter ABI Platform
graphworks-0.11.1-py3-none-any.whl Python 3 none any Details

Total release size: 80.7 kB

Release files / graphworks-0.11.1.tar.gz

Download URL graphworks-0.11.1.tar.gz
Size 36.0 kB
Tags Source
SHA-256 checksum
How to use checksums
b33e3ef8834e4dfd5344aa163e07d61f395b76f8be6ed5964557f9ce5a54af92
BLAKE2b-256 checksum
How to use checksums
14a612ce0c194c08dedce3878ddd26401983dba360ef52fd862c22b96fdec046
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Release files / graphworks-0.11.1-py3-none-any.whl

Download URL graphworks-0.11.1-py3-none-any.whl
Size 44.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7744412bf9eb08099e2476617f27c74168dd970b49da622eaf8f51f596867e64
BLAKE2b-256 checksum
How to use checksums
5950f7d910df73c698c8e9faab6cba192b7a4e224cc5a4ff02fe77a8981c9d8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.1 This release

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.12

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page