Skip to main content

Python bindings for Velr, an embedded openCypher graph database built on SQLite

Project description

Velr

Velr is an embedded property-graph database from Velr.ai, written in Rust, built on top of SQLite, and queried using the openCypher language.

It persists to a standard SQLite database file, runs in-process, and is designed for local, embedded, and edge use cases.

Vector data and time-series support are actively in development and will ship after openCypher support has stabilized.

This package provides the Python bindings for Velr. It wraps a bundled native runtime with a C ABI, implemented in Rust, and exposes a small, Pythonic API for executing Cypher queries, streaming result tables, working with transactions, and exporting results to Arrow, pandas, and Polars.

Questions, feedback, or commercial licensing: tomas@velr.ai


Release status

This release is alpha.

  • The Python API and query support are still evolving.
  • openCypher coverage is already substantial, but some features are still missing.

If you hit a missing feature, please reach out — that helps us prioritize.

Velr is already usable for real workflows and representative use cases, but rough edges remain and the API is not yet stable.


Installation

Install from PyPI:

pip install velr

For Arrow / dataframe workflows, install the optional Python dependencies you want to use:

pip install pyarrow pandas polars

Licensing in simple terms

  • The Python binding source code in this package is licensed under MIT.
  • The bundled native runtime binaries may be used and freely redistributed in unmodified form under the terms of LICENSE.runtime.

Quick start

from velr.driver import Velr

MOVIES_CREATE = r"""
CREATE
  (keanu:Person:Actor {name:'Keanu Reeves', born:1964}),
  (nolan:Person:Director {name:'Christopher Nolan'}),
  (matrix:Movie {title:'The Matrix', released:1999, genres:['Sci-Fi','Action']}),
  (inception:Movie {title:'Inception', released:2010, genres:['Sci-Fi','Heist']}),
  (keanu)-[:ACTED_IN {roles:['Neo']}]->(matrix),
  (nolan)-[:DIRECTED]->(inception);
"""

with Velr.open(None) as db:
    db.run(MOVIES_CREATE)

    with db.exec_one(
        "MATCH (m:Movie {title:'Inception'}) "
        "RETURN m.title AS title, m.released AS year, m.genres AS genres"
    ) as table:
        print(table.column_names())

        with table.rows() as rows:
            row = next(rows)

    title, year, genres = row
    print(title.as_python())
    print(year.as_python())
    print(genres.as_python())

Open a file-backed database instead of an in-memory database:

from velr.driver import Velr

with Velr.open("mygraph.db") as db:
    db.run("CREATE (:Person {name:'Alice'})")

Query model

A query may produce zero or more result tables.

Velr exposes three main ways to run Cypher:

  • run() executes a query or script and drains all result tables.
  • exec() returns a stream of result tables.
  • exec_one() expects exactly one result table.

run()

Use run() when you only care about side effects:

with Velr.open(None) as db:
    db.run("CREATE (:Movie {title:'Interstellar', released:2014})")

exec_one()

Use exec_one() when the query should yield exactly one table:

with Velr.open(None) as db:
    db.run("CREATE (:Person {name:'Alice', age:30})")

    with db.exec_one("MATCH (p:Person) RETURN p.name AS name, p.age AS age") as table:
        print(table.column_names())
        print(table.collect(lambda row: [cell.as_python() for cell in row]))

exec()

Use exec() when a query or script may produce multiple result tables:

with Velr.open(None) as db:
    db.run(MOVIES_CREATE)

    with db.exec(
        "MATCH (m:Movie {title:'The Matrix'}) RETURN m.title AS title; "
        "MATCH (m:Movie {title:'Inception'}) RETURN m.released AS released"
    ) as stream:
        for table in stream.iter_tables():
            print(table.column_names())
            print(table.collect(lambda row: [cell.as_python() for cell in row]))

Table lifetime and ownership

Table lifetime depends on how a table was obtained.

Tables from exec()

Tables pulled from exec() are stream-scoped.

They remain valid while the producing stream remains open, and closing the stream closes any still-open tables produced by that stream.

