Skip to main content

Embed the Drasi continuous-query engine directly in your Python application

Project description

drasi-lib

Embed the Drasi continuous-query engine directly in your Python application. drasi-lib is a native PyO3 binding around Drasi's embeddable engine (drasi-lib) and its plugin host SDK (drasi-host-sdk), so you get:

  • In-process continuous queries over a property graph, in Cypher or GQL.
  • A working plugin ecosystem — search, resolve, download, verify and install the Drasi source/reaction/bootstrap plugins published to ghcr.io/drasi-project, picking the build that is compatible with your host.
  • Python-defined components — define a reaction as a Python callback, or a source you push changes into from your own code. No Rust required.
  • Streamingasync for event in drasi.query_results(id), plus lifecycle events and component logs.
  • A blocking APIdrasi.sync.Drasi for scripts and notebooks.

Status: pre-1.0, not yet on PyPI. The API is complete — full parity with @drasi/lib plus streaming as async iterators, a blocking facade, and plugin lockfiles. See docs/api-audit.md.

Install

Not published to PyPI yet. Build it from source — see Development, or examples/README.md for a step-by-step walkthrough.

pip install drasi-lib   # once released

Quickstart

Push changes from your own code and react to the results — no plugins needed:

import asyncio
from drasi import Drasi


async def main() -> None:
    async with await Drasi.create("my-app") as drasi:
        await drasi.start()

        await drasi.add_python_source("orders")
        await drasi.add_query(
            "open",
            "MATCH (o:Order) WHERE o.status = 'open' RETURN o.id AS id, o.total AS total",
            ["orders"],
        )

        def on_results(event):
            for diff in event["results"]:
                print(diff["type"], diff.get("data"))

        await drasi.add_python_reaction("watch", ["open"], on_results)

        await drasi.push_change(
            "orders",
            {
                "op": "insert",
                "id": "o1",
                "labels": ["Order"],
                "properties": {"id": "o1", "status": "open", "total": 42},
            },
        )
        await asyncio.sleep(0.5)
        print(await drasi.get_query_results("open"))


asyncio.run(main())

Three things that are easy to get wrong:

  • Call start() first, then add components; they auto-start individually. Adding everything and then calling start() also works, but logs a spurious "already running" error for each component.
  • Drasi's Cypher dialect uses single-quoted string literals.
  • A change's id is the graph key, not a property. A query selecting o.id reads a property of that name, so emit it explicitly.

add_query returns once the query is provisioned; it finishes starting in the background, so reading results immediately can raise "is not running". Await wait_for_query(id) if you need to read straight away.

Using a plugin

install_plugin() resolves the build that is compatible with your machine, downloads it, verifies it and loads it:

async with await Drasi.create("my-app") as drasi:
    await drasi.install_plugin("source/mock")
    await drasi.start()

    await drasi.add_source("mock", "counters", {"dataType": {"type": "counter"}, "intervalMs": 500})
    await drasi.add_query("counts", "MATCH (c:Counter) RETURN c.value AS value", ["counters"])

Browse what is available first, if you like:

for plugin in await drasi.search_plugins():
    print(plugin["reference"])  # e.g. source/postgres, reaction/http

Plugin configuration keys are defined by the plugin itself, so they are passed through untouched — dataType above is the mock source's own spelling. Drasi's own API is snake_case, and accepts the Node.js camelCase spellings as aliases.

Plugins

Drasi plugins are self-contained cdylib files distributed as OCI artifacts from ghcr.io/drasi-project, published per platform:

ghcr.io/drasi-project/{type}/{kind}:{version}-{arch}

Because a plugin is a native library loaded into your process, it is only usable by a host built against a compatible set of Drasi crates. install_plugin() handles this for you — it reads the registry index, picks the newest build whose sdk/core/lib versions and target triple match this host, downloads it, optionally verifies its cosign signature, and loads it.

See docs/plugins.md.

Watching a query

Polling is rarely what you want:

async for event in await drasi.query_results("open"):
    for diff in event["results"]:
        print(diff["type"], diff.get("data"))

Lifecycle events (query_events, source_events, reaction_events, all_events) and logs (query_logs, source_logs, reaction_logs) stream the same way, and replay their history first. Callback forms (on_query_results, on_*_events, on_*_logs) exist for parity with the Node.js binding.

Without async

from drasi.sync import Drasi

with Drasi.create("my-app") as drasi:
    drasi.start()
    drasi.add_python_source("orders")
    print(drasi.get_query_results("open"))

Streams become ordinary iterators. Don't use this inside an existing event loop — it will tell you so rather than deadlocking.

Durability

A durable reaction only advances its checkpoint once your callback succeeds, so an unhandled event is replayed after a restart:

drasi = await Drasi.create("app", state_store={"kind": "redb", "path": "state.redb"})


async def handle(event):
    await write_somewhere(event)  # if this raises, the event is retried


await drasi.add_durable_python_reaction("sink", ["open"], handle)

Status

docs/api-audit.md inventories the public API and compares it against the Node.js bindings and the Rust engine. It is at full parity — 48/48 methods — plus 21 methods Node does not have.

