Skip to content

Commit bf63de0

Browse files
authored
Merge branch 'main' into extract-exception-handling-mixin
2 parents b99ee01 + 4cc4ffc commit bf63de0

14 files changed

Lines changed: 66 additions & 66 deletions

File tree

.beads/issues.jsonl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
{"id":"vgi-python-e9q","title":"Unify ProtocolOutput classes with shared base","description":"ProtocolOutput classes in table_function.py:177-224 and table_in_out_function.py:144-207 share similar metadata() method and from_process_result() classmethod. The table_in_out version adds status field. Create shared base with table_in_out extending it for status support.","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T20:06:41.45014-05:00","created_by":"rusty","updated_at":"2026-01-04T20:07:16.371419-05:00"}
1717
{"id":"vgi-python-ivf","title":"Add required_settings to function Meta class","description":"Update function metadata to support declaring required DuckDB settings.\n\nChanges needed:\n- Add 'required_settings: list[str]' to FunctionMeta in vgi/metadata.py\n- Update Meta class resolution in vgi/function.py\n- Add validation that required_settings is a list of strings\n- Make it available via get_metadata() for introspection\n\nExample usage:\nclass MyFunction(TableInOutFunction):\n class Meta:\n required_settings = ['timezone', 'threads']","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T13:05:47.903747-05:00","created_by":"rusty","updated_at":"2026-01-04T13:20:41.169516-05:00","closed_at":"2026-01-04T13:20:41.169516-05:00","close_reason":"Implementation complete, all tests pass","dependencies":[{"issue_id":"vgi-python-ivf","depends_on_id":"vgi-python-aad","type":"blocks","created_at":"2026-01-04T13:06:13.690253-05:00","created_by":"rusty"}]}
1818
{"id":"vgi-python-j4t","title":"Update client to pass DuckDB settings in Invocation","description":"Update vgi/client/client.py to support passing DuckDB settings.\n\nChanges needed:\n- Add 'duckdb_settings: dict[str, str] | None = None' parameter to relevant methods\n- Include settings in Invocation creation\n- Add helper to query function's required_settings from metadata\n\nThe client needs to know what settings to pass. Options:\n1. Client queries worker for function metadata first\n2. Settings passed explicitly by caller\n3. Client introspects function class if available locally","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T13:05:48.358656-05:00","created_by":"rusty","updated_at":"2026-01-04T13:20:41.173178-05:00","closed_at":"2026-01-04T13:20:41.173178-05:00","close_reason":"Implementation complete, all tests pass","dependencies":[{"issue_id":"vgi-python-j4t","depends_on_id":"vgi-python-aad","type":"blocks","created_at":"2026-01-04T13:06:13.761572-05:00","created_by":"rusty"}]}
19-
{"id":"vgi-python-kz4","title":"Rename TableInOutGeneratorFunction to TableInOutGenerator for consistency","description":"Naming inconsistency: TableFunctionGenerator uses *Generator suffix, but TableInOutGeneratorFunction uses *GeneratorFunction suffix. Rename TableInOutGeneratorFunction to TableInOutGenerator for consistency. Also consider renaming ScalarFunctionGenerator if needed.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T20:06:41.581028-05:00","created_by":"rusty","updated_at":"2026-01-04T21:43:58.141038-05:00","closed_at":"2026-01-04T21:43:58.141038-05:00","close_reason":"PR #7 created: https://github.com/Query-farm/vgi-python/pull/7"}
19+
{"id":"vgi-python-kz4","title":"Rename TableInOutGeneratorFunction to TableInOutGenerator for consistency","description":"Naming inconsistency: TableFunctionGenerator uses *Generator suffix, but TableInOutGeneratorFunction uses *GeneratorFunction suffix. Rename TableInOutGeneratorFunction to TableInOutGenerator for consistency. Also consider renaming ScalarFunctionGenerator if needed.","status":"in_progress","priority":3,"issue_type":"task","created_at":"2026-01-04T20:06:41.581028-05:00","created_by":"rusty","updated_at":"2026-01-04T21:39:29.83686-05:00"}
2020
{"id":"vgi-python-odi","title":"Change max_processes from method to property in Function hierarchy","description":"Refactor max_processes from a method to a property across the Function class hierarchy (Function, ScalarFunction, TableFunctionGenerator, TableInOutFunction, etc.). This makes the API more consistent since max_processes is effectively a constant per function class and properties are more idiomatic for such values.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T11:25:29.750648-05:00","created_by":"rusty","updated_at":"2026-01-04T11:50:57.566545-05:00","closed_at":"2026-01-04T11:50:57.566545-05:00","close_reason":"Closed"}
2121
{"id":"vgi-python-p91","title":"Move exception classes from function.py to own file","description":"Move InitIdentifierError and SchemaValidationError from vgi/function.py to a new vgi/exceptions.py file. Update imports in function.py and any other files that reference these exceptions.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T09:12:28.058227-05:00","created_by":"rusty","updated_at":"2026-01-04T09:17:52.477661-05:00","closed_at":"2026-01-04T09:17:52.477661-05:00","close_reason":"Closed"}
2222
{"id":"vgi-python-r3t","title":"Consolidate test client infrastructure in testing.py","description":"testing.py has three test client classes (FunctionTestClient, TableFunctionTestClient, ScalarFunctionTestClient) with shared infrastructure patterns. Extend _BaseTestClient pattern to reduce code duplication. Consider using a single unified client with method dispatch based on function type.","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T20:06:53.913912-05:00","created_by":"rusty","updated_at":"2026-01-04T20:07:38.132591-05:00"}

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ vgi/
8484
function.py # Invocation, OutputSpec, Arguments, FunctionType
8585
scalar_function.py # ScalarFunction, ScalarFunctionGenerator
8686
table_function.py # TableFunctionGenerator, TableCardinality, Output
87-
table_in_out_function.py # TableInOutFunction, TableInOutGeneratorFunction
87+
table_in_out_function.py # TableInOutFunction, TableInOutGenerator
8888
metadata.py # Function metadata for introspection
8989
schema_utils.py # Schema builder helpers (schema, schema_like)
9090
worker.py # Worker base class

