Skip to main content

Pre-release Python bindings for grm-rs runtime graph sessions.

Project description

grm-rs Python bindings

This crate packages a first-pass Python API for the grm-rs runtime session surface. It includes embedded Session, service-backed ServiceSession, and direct Neo4jSession implementations of a portable synchronous GraphSession core.

The Python package is an alpha pre-release. Its API and supported backend capabilities may change between alpha versions, but it is published for public evaluation, tutorials, and early application development.

Install the latest published alpha from PyPI:

python -m pip install --pre grm-rs

Pin a specific release when reproducibility matters:

python -m pip install grm-rs==0.1.0a8

The distribution package is named grm-rs; the import package is grm_rs.

Build

cd grm-python
maturin develop

Build a shareable wheel from the repository root:

python -m pip install maturin
maturin build --manifest-path grm-python/Cargo.toml --release --out dist

See ../docs/python-package-distribution.md for local builds and release details.

Example

from grm_rs import GraphId, GraphSession, Session


def add_user(session: GraphSession, name: str) -> GraphId:
    return session.node_create("User", {"name": name})["id"]

session = Session()
session.model_create(
    "User",
    "userId",
    [
        {"name": "name", "type": "string", "required": True},
        {"name": "age", "type": "int", "required": False},
    ],
)
session.model_create(
    "Post",
    "postId",
    [
        {"name": "title", "type": "string", "required": True},
    ],
)
session.link_create(
    "AUTHORED",
    "User",
    "Post",
    "authoredId",
    [
        {"name": "year", "type": "int", "required": True},
    ],
)

alice = session.node_create("User", {"name": "Alice", "age": 42})
post = session.node_create("Post", {"title": "Hello"})
edge = session.edge_create("AUTHORED", alice["id"], post["id"], {"year": 2024})
users = session.node_find("User", {"name": "Alice"})

The same add_user function accepts Session, ServiceSession, or Neo4jSession; applications do not need to redeclare the session API.

Portable Store Injection

Application stores can depend on GraphSession and receive either backend:

from grm_rs import GraphSession, Neo4jSession, ServiceSession


class UserStore:
    def __init__(self, graph: GraphSession) -> None:
        self.graph = graph

    def find_named(self, name: str):
        return self.graph.node_find("User", {"name": name})


graph: GraphSession
if use_neo4j:
    graph = Neo4jSession(uri=uri, user=user, password=password)
else:
    graph = ServiceSession(endpoint=endpoint, workspace_ref="demo", mode="open")

users = UserStore(graph).find_named("Ada")

The portable core has compatible schema inspection, CRUD/find, and atomic batch semantics. GraphId is opaque application-facing identity: code may pass returned IDs back to the same graph session, but must not assume physical ID preservation when moving data between backends.

Capability Portable GraphSession Workspace only Neo4j native
Schema define/list yes yes yes, GRM-owned session metadata
Node/edge CRUD and simple find yes yes yes
Atomic batch writes yes yes yes, one Neo4j transaction
Non-atomic batch writes no yes no
Traversal-shaped node_find no yes no
Explain/profile, indexes, import/export no yes no
Native Cypher via execute_query no no yes

Use session.capabilities() for lightweight discovery. The stable capability names currently include graph, atomic_batch, non_atomic_batch, workspace, traversal, explain_profile, persistence, and neo4j_native_query; applications should test membership rather than assume every session has optional methods.

Traversal queries mirror CLI node.find ... via=... semantics with structured Python inputs:

posts = session.node_find(
    "User",
    {"name": "Alice"},
    via=[
        {"dir": "out", "link": "AUTHORED", "model": "Post"},
    ],
)

authored_edges = session.node_find(
    "User",
    {"name": "Alice"},
    via=[
        {"dir": "out", "link": "AUTHORED", "model": "Post"},
    ],
    end_filters={"title": "Hello"},
    edge_filters={"year": 2024},
    return_="edge",
)

Explain and profile use the same query arguments and return structured plan data:

plan = session.explain_node_find(
    "User",
    {"name": "Alice"},
    via=[{"dir": "out", "link": "AUTHORED", "model": "Post"}],
)

profile = session.profile_edge_find("AUTHORED", {"from": alice["id"]})
assert profile["result_rows"] >= 0

indexes = session.indexes()
assert indexes["indexes"][0]["kind"] == "system"

Index catalog entries describe GRM-maintained derived acceleration structures such as node-label, exact node-property, relationship-type, and adjacency indexes. They are not user-defined indexes, and their contents are not durable source-of-truth data.

Batch operations share the same runtime semantics as MCP grm_batch, including atomic rollback, indexed errors, batch-local refs, and one autocommit snapshot after successful applied operations:

result = session.batch(
    [
        {"op": "node_create", "args": {"model": "User", "props": {"name": "Bob"}, "ref": "bob"}},
        {"op": "node_create", "args": {"model": "Post", "props": {"title": "Hello"}, "ref": "post"}},
        {
            "op": "edge_create",
            "args": {"model": "AUTHORED", "from": "bob", "to": "post", "props": {"year": 2026}},
        },
    ],
    response="detailed",
)

The portable GraphSession.batch() contract is atomic-only and therefore has no atomic argument. For Neo4j it stages GRM schema changes, executes all graph writes in one backend transaction, and installs staged schema only after commit. A failed operation rolls back graph writes and discards staged schema. Workspace sessions additionally implement WorkspaceBatchCapability, whose atomic=False mode is intentionally outside the portable contract.

