From d42ad2d805e4d3e662748420b9879fa099d05e0a Mon Sep 17 00:00:00 2001 From: beinan Date: Wed, 15 Oct 2025 21:41:49 +0000 Subject: [PATCH 1/7] examples(python): add basic Cypher and KG traversal examples - Add python/examples/basic_cypher.py (filter + projection) - Add python/examples/kg_traversal.py (two-hop traversal) - Add python/examples/README.md with setup and run instructions - Link examples from rust/lance-graph/README.md --- python/examples/README.md | 27 +++++++++++++ python/examples/basic_cypher.py | 53 ++++++++++++++++++++++++++ python/examples/kg_traversal.py | 67 +++++++++++++++++++++++++++++++++ rust/lance-graph/README.md | 15 ++++++++ 4 files changed, 162 insertions(+) create mode 100644 python/examples/README.md create mode 100644 python/examples/basic_cypher.py create mode 100644 python/examples/kg_traversal.py diff --git a/python/examples/README.md b/python/examples/README.md new file mode 100644 index 00000000..0706954e --- /dev/null +++ b/python/examples/README.md @@ -0,0 +1,27 @@ +# Python Examples for lance-graph + +## Setup + +From repo root, build/install the Python bindings for development: + +```bash +maturin develop -m python/Cargo.toml +``` + +Ensure Python has `pyarrow` available (e.g., `pip install pyarrow`). + +## Examples + +- `basic_cypher.py`: simple node filter and projection. + +```bash +python python/examples/basic_cypher.py +``` + +- `kg_traversal.py`: multi-hop traversal on a small synthetic knowledge graph. + +```bash +python python/examples/kg_traversal.py +``` + + diff --git a/python/examples/basic_cypher.py b/python/examples/basic_cypher.py new file mode 100644 index 00000000..165f7754 --- /dev/null +++ b/python/examples/basic_cypher.py @@ -0,0 +1,53 @@ +""" +Basic Cypher graph query using the lance-graph Python bindings. + +Requirements: +- Build/install the Python extension first (from repo root): + maturin develop -m python/Cargo.toml +- Python deps: pyarrow + +Run: + python python/examples/basic_cypher.py +""" + +from __future__ import annotations + +import pyarrow as pa + +from lance_graph import GraphConfigBuilder, CypherQuery + + +def make_people_batch() -> pa.RecordBatch: + return pa.record_batch( + [ + pa.array([1, 2, 3, 4, 5], type=pa.int32()), + pa.array(["Alice", "Bob", "Carol", "David", "Eve"], type=pa.string()), + pa.array([28, 34, 29, 42, 31], type=pa.int32()), + ], + names=["person_id", "name", "age"], + ) + + +def main() -> None: + config = ( + GraphConfigBuilder() + .with_node_label("Person", "person_id") + .build() + ) + + query = ( + CypherQuery("MATCH (n:Person) WHERE n.age > 30 RETURN n.name") + .with_config(config) + ) + + datasets = {"Person": make_people_batch()} + result = query.execute(datasets) + + # Convert to a simple Python dict for display + print(result.to_pydict()) + + +if __name__ == "__main__": + main() + + diff --git a/python/examples/kg_traversal.py b/python/examples/kg_traversal.py new file mode 100644 index 00000000..f2284ce7 --- /dev/null +++ b/python/examples/kg_traversal.py @@ -0,0 +1,67 @@ +""" +Simple knowledge-graph multi-hop traversal with lance-graph Python bindings. + +Requirements: +- Build/install the Python extension first (from repo root): + maturin develop -m python/Cargo.toml +- Python deps: pyarrow + +Run: + python python/examples/kg_traversal.py +""" + +from __future__ import annotations + +import pyarrow as pa + +from lance_graph import GraphConfigBuilder, CypherQuery + + +def make_people_batch(n: int = 6) -> pa.RecordBatch: + return pa.record_batch( + [ + pa.array(list(range(1, n + 1)), type=pa.int32()), + pa.array([f"P{i}" for i in range(1, n + 1)], type=pa.string()), + ], + names=["person_id", "name"], + ) + + +def make_friendship_batch(n: int = 6) -> pa.RecordBatch: + # Create a simple ring: 1->2->3->...->n->1 + src = list(range(1, n + 1)) + dst = [i + 1 if i < n else 1 for i in src] + return pa.record_batch( + [pa.array(src, type=pa.int32()), pa.array(dst, type=pa.int32())], + names=["person1_id", "person2_id"], + ) + + +def main() -> None: + config = ( + GraphConfigBuilder() + .with_node_label("Person", "person_id") + .with_relationship("FRIEND_OF", "person1_id", "person2_id") + .build() + ) + + # Two-hop traversal from a person to friend-of-a-friend + query = ( + CypherQuery( + "MATCH (a:Person)-[:FRIEND_OF]->(b:Person)-[:FRIEND_OF]->(c:Person) RETURN a.name, c.name" + ) + .with_config(config) + ) + + datasets = { + "Person": make_people_batch(), + "FRIEND_OF": make_friendship_batch(), + } + result = query.execute(datasets) + print(result.to_pydict()) + + +if __name__ == "__main__": + main() + + diff --git a/rust/lance-graph/README.md b/rust/lance-graph/README.md index 137a5311..bd456cdc 100644 --- a/rust/lance-graph/README.md +++ b/rust/lance-graph/README.md @@ -164,6 +164,21 @@ Numbers are illustrative; your hardware, compiler, and runtime load will affect Python bindings for this crate live under `python/src/graph.rs` and expose the same configuration and query APIs via PyO3. +### Python Examples + +See `python/examples` for runnable Python examples: + +- `basic_cypher.py`: simple node filter and projection against in-memory Arrow batches. +- `kg_traversal.py`: two-hop traversal on a small synthetic knowledge graph. + +Setup and run (from repo root): + +```bash +maturin develop -m python/Cargo.toml +python python/examples/basic_cypher.py +python python/examples/kg_traversal.py +``` + ## License Apache-2.0. See the top-level LICENSE file for details. From 1cd9e53920fd41e50d53a528a649164b08a63d20 Mon Sep 17 00:00:00 2001 From: beinan Date: Wed, 15 Oct 2025 21:43:33 +0000 Subject: [PATCH 2/7] chore(examples): move Python examples to top-level examples/ and update docs - Move basic_cypher.py, kg_traversal.py, and README to examples/ - Update rust/lance-graph/README.md links and run commands --- {python/examples => examples}/README.md | 6 +++--- {python/examples => examples}/basic_cypher.py | 0 {python/examples => examples}/kg_traversal.py | 0 rust/lance-graph/README.md | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) rename {python/examples => examples}/README.md (77%) rename {python/examples => examples}/basic_cypher.py (100%) rename {python/examples => examples}/kg_traversal.py (100%) diff --git a/python/examples/README.md b/examples/README.md similarity index 77% rename from python/examples/README.md rename to examples/README.md index 0706954e..9142957f 100644 --- a/python/examples/README.md +++ b/examples/README.md @@ -1,4 +1,4 @@ -# Python Examples for lance-graph +# Examples for lance-graph ## Setup @@ -15,13 +15,13 @@ Ensure Python has `pyarrow` available (e.g., `pip install pyarrow`). - `basic_cypher.py`: simple node filter and projection. ```bash -python python/examples/basic_cypher.py +python examples/basic_cypher.py ``` - `kg_traversal.py`: multi-hop traversal on a small synthetic knowledge graph. ```bash -python python/examples/kg_traversal.py +python examples/kg_traversal.py ``` diff --git a/python/examples/basic_cypher.py b/examples/basic_cypher.py similarity index 100% rename from python/examples/basic_cypher.py rename to examples/basic_cypher.py diff --git a/python/examples/kg_traversal.py b/examples/kg_traversal.py similarity index 100% rename from python/examples/kg_traversal.py rename to examples/kg_traversal.py diff --git a/rust/lance-graph/README.md b/rust/lance-graph/README.md index bd456cdc..ee15bd7d 100644 --- a/rust/lance-graph/README.md +++ b/rust/lance-graph/README.md @@ -166,7 +166,7 @@ Python bindings for this crate live under `python/src/graph.rs` and expose the s ### Python Examples -See `python/examples` for runnable Python examples: +See top-level `examples/` for runnable Python examples: - `basic_cypher.py`: simple node filter and projection against in-memory Arrow batches. - `kg_traversal.py`: two-hop traversal on a small synthetic knowledge graph. @@ -175,8 +175,8 @@ Setup and run (from repo root): ```bash maturin develop -m python/Cargo.toml -python python/examples/basic_cypher.py -python python/examples/kg_traversal.py +python examples/basic_cypher.py +python examples/kg_traversal.py ``` ## License From de14e687b8acced948665b51c985878bed87b574 Mon Sep 17 00:00:00 2001 From: beinan Date: Wed, 15 Oct 2025 21:47:27 +0000 Subject: [PATCH 3/7] docs(examples): fix run command paths after moving to top-level --- examples/basic_cypher.py | 4 +--- examples/kg_traversal.py | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/basic_cypher.py b/examples/basic_cypher.py index 165f7754..33db1c63 100644 --- a/examples/basic_cypher.py +++ b/examples/basic_cypher.py @@ -7,7 +7,7 @@ - Python deps: pyarrow Run: - python python/examples/basic_cypher.py + python examples/basic_cypher.py """ from __future__ import annotations @@ -49,5 +49,3 @@ def main() -> None: if __name__ == "__main__": main() - - diff --git a/examples/kg_traversal.py b/examples/kg_traversal.py index f2284ce7..7b2215b5 100644 --- a/examples/kg_traversal.py +++ b/examples/kg_traversal.py @@ -7,7 +7,7 @@ - Python deps: pyarrow Run: - python python/examples/kg_traversal.py + python examples/kg_traversal.py """ from __future__ import annotations @@ -63,5 +63,3 @@ def main() -> None: if __name__ == "__main__": main() - - From 5bb691b769217783b39885e7c62e38d2a8c7527b Mon Sep 17 00:00:00 2001 From: beinan Date: Wed, 15 Oct 2025 21:57:33 +0000 Subject: [PATCH 4/7] docs(examples): add uv run instructions for building and running examples --- examples/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/README.md b/examples/README.md index 9142957f..2cda2788 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,6 +10,19 @@ maturin develop -m python/Cargo.toml Ensure Python has `pyarrow` available (e.g., `pip install pyarrow`). +### Run with uv (optional) + +If you prefer `uv` for isolation without global installs: + +```bash +# Build/install the Python bindings (editable) using uvx + maturin +uvx --from maturin maturin develop -m python/Cargo.toml + +# Run examples with uv; point PYTHONPATH to the source package +PYTHONPATH=python/python uv run --with pyarrow python examples/basic_cypher.py +PYTHONPATH=python/python uv run --with pyarrow python examples/kg_traversal.py +``` + ## Examples - `basic_cypher.py`: simple node filter and projection. From 86b040fc863ac6c1bbdd5d615b365de90661915e Mon Sep 17 00:00:00 2001 From: beinan Date: Wed, 15 Oct 2025 22:29:08 +0000 Subject: [PATCH 5/7] docs(examples): document two run approaches (local build via maturin, and install) - examples/README: add local build and install flows, plus uv variants - rust README: mirror uv/local build flows in Python Examples section --- examples/README.md | 43 +++++++++++++++++++++++++++----------- rust/lance-graph/README.md | 12 +++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/examples/README.md b/examples/README.md index 2cda2788..e6ea2c25 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,26 +1,47 @@ # Examples for lance-graph -## Setup +## How to Run Examples -From repo root, build/install the Python bindings for development: +Pick one of the two approaches: + +### 1) Local build (editable) with maturin ```bash +# From the repo root; installs the Python extension in editable mode maturin develop -m python/Cargo.toml + +# Run examples +python examples/basic_cypher.py +python examples/kg_traversal.py ``` -Ensure Python has `pyarrow` available (e.g., `pip install pyarrow`). +With `uv`: + +```bash +# Build/install using uv +uvx --from maturin maturin develop -m python/Cargo.toml -### Run with uv (optional) +# Run examples (uv provides pyarrow; no PYTHONPATH needed after develop) +uv run --with pyarrow python examples/basic_cypher.py +uv run --with pyarrow python examples/kg_traversal.py +``` -If you prefer `uv` for isolation without global installs: +### 2) Install the package, then run + +- From PyPI (when published): ```bash -# Build/install the Python bindings (editable) using uvx + maturin -uvx --from maturin maturin develop -m python/Cargo.toml +pip install lance-graph pyarrow +python examples/basic_cypher.py +python examples/kg_traversal.py +``` -# Run examples with uv; point PYTHONPATH to the source package -PYTHONPATH=python/python uv run --with pyarrow python examples/basic_cypher.py -PYTHONPATH=python/python uv run --with pyarrow python examples/kg_traversal.py +- From git (editable): + +```bash +pip install -e python +python examples/basic_cypher.py +python examples/kg_traversal.py ``` ## Examples @@ -36,5 +57,3 @@ python examples/basic_cypher.py ```bash python examples/kg_traversal.py ``` - - diff --git a/rust/lance-graph/README.md b/rust/lance-graph/README.md index ee15bd7d..757e59d1 100644 --- a/rust/lance-graph/README.md +++ b/rust/lance-graph/README.md @@ -173,12 +173,24 @@ See top-level `examples/` for runnable Python examples: Setup and run (from repo root): +```bash +Option A - Local build (editable): + ```bash maturin develop -m python/Cargo.toml python examples/basic_cypher.py python examples/kg_traversal.py ``` +Option B - Using uv: + +```bash +uvx --from maturin maturin develop -m python/Cargo.toml +uv run --with pyarrow python examples/basic_cypher.py +uv run --with pyarrow python examples/kg_traversal.py +``` +``` + ## License Apache-2.0. See the top-level LICENSE file for details. From e2581b5967d7bfba04c6e5bfefc8d8d0b9603766 Mon Sep 17 00:00:00 2001 From: beinan Date: Wed, 15 Oct 2025 22:35:27 +0000 Subject: [PATCH 6/7] build(python): silence dead_code warnings in BackgroundExecutor methods --- python/src/executor.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/src/executor.rs b/python/src/executor.rs index d4be02d8..affd4be6 100644 --- a/python/src/executor.rs +++ b/python/src/executor.rs @@ -31,6 +31,7 @@ pub struct BackgroundExecutor { } impl BackgroundExecutor { + #[allow(dead_code)] pub fn get_runtime_handle(&self) -> Option { Some(self.runtime.handle().clone()) } @@ -50,6 +51,7 @@ impl BackgroundExecutor { /// /// This method is safe to use with inputs that may reference a Rust async /// runtime. + #[allow(dead_code)] pub fn spawn(&self, py: Option>, task: T) -> PyResult where T: Future + Send + 'static, @@ -63,6 +65,7 @@ impl BackgroundExecutor { } } + #[allow(dead_code)] fn spawn_impl(&self, task: T) -> PyResult where T: Future + Send + 'static, @@ -103,6 +106,7 @@ impl BackgroundExecutor { } /// Spawn a task in the background + #[allow(dead_code)] pub fn spawn_background(&self, py: Option>, task: T) where T: Future + Send + 'static, From cba6cdf819b3076d1af6e23b9e5714603eb467d2 Mon Sep 17 00:00:00 2001 From: beinan Date: Thu, 16 Oct 2025 00:17:48 +0000 Subject: [PATCH 7/7] docs(examples): clarify pyarrow install, uv ephemeral envs, and add venv + PYTHONPATH options --- examples/README.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/examples/README.md b/examples/README.md index e6ea2c25..b5d72502 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,6 +8,7 @@ Pick one of the two approaches: ```bash # From the repo root; installs the Python extension in editable mode +pip install pyarrow # or: uv pip install pyarrow maturin develop -m python/Cargo.toml # Run examples @@ -15,15 +16,19 @@ python examples/basic_cypher.py python examples/kg_traversal.py ``` -With `uv`: +With `uv` (persistent venv recommended): ```bash -# Build/install using uv +# Create and activate a reusable environment +uv venv .venv && . .venv/bin/activate + +# Install dependencies and build editable extension +uv pip install pyarrow uvx --from maturin maturin develop -m python/Cargo.toml -# Run examples (uv provides pyarrow; no PYTHONPATH needed after develop) -uv run --with pyarrow python examples/basic_cypher.py -uv run --with pyarrow python examples/kg_traversal.py +# Run examples using the venv's Python +python examples/basic_cypher.py +python examples/kg_traversal.py ``` ### 2) Install the package, then run @@ -44,6 +49,15 @@ python examples/basic_cypher.py python examples/kg_traversal.py ``` +### 3) Single-shot with uv (no install, run from source) + +uv creates a fresh isolated environment per run. If you prefer a one-liner without installing the package, point `PYTHONPATH` to the source package and let uv provide `pyarrow`: + +```bash +PYTHONPATH=python/python uv run --with pyarrow python examples/basic_cypher.py +PYTHONPATH=python/python uv run --with pyarrow python examples/kg_traversal.py +``` + ## Examples - `basic_cypher.py`: simple node filter and projection.