docs/generator-api.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def process(self):
170170

171171
## Table-In-Out Generator Function (Advanced)
172172

173-
For advanced streaming control with input data, use `TableInOutGeneratorFunction`. Most users should prefer `TableInOutFunction` instead.
173+
For advanced streaming control with input data, use `TableInOutGenerator`. Most users should prefer `TableInOutFunction` instead.
174174

175175
### When to Use Generator API
176176

@@ -182,9 +182,9 @@ For advanced streaming control with input data, use `TableInOutGeneratorFunction
182182

183183
```python
184184
import pyarrow as pa
185-
from vgi import TableInOutGeneratorFunction, Output, OutputGenerator, Arg
185+
from vgi import TableInOutGenerator, Output, OutputGenerator, Arg
186186

187-
class MyFunction(TableInOutGeneratorFunction):
187+
class MyFunction(TableInOutGenerator):
188188
"""One-line description."""
189189

190190
@property
@@ -208,13 +208,13 @@ class MyFunction(TableInOutGeneratorFunction):
208208

209209
**Passthrough (Echo):**
210210
```python
211-
class EchoFunction(TableInOutGeneratorFunction):
211+
class EchoFunction(TableInOutGenerator):
212212
pass # Default process() passes input unchanged
213213
```
214214

215215
**Aggregation (emit on finalize):**
216216
```python
217-
class SumFunction(TableInOutGeneratorFunction):
217+
class SumFunction(TableInOutGenerator):
218218
@property
219219
def output_schema(self):
220220
return pa.schema([pa.field("sum", pa.int64())])
@@ -270,7 +270,7 @@ def process(self, batch: pa.RecordBatch) -> OutputGenerator:
270270

271271
## Common Mistakes
272272

273-
### 1. Forgetting the priming yield (TableInOutGeneratorFunction only)
273+
### 1. Forgetting the priming yield (TableInOutGenerator only)
274274

275275
```python
276276
# ❌ WRONG - will raise TypeError on first send()
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"""Tests for TableInOutGeneratorFunction implementations."""
1+
"""Tests for TableInOutGenerator implementations."""

tests/table_in_out/test_streaming_decorator.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
Output,
99
OutputGenerator,
1010
StreamingGenerator,
11-
TableInOutGeneratorFunction,
11+
TableInOutGenerator,
1212
streaming,
1313
)
1414
from vgi.log import Level, Message
1515
from vgi.testing import FunctionTestClient, batch
1616