with db.exec("MATCH (n) RETURN n") as stream:
    table = stream.next_table()
    # table is valid here

# stream is now closed, so any still-open table from it is also closed

Tables from exec_one()

Tables returned by exec_one() are parent-scoped, not stream-scoped.

  • Velr.exec_one() returns a table parented to the connection.
  • VelrTx.exec_one() returns a table parented to the transaction.

That means the returned table remains usable after the internal stream logic used by exec_one() has finished.

Even so, tables should still be closed when no longer needed, ideally by using them as context managers.


Rows and cells

Rows are exposed through Rows. Each yielded row is a tuple of Cell objects.

Cell.as_python() converts values to normal Python objects:

  • NULLNone
  • BOOLbool
  • INT64int
  • DOUBLEfloat
  • TEXTstr by default
  • JSONstr by default, or parsed Python objects with parse_json=True

Example:

with db.exec_one("MATCH (p:Person) RETURN p.name AS name, p.age AS age") as table:
    with table.rows() as rows:
        for row in rows:
            print(row[0].as_python(), row[1].as_python())

For convenience and safety, TEXT and JSON payloads are copied into Python bytes as rows are read, so row contents remain valid after the next fetch.


Transactions and savepoints

Use begin_tx() to open a transaction:

from velr.driver import Velr

with Velr.open(None) as db:
    with db.begin_tx() as tx:
        tx.run("CREATE (:Movie {title:'Interstellar', released:2014})")
        tx.commit()

If a transaction context exits without commit(), it is rolled back.

After commit() or rollback(), a transaction can no longer be used.

Savepoints

Velr supports two savepoint styles:

  • savepoint() creates a scoped, handle-owned savepoint.
  • savepoint_named(name) creates a transaction-owned named savepoint.

Scoped savepoints are owned by the Python handle:

  • dropping the handle closes the savepoint
  • release() releases it
  • rollback() rolls back to it and releases it

Named savepoints are owned by the transaction:

  • dropping the returned Python handle does not remove the named savepoint
  • rollback_to(name) rolls back to that named savepoint, discards any newer named savepoints, and keeps the target named savepoint active
  • release_savepoint(name) releases a named savepoint by name; the named savepoint must be the most recent active named savepoint
  • release() or rollback() on a named savepoint handle consume that named savepoint

Active named savepoints are released automatically during commit() so that surviving changes are preserved in the committed transaction.

Example:

with Velr.open(None) as db:
    with db.begin_tx() as tx:
        tx.run("CREATE (:Temp {k:'outer'})")

        tx.savepoint_named("sp1")
        tx.run("CREATE (:Temp {k:'a'})")

        tx.savepoint_named("sp2")
        tx.run("CREATE (:Temp {k:'b'})")

        tx.rollback_to("sp1")  # undoes a and b, drops sp2, keeps sp1 active
        tx.run("CREATE (:Temp {k:'c'})")

        tx.release_savepoint("sp1")
        tx.commit()

pandas / Polars / PyArrow interop

Velr can export result tables as Arrow IPC and convert them into:

  • pyarrow.Table
  • pandas.DataFrame
  • polars.DataFrame

pandas

with Velr.open(None) as db:
    db.run(MOVIES_CREATE)

    df = db.to_pandas(
        "MATCH (m:Movie) "
        "RETURN m.title AS title, m.released AS released "
        "ORDER BY released"
    )
    print(df)

Polars

with Velr.open(None) as db:
    db.run(MOVIES_CREATE)

    df = db.to_polars(
        "MATCH (m:Movie) "
        "RETURN m.title AS title, m.released AS released "
        "ORDER BY released"
    )
    print(df)

PyArrow

with Velr.open(None) as db:
    db.run(MOVIES_CREATE)

    tbl = db.to_pyarrow(
        "MATCH (m:Movie) "
        "RETURN m.title AS title, m.released AS released "
        "ORDER BY released"
    )
    print(tbl)

Export from an existing table

