Skip to main content

Graphite

Graphite is a Python toolkit for describing, validating, matching, and rewriting Heterograph-based intermediate representations (IRs). It also provides contracts for checking the output of a graph workflow. Graphite has no Loom dependency; any object with an output attribute can be verified.

Install

Graphite requires Python 3.10+, Heterograph, Pydantic 2, and graph-tool for graph matching. For local development:

conda env create graphite
conda activate graphite
conda install -c conda-forge graph-tool=3.0 graphviz python-graphviz
pip install -e .

The runnable examples are in examples/. validation and processor_tests require Graphite only; lowering and agent are Graphite and Loom integration examples.

IR schemas

GraphSchema defines the accepted graph, vertex, and edge metadata with Pydantic models. It constructs correctly typed graph elements and returns a ValidationReport instead of failing at the first invalid element. Each graph element uses _type to select its model.

from typing import Literal

from pydantic import BaseModel, Field
from graphite import GraphSchema


class ConstantProps(BaseModel):
    type_: Literal["Constant"] = Field(alias="_type")
    value: float


class NegateProps(BaseModel):
    type_: Literal["Negate"] = Field(alias="_type")


class DataEdgeProps(BaseModel):
    type_: Literal["data"] = Field(alias="_type")


ir = GraphSchema(
    name="ArithmeticIR",
    vertex={"Constant": ConstantProps, "Negate": NegateProps},
    edge={"data": DataEdgeProps},
)

graph = ir.new_graph()
constant = ir.new_vertex(graph, "Constant", value=3.0)
negate = ir.new_vertex(graph, "Negate")
ir.new_edge(graph, constant, negate, "data")

report = ir.validate(graph)
assert report.ok

Pass rules to GraphSchema for structural validation such as arity, acyclicity, or required inputs and outputs. A rule receives the HGraph and returns a list of Issue values. update_vertex() and update_edge() apply the same Pydantic validation when metadata changes.

Graph processor

GraphProcessor finds AQL patterns and applies one in-place rewrite pass. A result contains matches, the parsed pattern, and a modified flag.

from heterograph import HGraph
from graphite import GraphProcessor

graph = HGraph()
graph.add_vx(3)
graph.add_edge(0, 1)
graph.add_edge(1, 2)

processor = GraphProcessor(snapshot=False)
result = processor.run(
    graph,
    select="a => b => c",
    rewrite="a => c",
)

assert result["modified"]
assert set(graph.edges) == {(0, 2)}

Use where(graph, **match) to filter matches and finalize(graph, **match) to initialize created vertices or metadata. finalize must return a boolean. Rewrites require disjoint matches; Graphite rejects overlapping matches before mutating the graph. Rewire annotations preserve boundary connections when a matched vertex is replaced:

processor.run(
    graph,
    select="a => b => c",
    rewrite="a => x {rewire: b} => c",
)

GraphProcessor(snapshot=True) is the default and records graphs in a Heterograph WebView. Use snapshot=False for scripts and tests without a viewer.

Contracts

Contract evaluates one object with an output attribute and returns a ContractResult. Verifier runs a collection of contracts, retaining all results; if any fail, it raises ContractException with the individual failures.

GraphSchemaContract validates a result's graph output against a schema:

from dataclasses import dataclass

from graphite import GraphSchemaContract, Verifier


@dataclass
class BuildResult:
    output: object


checks = Verifier([GraphSchemaContract(ir)])
contract_results = checks.verify(BuildResult(output=graph))
assert contract_results["valid-ArithmeticIR"].passed

Custom contracts can check domain-specific properties:

from graphite import Contract, ContractResult


class HasVertices(Contract):
    def __init__(self):
        super().__init__(name="has-vertices")

    def evaluate(self, result):
        count = len(result.output.vertices)
        return ContractResult(
            passed=count > 0,
            output=result.output,
            metrics={"vertex_count": count},
        )

For complete examples, see examples/validation, examples/processor_tests, and the Loom-backed examples/lowering workflow.

Metadata

Release files for graphite-ir 0.1.0

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

Source distribution (sdist)

Source distribution for graphite-ir 0.1.0
File Size Uploaded
graphite_ir-0.1.0.tar.gz 13.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for graphite-ir 0.1.0
File Interpreter ABI Platform
graphite_ir-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.9 kB

Release files / graphite_ir-0.1.0.tar.gz

Download URL graphite_ir-0.1.0.tar.gz
Size 13.3 kB
Tags Source
SHA-256 checksum
How to use checksums
f1b959e17812b770d309958cc4db049a84fe128e316e85dab2122e5bf4de3157
BLAKE2b-256 checksum
How to use checksums
c924b1dd0acb7fd698b9d32864a318338ea34098681c3f778795b0dc3c21908e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / graphite_ir-0.1.0-py3-none-any.whl

Download URL graphite_ir-0.1.0-py3-none-any.whl
Size 13.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7b412585b28db9b9648e80513584960ccee42e6a5755423fd05cc8c044e54bfb
BLAKE2b-256 checksum
How to use checksums
24eaecd6a2858a97a7bb9cd15fe00a86ccd7482da0467c91b09cdf96fa5028b0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.1.0 This release

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