Use save_json / load_json or save_binary / load_binary for local workspace snapshots. Use export_json, export_dict, and import_json for portable grm.interchange graph files; import_json currently imports into an empty session only.

Service-Backed Session

ServiceSession routes supported operations through the gRPC workspace service using workspace-scoped ExecuteWorkspace. The supported subset is schema define/list, node and edge create/update/delete/find, traversal-capable node_find for node/root/end/edge results, batch, and reopen by constructing another ServiceSession with mode="open" and the same workspace_ref.

from grm_rs import ServiceSession

session = ServiceSession(
    endpoint="http://127.0.0.1:50051",
    workspace_ref="python-demo",
    mode="create",
)
session.model_create("User", "userId", [{"name": "name", "type": "string", "required": True}])
ada = session.node_create("User", {"name": "Ada"})
assert session.node_find("User", {"id": ada["id"]})[0]["props"]["name"] == "Ada"

reopened = ServiceSession(
    endpoint="http://127.0.0.1:50051",
    workspace_ref="python-demo",
    mode="open",
)
assert len(reopened.node_find("User", {"name": "Ada"})) == 1

For a local TLS service, use an https:// endpoint and either pass trust material explicitly:

session = ServiceSession(
    endpoint="https://127.0.0.1:50051",
    workspace_ref="python-demo",
    mode="create",
    tls_ca_cert="/tmp/grm-tls/ca.crt",
    tls_domain_name="localhost",
    tls_client_cert="/tmp/grm-tls/client.crt",
    tls_client_key="/tmp/grm-tls/client.key",
)

or set GRM_SERVICE_TLS_CA_CERT, GRM_SERVICE_TLS_DOMAIN_NAME, GRM_SERVICE_TLS_CLIENT_CERT, and GRM_SERVICE_TLS_CLIENT_KEY in the environment before constructing ServiceSession. Client certificate/key parameters are paired and are required when the server enforces mutual TLS.

Service workspaces use binary persistence by default. Pass workspace_format="json" explicitly when you need JSON workspace files. The Python service path supports typed traversal-capable node_find, explain_node_find, and profile_node_find through workspace-scoped service requests. Direct unscoped service RPCs, free-form query parity, import/export, hosted durability, RBAC, production certificate lifecycle, and multi-writer coordination are not provided by this Python service path.

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

grm_rs-0.1.0a8.tar.gz (398.9 kB view details)

Uploaded Source

Built Distributions

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

grm_rs-0.1.0a8-cp39-abi3-win_amd64.whl (3.6 MB view details)

Uploaded CPython 3.9+Windows x86-64

grm_rs-0.1.0a8-cp39-abi3-manylinux_2_34_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.34+ x86-64

grm_rs-0.1.0a8-cp39-abi3-macosx_11_0_arm64.whl (3.8 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

File details

Details for the file grm_rs-0.1.0a8.tar.gz.

File metadata

  • Download URL: grm_rs-0.1.0a8.tar.gz
  • Upload date:
  • Size: 398.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for grm_rs-0.1.0a8.tar.gz
Algorithm Hash digest
SHA256 9e07b16f3ae2f4c544871a115fea34b9bfa98db6b6f2686a7b61a8f60c3b1029
MD5 102660848b6bdc28dfacaf7d8807f67d
BLAKE2b-256 1d9a46120b7036f17cfa014ea9cc8b51ddb3a0c14c614627384873700a3dd424

See more details on using hashes here.

Provenance

The following attestation bundles were made for grm_rs-0.1.0a8.tar.gz:

Publisher: python-wheels.yml on poppaLol/grm-rs

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

File details

Details for the file grm_rs-0.1.0a8-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: grm_rs-0.1.0a8-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.6 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for grm_rs-0.1.0a8-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 d6e897467a4c75471f9b9c78e7641ef234cad369448c12ff7bb7e90b0724677e
MD5 bab44d6a7b731e9b04baa2c48714c214
BLAKE2b-256 61af68f83ae49ff06bac8a7cd9901fc0356135d795ad5fded010c1094b216895

See more details on using hashes here.

Provenance

The following attestation bundles were made for grm_rs-0.1.0a8-cp39-abi3-win_amd64.whl:

Publisher: python-wheels.yml on poppaLol/grm-rs

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

File details

Details for the file grm_rs-0.1.0a8-cp39-abi3-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for grm_rs-0.1.0a8-cp39-abi3-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 4baa25d8a5c8cc9b97ce050a8fde93632de683a05aca51ede0cdb64c0f18b361
MD5 61057b519717585a500d552d0d92151a
BLAKE2b-256 03cf1f1e3ce5b9cac0cb4634ac81b43eddc853758d82efbc45564d2dfc810549

See more details on using hashes here.

Provenance

The following attestation bundles were made for grm_rs-0.1.0a8-cp39-abi3-manylinux_2_34_x86_64.whl:

Publisher: python-wheels.yml on poppaLol/grm-rs

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

File details

Details for the file grm_rs-0.1.0a8-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for grm_rs-0.1.0a8-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e92a575ac59cd0bb50e2a3035086d49e668ba55d4771838fe5de0602c3509d78
MD5 9d258b46b43be4f55eb1cd6c36c56963
BLAKE2b-256 f1712ec211df4d09dd47f1943a456c39459c90b52c052ea459db8546fba975b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for grm_rs-0.1.0a8-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: python-wheels.yml on poppaLol/grm-rs

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