Examples

Runnable programs are in examples/, with a guide covering how to build the package locally and run them:

Example What it shows Needs
python_source.py Push changes from your own code; react to results nothing
install_plugin.py Browse the registry, install a plugin, use it network
postgres_cdc.py React to a real Postgres database Docker, network
make venv && make develop
.venv/bin/python examples/python_source.py

Development

make venv        # create .venv with a managed Python and the dev tooling
make develop     # build the native extension and install it editable
make test        # unit tests + hermetic end-to-end tests
make test-oci    # download and install real plugins from ghcr.io

Building requires a Rust toolchain. The optional rocksdb feature additionally requires libclang and a C++ toolchain. See CONTRIBUTING.md.

License

Apache-2.0. See LICENSE.

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

drasi_lib-0.1.0.tar.gz (147.8 kB view details)

Uploaded Source

Built Distributions

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

drasi_lib-0.1.0-cp310-abi3-win_amd64.whl (10.1 MB view details)

Uploaded CPython 3.10+Windows x86-64

drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_x86_64.whl (10.6 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.35+ x86-64

drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_aarch64.whl (10.0 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.35+ ARM64

drasi_lib-0.1.0-cp310-abi3-macosx_11_0_arm64.whl (8.9 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

drasi_lib-0.1.0-cp310-abi3-macosx_10_13_x86_64.whl (9.6 MB view details)

Uploaded CPython 3.10+macOS 10.13+ x86-64

File details

Details for the file drasi_lib-0.1.0.tar.gz.

File metadata

  • Download URL: drasi_lib-0.1.0.tar.gz
  • Upload date:
  • Size: 147.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for drasi_lib-0.1.0.tar.gz
Algorithm Hash digest
SHA256 8d3206f8c33efd891c4e2e404d18486f1ddab6690873a17b97d7e465eaa1a34c
MD5 10210f9e76600d5fd04579bf2c2e5483
BLAKE2b-256 ba888a3fd46d1e3ccfa84b895b0b4fdd1097a2145ab44280e90471cccd125e41

See more details on using hashes here.

Provenance

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

Publisher: release.yml on drasi-project/drasi-python

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

File details

Details for the file drasi_lib-0.1.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: drasi_lib-0.1.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 10.1 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for drasi_lib-0.1.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 d49d9d87b922d607e4614265af94dbe502d604dd792e26d98eab21f741e26107
MD5 2def729cc9c9e1f70358c9cc705076f2
BLAKE2b-256 b02f9a2343d345a2b050e04ed7dc072ae662963bb85d01a970fb511364a60c54

See more details on using hashes here.

Provenance

The following attestation bundles were made for drasi_lib-0.1.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on drasi-project/drasi-python

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

File details

Details for the file drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 863dd0e0f71a5504981387cb6222ec34bb70eda2c61bdd0fbb73c674aed0c4e3
MD5 13ac770a1c9b55ec968433af1a46e4c0
BLAKE2b-256 dd50be734c81ccc9258a1fd6338177e21015d263fe138c5241d8c114ac0a70b3

See more details on using hashes here.

Provenance

The following attestation bundles were made for drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_x86_64.whl:

Publisher: release.yml on drasi-project/drasi-python

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

File details

Details for the file drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_aarch64.whl.

File metadata

File hashes

Hashes for drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_aarch64.whl
Algorithm Hash digest
SHA256 a0678943a46dff9debc2b390e9ea79696adb91cb5f8527bd59a3cac10cb92563
MD5 90bf326b266cb774927c5976f872f311
BLAKE2b-256 8d819b6ad0f66ace00aa4bd72176d31dfaa52df9861a2d87dee5e035dcba0382

See more details on using hashes here.

Provenance

The following attestation bundles were made for drasi_lib-0.1.0-cp310-abi3-manylinux_2_35_aarch64.whl:

Publisher: release.yml on drasi-project/drasi-python

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

File details

Details for the file drasi_lib-0.1.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for drasi_lib-0.1.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 95c9fe9e2ebb6f4cbcede1532a6003ecb45baef17f71d4787c9a125799402b25
MD5 cd52a704dd969581d3f97d2e487fe423
BLAKE2b-256 0f4d90d5b08bc028fbf230e744b264009e7e870048aa49858030a7a47c70fd40

See more details on using hashes here.

Provenance

The following attestation bundles were made for drasi_lib-0.1.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on drasi-project/drasi-python

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

File details

Details for the file drasi_lib-0.1.0-cp310-abi3-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for drasi_lib-0.1.0-cp310-abi3-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 7c52064f812fca46437945b18a5b9581446a4b56ac8a013e9bd18410a4261007
MD5 b907dd84bc5e3d109693af97bcf31137
BLAKE2b-256 c55313c63be99837c9e6a66acbe049d833dfc0d8a942b1b97aa09563083ad0ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for drasi_lib-0.1.0-cp310-abi3-macosx_10_13_x86_64.whl:

Publisher: release.yml on drasi-project/drasi-python

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