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 (persisting to a standard SQLite database file) and queried using the openCypher language.

It runs in-process and is designed for local, embedded, and edge use cases.

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.

For the main Velr public entry point, see velr-ai/velr.
For the Velr website, see velr.ai.

Community

We’d love to have you join the Velr community.


Release status

Velr is currently in public alpha.

  • The Python API and query support are still evolving.
  • openCypher coverage is already substantial, but some features are still missing.
  • During the 0.2.x series, we do not guarantee database migration or on-disk database compatibility between releases.
  • Starting with the 0.3.x series, we intend to guarantee internal database compatibility within the branch.

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

Velr 1.0 is focused on strong openCypher compatibility.
Vector search, time-series, and federation are planned as post-1.0 capabilities.


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'})")

Open an existing database for reads only:

from velr.driver import Velr

with Velr.open_readonly("mygraph.db") as db:
    with db.exec_one("MATCH (n) RETURN count(n) AS count") as table:
        print(table.collect(lambda row: [cell.as_python() for cell in row]))

open_readonly() never creates, initializes, migrates, or repairs a database. The file must already exist and have the current Velr schema version. Use Velr.open() from import and maintenance code when initialization or migration is intended.


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 current limitations:

  • Driver-level 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.2.11-cp313-cp313-win_amd64.whl (2.1 MB view details)

Uploaded CPython 3.13Windows x86-64

velr-0.2.11-cp313-cp313-manylinux_2_34_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

velr-0.2.11-cp313-cp313-manylinux_2_34_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ ARM64

velr-0.2.11-cp313-cp313-macosx_11_0_universal2.whl (2.0 MB view details)

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

velr-0.2.11-cp312-cp312-win_amd64.whl (2.1 MB view details)

Uploaded CPython 3.12Windows x86-64

velr-0.2.11-cp312-cp312-manylinux_2_34_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

velr-0.2.11-cp312-cp312-manylinux_2_34_aarch64.whl (2.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ ARM64

velr-0.2.11-cp312-cp312-macosx_11_0_universal2.whl (2.0 MB view details)

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

File details

Details for the file velr-0.2.11-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: velr-0.2.11-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 2.1 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for velr-0.2.11-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 3d49dca22c32c359c9c07c94604268597e7762e6ffea10560f34cd7e23380f37
MD5 cba594c23e9eeb00be979f8b00c732a5
BLAKE2b-256 e1c0813ed5707481ee7f2df52460a6f22a504287a1ce77c3b7cc32b6cc24a895

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-cp313-cp313-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.2.11-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for velr-0.2.11-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 0c3e69e1a285c2c4cb438497bd466ed4ee5284c31700d01ec6da43fe129f3e68
MD5 dae3b392c3c0e2e8d4a28fc122367a81
BLAKE2b-256 5b230ee92d47b9ba72910c672e38192bb673852e303071291f334b0b6f8f4c69

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-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.2.11-cp313-cp313-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for velr-0.2.11-cp313-cp313-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 50e5813c61254209365c41d570df1daef1225b0efd418ed1ec7fe1ae65ea4707
MD5 2a55d8737eb587a9d6b2bf0dee25715e
BLAKE2b-256 bb5c23ba8da15526cf11b235450050c501823ad7b8e9d96ade6ce1e840d1dc2c

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-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.2.11-cp313-cp313-macosx_11_0_universal2.whl.

File metadata

File hashes

Hashes for velr-0.2.11-cp313-cp313-macosx_11_0_universal2.whl
Algorithm Hash digest
SHA256 e8483695516ae67ffafd74cf0a480a5253048ef4a43e6190f9e5145f9a6b1f6f
MD5 c8529d9b906976f63822fdd71537fed5
BLAKE2b-256 8eeb69f03dccfe51525e826611539c830763d0eca534e693671910408d79684c

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-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.2.11-cp312-cp312-win_amd64.whl.

File metadata

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

File hashes

Hashes for velr-0.2.11-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 857b315dce2f83a682aceed33ca2d91a367585e2e7e1667bd20c14c7e5d82fa4
MD5 ff26c6e5b5e4e19ef84079011bf5c16c
BLAKE2b-256 6c978f0fbb63bf9f8be8ad50aa67aabedbab17317f2db0e09ba8f65433c680b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-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.2.11-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for velr-0.2.11-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 3d7fb4c2a3bc9a746921c102f3a8f9bce31e0f866a86351969d1dad8e7cbfe2f
MD5 df01961ebcd225cfa7da71df5a19d6e3
BLAKE2b-256 d74d563673d8a6e5eb183a4f482989a04c0b38da653523e10735e3fe68dc0ffd

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-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.2.11-cp312-cp312-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for velr-0.2.11-cp312-cp312-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 31a00940aba18e290e969f3fbf0d1b53c2df465c522a7c9847eb96d8309e9fa9
MD5 cf4089870d4a5bdc13978c31ca5f24e0
BLAKE2b-256 fd3bdb165383017f14ca17091c9828c6084823f840c75b6d190ca3e42d795c4b

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-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.2.11-cp312-cp312-macosx_11_0_universal2.whl.

File metadata

File hashes

Hashes for velr-0.2.11-cp312-cp312-macosx_11_0_universal2.whl
Algorithm Hash digest
SHA256 f0e7256b2a5c6de9046b1c3f4c3d2d2fd7f72bd6195794f07635a2f1a40384bd
MD5 10b0ba2c0b9074dcc59827fb05a49197
BLAKE2b-256 2fa33d32c1479a142ff5cf3af90c0aef2182300a5a9fdcb444fe6ee5acef546c

See more details on using hashes here.

Provenance

The following attestation bundles were made for velr-0.2.11-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