From 0711b14419a98d8d0c3f76655475e3bf6914876f Mon Sep 17 00:00:00 2001 From: jackylee-ch Date: Tue, 22 Sep 2026 22:22:43 +0800 Subject: [PATCH] fix(python): declare read-scan methods in the datafusion type stub `ReadBuilder.with_nested_projection`, `TableScan.with_chunk_shuffle` and `TableScan.with_shard` are implemented `#[pymethods]` and exercised in `tests/test_read.py`, but `datafusion.pyi` never declared them. The package ships `py.typed`, so the stub is the type contract: mypy/pyright reject these calls with "no attribute" and offer no completion, even though they work. The methods were added in #887 and #890; the stub was just not updated. --- bindings/python/python/pypaimon_rust/datafusion.pyi | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bindings/python/python/pypaimon_rust/datafusion.pyi b/bindings/python/python/pypaimon_rust/datafusion.pyi index b3ebed818..de67f4c4d 100644 --- a/bindings/python/python/pypaimon_rust/datafusion.pyi +++ b/bindings/python/python/pypaimon_rust/datafusion.pyi @@ -59,6 +59,14 @@ class Plan: class TableScan: def with_row_position_slice(self, start: int, end: int) -> "TableScan": ... def with_row_position_shard(self, index: int, count: int) -> "TableScan": ... + def with_chunk_shuffle(self, seed: str, chunk_size: int) -> "TableScan": + """Deterministically shuffle fixed-live-row chunks. ``seed`` is a decimal + integer string so arbitrarily large seeds keep Python ``random.Random`` + semantics.""" + ... + def with_shard(self, index: int, count: int) -> "TableScan": + """Select one balanced worker shard (``index`` of ``count``) for a distributed scan.""" + ... def plan(self) -> Plan: ... class RecordBatchReader: @@ -77,6 +85,10 @@ class TableRead: class ReadBuilder: def with_projection(self, columns: List[str]) -> "ReadBuilder": ... + def with_nested_projection(self, paths: List[List[str]]) -> "ReadBuilder": + """Project top-level fields or nested ROW leaves by exact name paths. A MAP + path keeps the complete MAP so the caller can extract literal keys.""" + ... def with_case_sensitive(self, case_sensitive: bool) -> "ReadBuilder": """ Set whether column-name matching (projection and predicate column