1717

18-
class EchoStreamingFunction(TableInOutGeneratorFunction):
18+
class EchoStreamingFunction(TableInOutGenerator):
1919
"""Simple echo function using the @streaming decorator."""
2020

2121
@streaming
@@ -26,7 +26,7 @@ def process(self, b: pa.RecordBatch) -> StreamingGenerator:
2626
current = yield Output(current)
2727

2828

29-
class CountingStreamingFunction(TableInOutGeneratorFunction):
29+
class CountingStreamingFunction(TableInOutGenerator):
3030
"""Function that counts batches using @streaming."""
3131

3232
def __init__(
@@ -45,7 +45,7 @@ def process(self, b: pa.RecordBatch) -> StreamingGenerator:
4545
current = yield Output(current)
4646

4747

48-
class AccumulatingStreamingFunction(TableInOutGeneratorFunction):
48+
class AccumulatingStreamingFunction(TableInOutGenerator):
4949
"""Function that accumulates and outputs empty batches during process."""
5050

5151
def __init__(
@@ -80,7 +80,7 @@ def finalize(self) -> OutputGenerator:
8080
)
8181

8282

83-
class LoggingStreamingFunction(TableInOutGeneratorFunction):
83+
class LoggingStreamingFunction(TableInOutGenerator):
8484
"""Function that logs using the @streaming decorator."""
8585

8686
@streaming
@@ -171,7 +171,7 @@ class TestStreamingDecoratorComparedToManual:
171171
def test_equivalent_output(self) -> None:
172172
"""@streaming decorated function should produce same output as manual."""
173173

174-
class ManualEcho(TableInOutGeneratorFunction):
174+
class ManualEcho(TableInOutGenerator):
175175
def process(self, b: pa.RecordBatch) -> OutputGenerator:
176176
"""Manual process without decorator."""
177177
_ = yield None

vgi/__init__.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@ def transform(self, batch: pa.RecordBatch) -> pa.RecordBatch:
1616
# Transform each batch here
1717
return batch
1818
19-
For advanced streaming control, use TableInOutGeneratorFunction with the
19+
For advanced streaming control, use TableInOutGenerator with the
2020
@streaming decorator:
2121
22-
from vgi import TableInOutGeneratorFunction, Output, StreamingGenerator, streaming
22+
from vgi import TableInOutGenerator, Output, StreamingGenerator, streaming
2323
import pyarrow as pa
2424
25-
class MyFunction(TableInOutGeneratorFunction):
25+
class MyFunction(TableInOutGenerator):
2626
@streaming
2727
def process(self, batch: pa.RecordBatch) -> StreamingGenerator:
2828
# No priming yield needed!
@@ -31,10 +31,10 @@ def process(self, batch: pa.RecordBatch) -> StreamingGenerator:
3131
3232
Or without the decorator (more verbose):
3333
34-
from vgi import TableInOutGeneratorFunction, Output, OutputGenerator
34+
from vgi import TableInOutGenerator, Output, OutputGenerator
3535
import pyarrow as pa
3636
37-
class MyFunction(TableInOutGeneratorFunction):
37+
class MyFunction(TableInOutGenerator):
3838
def process(self, batch: pa.RecordBatch) -> OutputGenerator:
3939
_ = yield None # Required priming yield
4040
while True:
@@ -58,7 +58,7 @@ class MyWorker(Worker):
5858
Classes and functions exported from this module:
5959
6060
TableInOutFunction - Callback-based API (recommended)
61-
TableInOutGeneratorFunction - Generator-based API (advanced)
61+
TableInOutGenerator - Generator-based API (advanced)
6262
ScalarFunction - Scalar function with compute() (single-column output)
6363
ScalarFunctionGenerator - Scalar function with generator protocol
6464
Output - Output batch from process()/finalize()
@@ -114,7 +114,7 @@ class Meta:
114114
vgi.function.Function - Base (max_processes, invocation_id)
115115
├─ vgi.table_function.TableFunctionBase - Adds cardinality hints, projection
116116
│ ├─ TableFunctionGenerator - Generate output without input
117-
│ └─ TableInOutGeneratorFunction - Full streaming (process/finalize)
117+
│ └─ TableInOutGenerator - Full streaming (process/finalize)
118118
│ └─ TableInOutFunction - Callback API (transform/finish)
119119
│ ├─ AggregationFunction - Reduce to summary
120120
│ ├─ FilterFunction - Row filtering
@@ -159,7 +159,7 @@ class Meta:
159159
OutputGenerator,
160160
StreamingGenerator,
161161
TableInOutFunction,
162-
TableInOutGeneratorFunction,
162+
TableInOutGenerator,
163163
streaming,
164164
)
165165
from vgi.table_in_out_function_patterns import (
@@ -195,7 +195,7 @@ class Meta:
195195
"ScalarOutputGenerator",
196196
"StreamingGenerator",
197197
"TableInOutFunction",
198-
"TableInOutGeneratorFunction",
198+
"TableInOutGenerator",
199199
"TableInput",
200200
"TableInputValidationError",
201201
"Worker",

vgi/client/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
-------
3939
client.start() : Start the worker subprocess
4040
client.stop() : Stop the worker subprocess
41-
client.table_in_out_function() : Invoke a TableInOutGeneratorFunction and stream results
41+
client.table_in_out_function() : Invoke a TableInOutGenerator and stream results
4242
client.table_function() : Invoke a TableFunctionGenerator and stream results
4343
client.scalar_function() : Invoke a ScalarFunction and stream results
4444
client.get_worker_stderr() : Get captured stderr from worker

vgi/examples/table_in_out.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
Output,
4040
OutputGenerator,
4141
TableInOutFunction,
42-
TableInOutGeneratorFunction,
42+
TableInOutGenerator,
4343
)
4444

