Skip to content

Commit d6a5ec9

Browse files
authored
examples(python): add basic Cypher and KG traversal examples (#8)
* 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 * 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 * docs(examples): fix run command paths after moving to top-level * docs(examples): add uv run instructions for building and running examples * 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 * build(python): silence dead_code warnings in BackgroundExecutor methods * docs(examples): clarify pyarrow install, uv ephemeral envs, and add venv + PYTHONPATH options
1 parent f89fdd8 commit d6a5ec9

5 files changed

Lines changed: 220 additions & 0 deletions

File tree

examples/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Examples for lance-graph
2+
3+
## How to Run Examples
4+
5+
Pick one of the two approaches:
6+
7+
### 1) Local build (editable) with maturin
8+
9+
```bash
10+
# From the repo root; installs the Python extension in editable mode
11+
pip install pyarrow # or: uv pip install pyarrow
12+
maturin develop -m python/Cargo.toml
13+
14+
# Run examples
15+
python examples/basic_cypher.py
16+
python examples/kg_traversal.py
17+
```
18+
19+
With `uv` (persistent venv recommended):
20+
21+
```bash
22+
# Create and activate a reusable environment
23+
uv venv .venv && . .venv/bin/activate
24+
25+
# Install dependencies and build editable extension
26+
uv pip install pyarrow
27+
uvx --from maturin maturin develop -m python/Cargo.toml
28+
29+
# Run examples using the venv's Python
30+
python examples/basic_cypher.py
31+
python examples/kg_traversal.py
32+
```
33+
34+
### 2) Install the package, then run
35+
36+
- From PyPI (when published):
37+
38+
```bash
39+
pip install lance-graph pyarrow
40+
python examples/basic_cypher.py
41+
python examples/kg_traversal.py
42+
```
43+
44+
- From git (editable):
45+
46+
```bash
47+
pip install -e python
48+
python examples/basic_cypher.py
49+
python examples/kg_traversal.py
50+
```
51+
52+
### 3) Single-shot with uv (no install, run from source)
53+
54+
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`:
55+
56+
```bash
57+
PYTHONPATH=python/python uv run --with pyarrow python examples/basic_cypher.py
58+
PYTHONPATH=python/python uv run --with pyarrow python examples/kg_traversal.py
59+
```
60+
61+
## Examples
62+
63+
- `basic_cypher.py`: simple node filter and projection.
64+
65+
```bash
66+
python examples/basic_cypher.py
67+
```
68+
69+
- `kg_traversal.py`: multi-hop traversal on a small synthetic knowledge graph.
70+
71+
```bash
72+
python examples/kg_traversal.py
73+
```

examples/basic_cypher.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
Basic Cypher graph query using the lance-graph Python bindings.
3+
4+
Requirements:
5+
- Build/install the Python extension first (from repo root):
6+
maturin develop -m python/Cargo.toml
7+
- Python deps: pyarrow
8+
9+
Run:
10+
python examples/basic_cypher.py
11+
"""
12+
13+
from __future__ import annotations
14+
15+
import pyarrow as pa
16+
17+
from lance_graph import GraphConfigBuilder, CypherQuery
18+
19+
20+
def make_people_batch() -> pa.RecordBatch:
21+
return pa.record_batch(
22+
[
23+
pa.array([1, 2, 3, 4, 5], type=pa.int32()),
24+
pa.array(["Alice", "Bob", "Carol", "David", "Eve"], type=pa.string()),
25+
pa.array([28, 34, 29, 42, 31], type=pa.int32()),
26+
],
27+
names=["person_id", "name", "age"],
28+
)
29+
30+
31+
def main() -> None:
32+
config = (
33+
GraphConfigBuilder()
34+
.with_node_label("Person", "person_id")
35+
.build()
36+
)
37+
38+
query = (
39+
CypherQuery("MATCH (n:Person) WHERE n.age > 30 RETURN n.name")
40+
.with_config(config)
41+
)
42+
43+
datasets = {"Person": make_people_batch()}
44+
result = query.execute(datasets)
45+
46+
# Convert to a simple Python dict for display
47+
print(result.to_pydict())
48+
49+
50+
if __name__ == "__main__":
51+
main()

examples/kg_traversal.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""
2+
Simple knowledge-graph multi-hop traversal with lance-graph Python bindings.
3+
4+
Requirements:
5+
- Build/install the Python extension first (from repo root):
6+
maturin develop -m python/Cargo.toml
7+
- Python deps: pyarrow
8+
9+
Run:
10+
python examples/kg_traversal.py
11+
"""
12+
13+
from __future__ import annotations
14+
15+
import pyarrow as pa
16+
17+
from lance_graph import GraphConfigBuilder, CypherQuery
18+
19+
20+
def make_people_batch(n: int = 6) -> pa.RecordBatch:
21+
return pa.record_batch(
22+
[
23+
pa.array(list(range(1, n + 1)), type=pa.int32()),
24+
pa.array([f"P{i}" for i in range(1, n + 1)], type=pa.string()),
25+
],
26+
names=["person_id", "name"],
27+
)
28+
29+
30+
def make_friendship_batch(n: int = 6) -> pa.RecordBatch:
31+
# Create a simple ring: 1->2->3->...->n->1
32+
src = list(range(1, n + 1))
33+
dst = [i + 1 if i < n else 1 for i in src]
34+
return pa.record_batch(
35+
[pa.array(src, type=pa.int32()), pa.array(dst, type=pa.int32())],
36+
names=["person1_id", "person2_id"],
37+
)
38+
39+
40+
def main() -> None:
41+
config = (
42+
GraphConfigBuilder()
43+
.with_node_label("Person", "person_id")
44+
.with_relationship("FRIEND_OF", "person1_id", "person2_id")
45+
.build()
46+
)
47+
48+
# Two-hop traversal from a person to friend-of-a-friend
49+
query = (
50+
CypherQuery(
51+
"MATCH (a:Person)-[:FRIEND_OF]->(b:Person)-[:FRIEND_OF]->(c:Person) RETURN a.name, c.name"
52+
)
53+
.with_config(config)
54+
)
55+
56+
datasets = {
57+
"Person": make_people_batch(),
58+
"FRIEND_OF": make_friendship_batch(),
59+
}
60+
result = query.execute(datasets)
61+
print(result.to_pydict())
62+
63+
64+
if __name__ == "__main__":
65+
main()

python/src/executor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct BackgroundExecutor {
3131
}
3232

3333
impl BackgroundExecutor {
34+
#[allow(dead_code)]
3435
pub fn get_runtime_handle(&self) -> Option<tokio::runtime::Handle> {
3536
Some(self.runtime.handle().clone())
3637
}
@@ -50,6 +51,7 @@ impl BackgroundExecutor {
5051
///
5152
/// This method is safe to use with inputs that may reference a Rust async
5253
/// runtime.
54+
#[allow(dead_code)]
5355
pub fn spawn<T>(&self, py: Option<Python<'_>>, task: T) -> PyResult<T::Output>
5456
where
5557
T: Future + Send + 'static,
@@ -63,6 +65,7 @@ impl BackgroundExecutor {
6365
}
6466
}
6567

68+
#[allow(dead_code)]
6669
fn spawn_impl<T>(&self, task: T) -> PyResult<T::Output>
6770
where
6871
T: Future + Send + 'static,
@@ -103,6 +106,7 @@ impl BackgroundExecutor {
103106
}
104107

105108
/// Spawn a task in the background
109+
#[allow(dead_code)]
106110
pub fn spawn_background<T>(&self, py: Option<Python<'_>>, task: T)
107111
where
108112
T: Future + Send + 'static,

rust/lance-graph/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,33 @@ Numbers are illustrative; your hardware, compiler, and runtime load will affect
164164

165165
Python bindings for this crate live under `python/src/graph.rs` and expose the same configuration and query APIs via PyO3.
166166

167+
### Python Examples
168+
169+
See top-level `examples/` for runnable Python examples:
170+
171+
- `basic_cypher.py`: simple node filter and projection against in-memory Arrow batches.
172+
- `kg_traversal.py`: two-hop traversal on a small synthetic knowledge graph.
173+
174+
Setup and run (from repo root):
175+
176+
```bash
177+
Option A - Local build (editable):
178+
179+
```bash
180+
maturin develop -m python/Cargo.toml
181+
python examples/basic_cypher.py
182+
python examples/kg_traversal.py
183+
```
184+
185+
Option B - Using uv:
186+
187+
```bash
188+
uvx --from maturin maturin develop -m python/Cargo.toml
189+
uv run --with pyarrow python examples/basic_cypher.py
190+
uv run --with pyarrow python examples/kg_traversal.py
191+
```
192+
```
193+
167194
## License
168195

169196
Apache-2.0. See the top-level LICENSE file for details.

0 commit comments

Comments
 (0)