Skip to main content

lexigram-graph

Graph database support for the Lexigram Framework (Neo4j, in-memory).


Overview

lexigram-graph provides graph storage backends with DI wiring for in-memory and Neo4j implementations behind the graph contracts. It supports node and edge creation, graph traversal queries, Cypher compilation for Neo4j, and lazy graph creation with lifecycle events.


Full documentation: docs.lexigram.dev

Install

uv add lexigram-graph
# With Neo4j support
uv add "lexigram-graph[neo4j]"

Quick Start

from lexigram import Application
from lexigram.di.module import Module, module
from lexigram.graph import GraphConfig, GraphModule
from lexigram.contracts.data.graph import GraphStoreProtocol, TraversalQuery, StartSpec, TraversalStep


@module(imports=[GraphModule.configure(GraphConfig(backend="memory"))])
class AppModule(Module):
    pass


async def main() -> None:
    async with Application.boot(modules=[AppModule]) as app:
        store = await app.container.resolve(GraphStoreProtocol)
        graph = await store.get_graph()

        await graph.create_node(["Person"], {"name": "Alice"}, node_id="alice")
        await graph.create_node(["Person"], {"name": "Bob"}, node_id="bob")
        await graph.create_edge("alice", "bob", "KNOWS")

        paths = await graph.traverse(
            TraversalQuery(
                start=StartSpec(node_ids=("alice",)),
                steps=(TraversalStep(edge_types=("KNOWS",)),),
            )
        )
        assert paths


if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Configuration

Zero-config usage: Call GraphModule.configure() with no arguments to use all defaults (in-memory backend).

Option 1 — YAML file

# application.yaml
graph:
  enabled: true
  backend: neo4j
  default_traversal_max_depth: 10
  neo4j:
    uri: bolt://localhost:7687
    password: "${NEO4J_PASSWORD}"

Option 2 — Profiles + Environment Variables (recommended)

export LEX_GRAPH__BACKEND=neo4j
export LEX_GRAPH__NEO4J__URI=bolt://localhost:7687

Option 3 — Python

from lexigram.graph import GraphConfig, GraphModule
from lexigram.graph.config import Neo4jConfig

GraphModule.configure(
    GraphConfig(
        backend="neo4j",
        neo4j=Neo4jConfig(
            uri="bolt://localhost:7687",
            password="${NEO4J_PASSWORD}",
        ),
    )
)

Config reference

Field Default Env var Description
enabled true LEX_GRAPH__ENABLED Enable or disable the graph subsystem
backend memory LEX_GRAPH__BACKEND Graph backend to use (memory or neo4j)
default_traversal_max_depth 10 LEX_GRAPH__DEFAULT_TRAVERSAL_MAX_DEPTH Maximum depth for graph traversals
default_query_limit 100 LEX_GRAPH__DEFAULT_QUERY_LIMIT Default result limit for graph queries
bulk_batch_size 1000 LEX_GRAPH__BULK_BATCH_SIZE Batch size for bulk insert and update operations
max_retries 3 LEX_GRAPH__MAX_RETRIES Retry attempts on transient graph errors
retry_delay 1.0 LEX_GRAPH__RETRY_DELAY Seconds between retry attempts
neo4j.uri bolt://localhost:7687 LEX_GRAPH__NEO4J__URI Neo4j Bolt connection URI
neo4j.username neo4j LEX_GRAPH__NEO4J__USERNAME Neo4j authentication username
neo4j.password LEX_GRAPH__NEO4J__PASSWORD Neo4j authentication password (required for production)
neo4j.database neo4j LEX_GRAPH__NEO4J__DATABASE Target Neo4j database name
neo4j.max_connection_pool_size 100 LEX_GRAPH__NEO4J__MAX_CONNECTION_POOL_SIZE Maximum driver connection pool size
memory.max_nodes 1000000 LEX_GRAPH__MEMORY__MAX_NODES Node capacity for the in-memory backend
tenancy.enabled False Enable per-tenant graph isolation
tenancy.strategy "graph_per_tenant" "graph_per_tenant" or "node_property"
tenancy.template "{logical}_{tenant}" Template for resolving tenant-specific graph names

Module Factory Methods

Method Description
GraphModule.configure(config=None) Register GraphProvider with a config
GraphModule.stub(config=None) Lightweight test module with in-memory backend

Key Features

  • In-memory backend — no external service needed; for development and tests
  • Neo4j backend — async Neo4j driver with Cypher query compilation
  • Graph traversalTraversalQuery, StartSpec, TraversalStep for graph walks
  • Named graphs — lazy graph creation per name with lifecycle events
  • Connection pooling — configurable pool size for Neo4j driver

Testing

async with Application.boot(modules=[GraphModule.stub()]) as app:
    store = await app.container.resolve(GraphStoreProtocol)
    graph = await store.get_graph()
    # Test with in-memory backend

Multi-Tenancy

lexigram-graph supports two isolation strategies:

Strategies

Strategy GraphTenancyStrategy How It Works
Graph per tenant GRAPH_PER_TENANT Graph names are resolved through a TenantCollectionResolver, giving each tenant an isolated named graph
Node property NODE_PROPERTY Graph names pass through unchanged; every node/edge gets a tenant_id property, and find_nodes auto-injects a tenant_id filter

Configuration

from lexigram.graph.config import GraphTenancyConfig, GraphConfig, GraphModule

config = GraphConfig(
    backend="neo4j",
    tenancy=GraphTenancyConfig(
        enabled=True,
        strategy="graph_per_tenant",  # or "node_property"
        template="{logical}_{tenant}",
    ),
)
GraphModule.configure(config)

Components

Component Role
GraphTenancyConfig Dataclass with enabled, strategy, and template
TemplatedTenantCollectionResolver Resolves logical → physical graph names
TenantGraphStoreDecorator Strategy-aware decorator: resolves names (GRAPH_PER_TENANT) or wraps returned graphs (NODE_PROPERTY)
TenantPropertyFilterGraph Auto-injects tenant_id into create_node/create_edge properties and find_nodes filters

Key Source Files

File What it contains
src/lexigram/graph/module.py GraphModule.configure(), .stub()
src/lexigram/graph/config.py GraphConfig, GraphTenancyConfig, Neo4jConfig
src/lexigram/graph/di/provider.py GraphProvider boot and registration
src/lexigram/graph/backends/memory/backend.py InMemoryGraphStore implementation
src/lexigram/graph/backends/neo4j/backend.py Neo4jGraphStore implementation
src/lexigram/graph/backends/neo4j/cypher.py CypherCompiler
src/lexigram/graph/tenancy/ Strategy enum, decorator, resolver, property filter graph

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

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

lexigram_graph-0.1.2-py3-none-any.whl (30.6 kB view details)

Uploaded Python 3

File details

Details for the file lexigram_graph-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for lexigram_graph-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ab46877859a740ff218701f0e407a5b22bdf75c3a232c45f098f65a3f2a47ba6
MD5 33cd64ab7c4a3cd4cd64c3b0198a7b11
BLAKE2b-256 9ab9a82ed8a19ffb7c81ff15ad0b719ed212ee5d44751ed8ce0eff2fb93ee873

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.5008

1 file

0.1.5004

2 files

0.1.5001

2 files

0.1.3007

1 file

0.1.3006

1 file

0.1.3005

1 file

0.1.4

2 files

This release

0.1.2 This release

1 file

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