with db.exec_one("MATCH (m:Movie) RETURN m.title AS title") as table:
    pa_tbl = table.to_pyarrow()
    df = table.to_pandas()
    pl_df = table.to_polars()

Binding Arrow, pandas, Polars, NumPy, and records

Velr can also bind external columnar data under a logical name and query it from Cypher.

Supported bind helpers include:

  • bind_arrow()
  • bind_pandas()
  • bind_polars()
  • bind_numpy()
  • bind_records()

Bind a pandas DataFrame

import pandas as pd
from velr.driver import Velr

df = pd.DataFrame(
    [
        {"name": "Alice", "age": 30},
        {"name": "Bob", "age": 41},
    ]
)

with Velr.open(None) as db:
    db.bind_pandas("_people", df)

    db.run("""
    UNWIND BIND('_people') AS r
    CREATE (:Person {name:r.name, age:r.age})
    """)

    out = db.to_pandas("MATCH (p:Person) RETURN p.name AS name, p.age AS age ORDER BY age")
    print(out)

Bind a list of dicts

rows = [
    {"name": "Alice", "age": 30},
    {"name": "Bob", "age": 41},
]

with Velr.open(None) as db:
    db.bind_records("_people", rows)
    db.run("""
    UNWIND BIND('_people') AS r
    CREATE (:Person {name:r.name, age:r.age})
    """)

Explain support

Velr exposes explain traces through:

  • Velr.explain()
  • Velr.explain_analyze()
  • VelrTx.explain()
  • VelrTx.explain_analyze()

These return an ExplainTrace, which can be navigated incrementally or fully materialized with snapshot().

with Velr.open(None) as db:
    with db.explain("MATCH (p:Person) RETURN p.name AS name") as xp:
        print(xp.to_compact_string())

Query language support

Velr supports most of openCypher, but some features are not yet implemented.

Notable missing features:

  • REMOVE clause
  • Query parameters (for example $name)
  • The query planner does not yet use indexes in all cases where expected.

Supported functions

Velr currently supports these openCypher functions:

Scalars

  • id()
  • type()
  • length()
  • nodes()
  • relationships()
  • coalesce()
  • labels()
  • properties()
  • keys()

Aggregates

  • count()
  • sum()
  • avg()
  • min()
  • max()
  • collect()

Thread safety

Velr connections and active result handles are not safe for concurrent use from multiple threads.

If you need parallelism:

  • open one connection per thread
  • do not share active connections
  • do not share transactions, streams, tables, row iterators, or explain traces across threads

Platform support

The Python package wraps a bundled native runtime implemented in Rust.

Supported distributions may include prebuilt binary wheels for common platforms. Where binary wheels are available, the compiled runtime is included with the package.

Currently bundled targets:

* macOS (arm64)
* Linux x86_64
* Linux aarch64
* Windows x86_64

License

See LICENSE and LICENSE.runtime for the full license texts.

Project details


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 Distributions

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

velr-0.1.66-cp313-cp313-manylinux_2_34_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