4545
__all__ = [
@@ -55,7 +55,7 @@
5555
]
5656

5757

58-
class EchoFunction(TableInOutGeneratorFunction):
58+
class EchoFunction(TableInOutGenerator):
5959
"""Passthrough function that emits each input batch unchanged.
6060
6161
USE CASE
@@ -90,7 +90,7 @@ class Meta:
9090
data: TableInput = Arg[TableInput](0, doc="Input table") # type: ignore[assignment]
9191

9292

93-
class BufferInputFunction(TableInOutGeneratorFunction):
93+
class BufferInputFunction(TableInOutGenerator):
9494
"""Buffering function that collects all input and emits during finalization.
9595
9696
USE CASE
@@ -166,7 +166,7 @@ def finalize(self) -> OutputGenerator:
166166
yield Output(b, has_more)
167167

168168

169-
class RepeatInputsFunction(TableInOutGeneratorFunction):
169+
class RepeatInputsFunction(TableInOutGenerator):
170170
"""Explosion function that duplicates each input batch N times.
171171
172172
USE CASE
@@ -262,7 +262,7 @@ def process(self, batch: pa.RecordBatch) -> OutputGenerator:
262262
batch = received
263263

264264

265-
class SumAllColumnsFunction(TableInOutGeneratorFunction):
265+
class SumAllColumnsFunction(TableInOutGenerator):
266266
"""Aggregation function that computes column-wise sums across all batches.
267267
268268
USE CASE

vgi/examples/worker.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
each class's metadata (Meta.name or snake_case of class name).
66
77
The worker supports:
8-
- TableInOutGeneratorFunction: Transforms input batches to output batches
8+
- TableInOutGenerator: Transforms input batches to output batches
99
- TableFunctionGenerator: Generates output batches without input
1010
- ScalarFunctionGenerator: Transforms input to single-column output (1:1 rows)
1111
@@ -47,7 +47,7 @@ class ExampleWorker(Worker):
4747
"""Example worker with built-in test functions."""
4848

4949
functions = [
50-
# TableInOutGeneratorFunction - transform input batches
50+
# TableInOutGenerator - transform input batches
5151
EchoFunction,
5252
BufferInputFunction,
5353
RepeatInputsFunction,

vgi/output_complete.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class OutputComplete:
3232
Attributes:
3333
batch: Always a valid RecordBatch (never None).
3434
has_more: If True, generator expects another send() call.
35-
Only used by TableInOutGeneratorFunction.
35+
Only used by TableInOutGenerator.
3636
log_message: Present when user yielded Message directly.
3737
3838
"""

0 commit comments

Comments
 (0)