Pydantic meet Cypher, Cypher meet Pydantic.
Project description
cypherantic
Pydantic meet Cypher, Cypher meet Pydantic.
⚠️ ALPHA SOFTWARE: This project is in early development and has not been released. The API is subject to change without notice. Use at your own risk.
Overview
Cypherantic is a Python library that makes interacting with Neo4j simple and typesafe by leveraging Pydantic models. Define your graph structure using familiar Pydantic syntax, and let cypherantic handle the Cypher query generation and type validation.
Features
- Type-safe graph modeling: Use Pydantic models to define nodes and relationships with full type checking support
- Automatic constraint management: Unique constraints are created automatically based on field metadata
- Relationship traversal: Navigate graph relationships with simple method calls that preserve type information
- Async-first: Built on neo4j's async driver for modern Python applications
- Zero boilerplate: No manual Cypher query writing for common operations
Installation
Since this is an unreleased alpha project, install directly from source:
uv pip install git+https://github.com/yourusername/cypherantic.git
Quick Example
Using the Neo4j movies database as an example:
import typing
import neo4j
import pydantic
import cypherantic
class MovieReviewEdge(typing.NamedTuple):
node: 'User'
properties: 'MovieReview'
class Movie(pydantic.BaseModel):
title: typing.Annotated[str, cypherantic.Field(unique=True)]
released: typing.Annotated[int, cypherantic.Field(unique=True)]
tagline: str | None = None
reviews: typing.Annotated[
list[MovieReviewEdge],
cypherantic.Relationship(rel_type='REVIEWED', direction='INCOMING'),
] = []
class User(pydantic.BaseModel):
cypherantic_config: typing.ClassVar[cypherantic.NodeConfig] = {
'labels': ['Person'],
}
name: typing.Annotated[str, cypherantic.Field(unique=True)]
class MovieReview(pydantic.BaseModel):
cypherantic_config: typing.ClassVar[cypherantic.RelationshipConfig] = {
'rel_type': 'REVIEWED',
}
rating: float
summary: str
async def main() -> None:
async with neo4j.AsyncGraphDatabase().driver(
'bolt://localhost:7687', auth=('neo4j', 'password')
) as driver:
movie = Movie(
title='Cloud Atlas',
released=2012,
tagline='Everything is connected',
)
async with driver.session() as session:
# Load all reviews for the movie
await cypherantic.refresh_relationship(session, movie, 'reviews')
for edge in movie.reviews:
print(f'{edge.node.name}: {edge.properties.rating}/5')
Key Concepts
Node Models
Define graph nodes using Pydantic models. Use cypherantic.Field(unique=True)
to mark properties that should have uniqueness constraints:
class Person(pydantic.BaseModel):
name: typing.Annotated[str, cypherantic.Field(unique=True)]
born: int
Override the node labels using the cypherantic_config class variable:
class User(pydantic.BaseModel):
cypherantic_config: typing.ClassVar[cypherantic.NodeConfig] = {
'labels': ['Person', 'User'],
}
name: str
Relationship Models
Define relationship properties using Pydantic models with a
cypherantic_config that specifies the relationship type:
class ActedIn(pydantic.BaseModel):
cypherantic_config: typing.ClassVar[cypherantic.RelationshipConfig] = {
'rel_type': 'ACTED_IN',
}
roles: list[str]
Edge Types
Connect nodes and relationship properties using NamedTuples:
class ActedInEdge(typing.NamedTuple):
node: Movie
properties: ActedIn
Relationships on Node Models
Declare relationships on node models using the cypherantic.Relationship
annotation:
class Actor(pydantic.BaseModel):
name: str
movies: typing.Annotated[
list[ActedInEdge],
cypherantic.Relationship(rel_type='ACTED_IN', direction='OUTGOING'),
] = []
Core API
Node Operations
create_node(session, model): Create a node from a Pydantic modelunwrap_node_as(model_cls, node): Convert a Neo4j node to a Pydantic model
Relationship Operations
create_relationship(session, from_node, to_node, rel_props): Create a relationship between nodesrefresh_relationship(session, model, rel_property): Load relationship edges into a model's relationship fieldretrieve_relationship_edges(session, model, rel_name, direction, edge_cls): Retrieve relationship edges with full type information
Requirements
- Python 3.12+
- Neo4j 6.0+
- Pydantic 2.12+
License
BSD-3-Clause License. See LICENSE file for details.
Contributing
Since this is an alpha project, contributions and feedback are welcome. Please open an issue to discuss proposed changes.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cypherantic-0.0.1.tar.gz.
File metadata
- Download URL: cypherantic-0.0.1.tar.gz
- Upload date:
- Size: 69.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e1e315d6be2b6156ef88069fb661005943073590adc044f2ee46e761d05675b
|
|
| MD5 |
38457b0de7a30fc047b6c80f532f6c73
|
|
| BLAKE2b-256 |
bf38839b2cd8bd244ded23c840ea6c924c8ec39dfa849616c69368ffb5ddf14c
|
Provenance
The following attestation bundles were made for cypherantic-0.0.1.tar.gz:
Publisher:
publish.yml on dave-shawley/cypherantic
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cypherantic-0.0.1.tar.gz -
Subject digest:
0e1e315d6be2b6156ef88069fb661005943073590adc044f2ee46e761d05675b - Sigstore transparency entry: 910959922
- Sigstore integration time:
-
Permalink:
dave-shawley/cypherantic@6b42d3e190ca815eb96fdbeadf917ac4f4e5be96 -
Branch / Tag:
refs/tags/0.0.1 - Owner: https://github.com/dave-shawley
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6b42d3e190ca815eb96fdbeadf917ac4f4e5be96 -
Trigger Event:
release
-
Statement type:
File details
Details for the file cypherantic-0.0.1-py3-none-any.whl.
File metadata
- Download URL: cypherantic-0.0.1-py3-none-any.whl
- Upload date:
- Size: 8.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e546356579f259a3afd3d136604889c7537de3e1375d8c5c4d98e68f9f9347e9
|
|
| MD5 |
4007898ec8259cd2b3d2ad125b0abd40
|
|
| BLAKE2b-256 |
1e24dd91cd82b123ea26af27cf199470f977bc432f1aa69526c452e37e026cd3
|
Provenance
The following attestation bundles were made for cypherantic-0.0.1-py3-none-any.whl:
Publisher:
publish.yml on dave-shawley/cypherantic
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cypherantic-0.0.1-py3-none-any.whl -
Subject digest:
e546356579f259a3afd3d136604889c7537de3e1375d8c5c4d98e68f9f9347e9 - Sigstore transparency entry: 910959956
- Sigstore integration time:
-
Permalink:
dave-shawley/cypherantic@6b42d3e190ca815eb96fdbeadf917ac4f4e5be96 -
Branch / Tag:
refs/tags/0.0.1 - Owner: https://github.com/dave-shawley
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6b42d3e190ca815eb96fdbeadf917ac4f4e5be96 -
Trigger Event:
release
-
Statement type: