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)
| File | Size | Uploaded | |
|---|---|---|---|
| graphite_ir-0.1.0.tar.gz | 13.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|