velr-0.1.66-cp313-cp313-manylinux_2_34_aarch64.whl (1.7 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ ARM64

velr-0.1.66-cp313-cp313-macosx_11_0_universal2.whl (1.5 MB view details)

Uploaded CPython 3.13macOS 11.0+ universal2 (ARM64, x86-64)

velr-0.1.66-cp312-cp312-win_amd64.whl (1.5 MB view details)

Uploaded CPython 3.12Windows x86-64

velr-0.1.66-cp312-cp312-manylinux_2_34_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

velr-0.1.66-cp312-cp312-manylinux_2_34_aarch64.whl (1.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ ARM64

velr-0.1.66-cp312-cp312-macosx_11_0_universal2.whl (1.5 MB view details)

Uploaded CPython 3.12macOS 11.0+ universal2 (ARM64, x86-64)

File details

Details for the file velr-0.1.66-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for velr-0.1.66-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 cec1ad4b1b524af1618432c9b0b484ff03677c10f7df5392995b591147251b4d
MD5 0e93df37c504d757e304a0ea714b37ba
BLAKE2b-256 a79d95930e7c030a0154d63e5aab4cda6f65f4ef12b4f41235db5dc27ac2158f

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.1.66-cp313-cp313-manylinux_2_34_x86_64.whl:

Publisher: publish-pypi.yml on velr-ai/velr-repo

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

File details

Details for the file velr-0.1.66-cp313-cp313-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for velr-0.1.66-cp313-cp313-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 10976c107f6ab8bd87f572b9b48b9714d99c525fdeef6c3deb86cb6f573ff1c5
MD5 1779ba76e9b85e6392f1f83522888501
BLAKE2b-256 44b3be3a9d20d212416c77cd29ccb9a19b4fad7688f3f61e89df1bff0c271fab

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.1.66-cp313-cp313-manylinux_2_34_aarch64.whl:

Publisher: publish-pypi.yml on velr-ai/velr-repo

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

File details

Details for the file velr-0.1.66-cp313-cp313-macosx_11_0_universal2.whl.

File metadata

File hashes

Hashes for velr-0.1.66-cp313-cp313-macosx_11_0_universal2.whl
Algorithm Hash digest
SHA256 d1cb5776ce46eb6ad844414c04987aecd48dd27aace60872a20e055d4b960eeb
MD5 d556d2817d165f635497537969e0a0a2
BLAKE2b-256 d84446718d719e7a31df27918a53c93d840c2f6367cee4079635a5c9203508d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.1.66-cp313-cp313-macosx_11_0_universal2.whl:

Publisher: publish-pypi.yml on velr-ai/velr-repo

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

File details

Details for the file velr-0.1.66-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: velr-0.1.66-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for velr-0.1.66-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 b46951ea67a1071bb5ae0131b7d3db2cd362355817228b652ebbc8abd55d9cf4
MD5 55e06fa2acc4383de13c40292b425351
BLAKE2b-256 d37e6999b669b585a7df3bf8085b418f938bbc34f6a3b77be26b484d1656e93b

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.1.66-cp312-cp312-win_amd64.whl:

Publisher: publish-pypi.yml on velr-ai/velr-repo

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

File details

Details for the file velr-0.1.66-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for velr-0.1.66-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 4906abcf67dc5c0b093244736cf704ddb9360fe80ffc0420f03aa11d44e602e9
MD5 1b680cd844bd9a4ed76a3e38f9ada786
BLAKE2b-256 91e079c7c6356f1e7db0a0bb0807233d28bd79381a7bc550becda3d88a16bef2

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.1.66-cp312-cp312-manylinux_2_34_x86_64.whl:

Publisher: publish-pypi.yml on velr-ai/velr-repo

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

File details

Details for the file velr-0.1.66-cp312-cp312-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for velr-0.1.66-cp312-cp312-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 1cfaaffecc1177de2b1dd9aa23cf3ea819716beec55840fa04ce049720402d6f
MD5 fab86b345262320150e0ebf6118238f5
BLAKE2b-256 573658d11c7dbfa15c1f47436e5b0522de78244039664fe20c1bdad7f71a0a97

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.1.66-cp312-cp312-manylinux_2_34_aarch64.whl:

Publisher: publish-pypi.yml on velr-ai/velr-repo

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

File details

Details for the file velr-0.1.66-cp312-cp312-macosx_11_0_universal2.whl.

File metadata

File hashes

Hashes for velr-0.1.66-cp312-cp312-macosx_11_0_universal2.whl
Algorithm Hash digest
SHA256 ea787a6ef94bacf7862bc378cfcc6b05b7f3c679f93f72a158b40a7c97e5d2a8
MD5 82eb61cabadaa937639d65219e576ed5
BLAKE2b-256 0aaf32321c45a3e7e8274f8de8558deac311a046036d3ad60a3fd1f088b1808a

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.1.66-cp312-cp312-macosx_11_0_universal2.whl:

Publisher: publish-pypi.yml on velr-ai/velr-repo

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