From 66d5842464400399ea3b6fd9f5262791940b73ad Mon Sep 17 00:00:00 2001 From: Rusty Conover Date: Mon, 5 Jan 2026 16:02:01 -0500 Subject: [PATCH 1/2] test: Add tests for example function Arrow serialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add TestExampleFunctionsSerialization class to verify that all example functions can have their argument specs extracted and serialized: - test_scalar_functions: DoubleColumn, AddColumns, UpperCase - test_table_functions: Sequence, Range, ConstantTable - test_table_in_out_functions: Echo, BufferInput, RepeatInputs, SumAllColumns - test_range_function_step_uses_int32: Verifies explicit arrow_type - test_double_column_uses_explicit_utf8: Verifies explicit arrow_type Each test verifies: 1. Specs are extracted successfully 2. All specs have non-null arrow_type 3. Schema roundtrip works 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .beads/issues.jsonl | 2 +- tests/test_argument_spec.py | 95 +++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 8bff7aa..a638038 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,7 +1,7 @@ {"id":"vgi-python-0fe","title":"Add is_varargs to ParameterInfo and metadata extraction","description":"In vgi/metadata.py:\n- Add is_varargs: bool = False to ParameterInfo\n- Update to_dict() and from_dict()\n- Add is_varargs field to _PARAMETER_STRUCT for Arrow serialization\n- Extract varargs flag in extract_parameters()\n- Add _validate_varargs() with rules:\n - Only one varargs parameter allowed\n - Must be positional (not named)\n - Must be last positional (before TableInput if present)\n - Cannot have default value","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T10:49:20.141375-05:00","created_by":"rusty","updated_at":"2026-01-05T10:58:21.242603-05:00","closed_at":"2026-01-05T10:58:21.242603-05:00","close_reason":"Added is_varargs to ParameterInfo, _PARAMETER_STRUCT, extract_parameters(), and _validate_varargs()","dependencies":[{"issue_id":"vgi-python-0fe","depends_on_id":"vgi-python-jrf","type":"blocks","created_at":"2026-01-05T10:49:26.421664-05:00","created_by":"rusty"}]} {"id":"vgi-python-0hr","title":"Remove redundant InitInputType class attribute","description":"InitInputType class attribute duplicates the generic type parameter: 'class ScalarFunctionGenerator(Function[FunctionInitInput])' already specifies the type, but 'InitInputType = FunctionInitInput' repeats it. Investigate using get_type_hints or __orig_bases__ to infer the type and remove the redundant attribute.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T20:06:53.780529-05:00","created_by":"rusty","updated_at":"2026-01-04T22:00:40.221423-05:00","closed_at":"2026-01-04T22:00:40.221423-05:00","close_reason":"PR #10 created - uses _get_init_input_type() to infer type from generic parameter"} {"id":"vgi-python-1s5","title":"Move distributed state management to optional mixin","description":"The Function base class in function.py includes ~200 lines for distributed state management (store_state, collect_states, enqueue_work, dequeue_work, work queue storage). Not all functions need this. Extract to DistributedStateMixin that functions can opt into, keeping Function base class simpler for basic use cases.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T20:06:53.606614-05:00","created_by":"rusty","updated_at":"2026-01-04T21:22:09.772825-05:00","closed_at":"2026-01-04T21:22:09.772825-05:00","close_reason":"Analysis complete: extraction not recommended. The distributed state methods are tightly coupled with execution_identifier and storage, which are used by core initialization methods. Extraction would require moving initialize_global_state/load_global_state to the mixin, breaking the protocol and requiring multiple inheritance. Current API is already opt-in (just don't call the methods) and well-documented."} -{"id":"vgi-python-229","title":"Add tests for example function Arrow serialization","description":"Add to tests/test_argument_spec.py:\n\nclass TestExampleFunctionsSerialization:\n- test_scalar_functions: DoubleColumnFunction, AddColumnsFunction, UpperCaseFunction\n- test_table_functions: SequenceFunction, RangeFunction, ConstantTableFunction\n- test_table_in_out_functions: EchoFunction, BufferInputFunction, RepeatInputsFunction, SumAllColumnsFunction\n\nEach test should:\n1. Call extract_argument_specs(cls)\n2. Verify all specs have non-null arrow_type\n3. Verify schema roundtrip works","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-05T15:44:57.064847-05:00","created_by":"rusty","updated_at":"2026-01-05T15:44:57.064847-05:00","dependencies":[{"issue_id":"vgi-python-229","depends_on_id":"vgi-python-coi","type":"blocks","created_at":"2026-01-05T15:45:14.210202-05:00","created_by":"rusty"}]} +{"id":"vgi-python-229","title":"Add tests for example function Arrow serialization","description":"Add to tests/test_argument_spec.py:\n\nclass TestExampleFunctionsSerialization:\n- test_scalar_functions: DoubleColumnFunction, AddColumnsFunction, UpperCaseFunction\n- test_table_functions: SequenceFunction, RangeFunction, ConstantTableFunction\n- test_table_in_out_functions: EchoFunction, BufferInputFunction, RepeatInputsFunction, SumAllColumnsFunction\n\nEach test should:\n1. Call extract_argument_specs(cls)\n2. Verify all specs have non-null arrow_type\n3. Verify schema roundtrip works","status":"in_progress","priority":2,"issue_type":"task","created_at":"2026-01-05T15:44:57.064847-05:00","created_by":"rusty","updated_at":"2026-01-05T16:00:33.684801-05:00","dependencies":[{"issue_id":"vgi-python-229","depends_on_id":"vgi-python-coi","type":"blocks","created_at":"2026-01-05T15:45:14.210202-05:00","created_by":"rusty"}]} {"id":"vgi-python-29x","title":"Add tests for varargs metadata validation","description":"In tests/test_metadata.py:\n- Varargs must be positional - error if named\n- Only one varargs allowed - error if multiple\n- Varargs must be last positional - error if regular arg after\n- Varargs + TableInput ordering works correctly\n- Arrow serialization round-trip preserves is_varargs\n- ParameterInfo.is_varargs correctly extracted","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T10:49:20.406998-05:00","created_by":"rusty","updated_at":"2026-01-05T11:02:41.043316-05:00","closed_at":"2026-01-05T11:02:41.043316-05:00","close_reason":"Added tests for varargs metadata extraction and validation","dependencies":[{"issue_id":"vgi-python-29x","depends_on_id":"vgi-python-jrf","type":"blocks","created_at":"2026-01-05T10:49:26.482596-05:00","created_by":"rusty"},{"issue_id":"vgi-python-29x","depends_on_id":"vgi-python-0fe","type":"blocks","created_at":"2026-01-05T10:49:26.512138-05:00","created_by":"rusty"}]} {"id":"vgi-python-2ln","title":"Add varargs support for trailing positional arguments","description":"Allow a single trailing positional argument to accept one or more values of the same type using Arg[T](position, varargs=True). Returns tuple[T, ...]. Requires at least 1 value. Must be last positional arg (before TableInput if present).","status":"closed","priority":2,"issue_type":"feature","created_at":"2026-01-05T10:49:07.327391-05:00","created_by":"rusty","updated_at":"2026-01-05T11:02:41.151847-05:00","closed_at":"2026-01-05T11:02:41.151847-05:00","close_reason":"Completed varargs support for trailing positional arguments"} {"id":"vgi-python-35i","title":"Test SchemaValidationError detailed message paths","notes":"Coverage: 67% in vgi/exceptions.py. Missing tests for:\n- Lines 116-123: Type mismatch detection in _build_detailed_message\n- Lines 128-131: Field order difference detection \n- Lines 149-151: Type mismatch reporting\n- Lines 155-157: Field order difference reporting\n\nTest scenarios needed:\n1. Schema with same fields but different types\n2. Schema with nullable vs non-nullable mismatch\n3. Schema with same fields in different order","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T22:15:25.858704-05:00","created_by":"rusty","updated_at":"2026-01-04T22:25:58.697852-05:00","closed_at":"2026-01-04T22:25:58.697852-05:00","close_reason":"Added comprehensive tests for SchemaValidationError. Coverage improved from 67% to 99%."} diff --git a/tests/test_argument_spec.py b/tests/test_argument_spec.py index 119a446..14dd39d 100644 --- a/tests/test_argument_spec.py +++ b/tests/test_argument_spec.py @@ -674,3 +674,98 @@ class FunctionWithExplicit(TableInOutFunction): specs = extract_argument_specs(FunctionWithExplicit) assert specs[0].arrow_type == pa.int32() + + +class TestExampleFunctionsSerialization: + """Test that example functions can be serialized and deserialized.""" + + def test_scalar_functions(self) -> None: + """Test serialization of scalar example functions.""" + from vgi.examples.scalar import ( + AddColumnsFunction, + DoubleColumnFunction, + UpperCaseFunction, + ) + + for func_cls in [DoubleColumnFunction, AddColumnsFunction, UpperCaseFunction]: + specs = extract_argument_specs(func_cls) + assert len(specs) > 0, f"{func_cls.__name__} should have arguments" + + # All specs should have non-null arrow_type + for spec in specs: + assert spec.arrow_type is not None, ( + f"{func_cls.__name__}.{spec.name} has null arrow_type" + ) + + # Schema roundtrip should work + schema = argument_specs_to_schema(specs) + restored = schema_to_argument_specs(schema) + assert len(restored) == len(specs) + + def test_table_functions(self) -> None: + """Test serialization of table example functions.""" + from vgi.examples.table import ( + ConstantTableFunction, + RangeFunction, + SequenceFunction, + ) + + for func_cls in [SequenceFunction, RangeFunction, ConstantTableFunction]: + specs = extract_argument_specs(func_cls) + assert len(specs) > 0, f"{func_cls.__name__} should have arguments" + + # All specs should have non-null arrow_type + for spec in specs: + assert spec.arrow_type is not None, ( + f"{func_cls.__name__}.{spec.name} has null arrow_type" + ) + + # Schema roundtrip should work + schema = argument_specs_to_schema(specs) + restored = schema_to_argument_specs(schema) + assert len(restored) == len(specs) + + def test_table_in_out_functions(self) -> None: + """Test serialization of table-in-out example functions.""" + from vgi.examples.table_in_out import ( + BufferInputFunction, + EchoFunction, + RepeatInputsFunction, + SumAllColumnsFunction, + ) + + for func_cls in [ + EchoFunction, + BufferInputFunction, + RepeatInputsFunction, + SumAllColumnsFunction, + ]: + specs = extract_argument_specs(func_cls) + assert len(specs) > 0, f"{func_cls.__name__} should have arguments" + + # All specs should have non-null arrow_type + for spec in specs: + assert spec.arrow_type is not None, ( + f"{func_cls.__name__}.{spec.name} has null arrow_type" + ) + + # Schema roundtrip should work + schema = argument_specs_to_schema(specs) + restored = schema_to_argument_specs(schema) + assert len(restored) == len(specs) + + def test_range_function_step_uses_int32(self) -> None: + """Verify RangeFunction.step uses explicit int32 arrow_type.""" + from vgi.examples.table import RangeFunction + + specs = extract_argument_specs(RangeFunction) + step_spec = next(s for s in specs if s.name == "step") + assert step_spec.arrow_type == pa.int32() + + def test_double_column_uses_explicit_utf8(self) -> None: + """Verify DoubleColumnFunction.column uses explicit utf8 arrow_type.""" + from vgi.examples.scalar import DoubleColumnFunction + + specs = extract_argument_specs(DoubleColumnFunction) + column_spec = next(s for s in specs if s.name == "column") + assert column_spec.arrow_type == pa.utf8() From 185ee2d26733b2e0cc293c2f3a43edff9eeb9518 Mon Sep 17 00:00:00 2001 From: Rusty Conover Date: Mon, 5 Jan 2026 16:02:18 -0500 Subject: [PATCH 2/2] bd sync: 2026-01-05 16:02:18 --- .beads/issues.jsonl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index a638038..be32417 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -1,7 +1,7 @@ {"id":"vgi-python-0fe","title":"Add is_varargs to ParameterInfo and metadata extraction","description":"In vgi/metadata.py:\n- Add is_varargs: bool = False to ParameterInfo\n- Update to_dict() and from_dict()\n- Add is_varargs field to _PARAMETER_STRUCT for Arrow serialization\n- Extract varargs flag in extract_parameters()\n- Add _validate_varargs() with rules:\n - Only one varargs parameter allowed\n - Must be positional (not named)\n - Must be last positional (before TableInput if present)\n - Cannot have default value","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T10:49:20.141375-05:00","created_by":"rusty","updated_at":"2026-01-05T10:58:21.242603-05:00","closed_at":"2026-01-05T10:58:21.242603-05:00","close_reason":"Added is_varargs to ParameterInfo, _PARAMETER_STRUCT, extract_parameters(), and _validate_varargs()","dependencies":[{"issue_id":"vgi-python-0fe","depends_on_id":"vgi-python-jrf","type":"blocks","created_at":"2026-01-05T10:49:26.421664-05:00","created_by":"rusty"}]} {"id":"vgi-python-0hr","title":"Remove redundant InitInputType class attribute","description":"InitInputType class attribute duplicates the generic type parameter: 'class ScalarFunctionGenerator(Function[FunctionInitInput])' already specifies the type, but 'InitInputType = FunctionInitInput' repeats it. Investigate using get_type_hints or __orig_bases__ to infer the type and remove the redundant attribute.","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T20:06:53.780529-05:00","created_by":"rusty","updated_at":"2026-01-04T22:00:40.221423-05:00","closed_at":"2026-01-04T22:00:40.221423-05:00","close_reason":"PR #10 created - uses _get_init_input_type() to infer type from generic parameter"} {"id":"vgi-python-1s5","title":"Move distributed state management to optional mixin","description":"The Function base class in function.py includes ~200 lines for distributed state management (store_state, collect_states, enqueue_work, dequeue_work, work queue storage). Not all functions need this. Extract to DistributedStateMixin that functions can opt into, keeping Function base class simpler for basic use cases.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T20:06:53.606614-05:00","created_by":"rusty","updated_at":"2026-01-04T21:22:09.772825-05:00","closed_at":"2026-01-04T21:22:09.772825-05:00","close_reason":"Analysis complete: extraction not recommended. The distributed state methods are tightly coupled with execution_identifier and storage, which are used by core initialization methods. Extraction would require moving initialize_global_state/load_global_state to the mixin, breaking the protocol and requiring multiple inheritance. Current API is already opt-in (just don't call the methods) and well-documented."} -{"id":"vgi-python-229","title":"Add tests for example function Arrow serialization","description":"Add to tests/test_argument_spec.py:\n\nclass TestExampleFunctionsSerialization:\n- test_scalar_functions: DoubleColumnFunction, AddColumnsFunction, UpperCaseFunction\n- test_table_functions: SequenceFunction, RangeFunction, ConstantTableFunction\n- test_table_in_out_functions: EchoFunction, BufferInputFunction, RepeatInputsFunction, SumAllColumnsFunction\n\nEach test should:\n1. Call extract_argument_specs(cls)\n2. Verify all specs have non-null arrow_type\n3. Verify schema roundtrip works","status":"in_progress","priority":2,"issue_type":"task","created_at":"2026-01-05T15:44:57.064847-05:00","created_by":"rusty","updated_at":"2026-01-05T16:00:33.684801-05:00","dependencies":[{"issue_id":"vgi-python-229","depends_on_id":"vgi-python-coi","type":"blocks","created_at":"2026-01-05T15:45:14.210202-05:00","created_by":"rusty"}]} +{"id":"vgi-python-229","title":"Add tests for example function Arrow serialization","description":"Add to tests/test_argument_spec.py:\n\nclass TestExampleFunctionsSerialization:\n- test_scalar_functions: DoubleColumnFunction, AddColumnsFunction, UpperCaseFunction\n- test_table_functions: SequenceFunction, RangeFunction, ConstantTableFunction\n- test_table_in_out_functions: EchoFunction, BufferInputFunction, RepeatInputsFunction, SumAllColumnsFunction\n\nEach test should:\n1. Call extract_argument_specs(cls)\n2. Verify all specs have non-null arrow_type\n3. Verify schema roundtrip works","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T15:44:57.064847-05:00","created_by":"rusty","updated_at":"2026-01-05T16:02:18.537006-05:00","closed_at":"2026-01-05T16:02:18.537006-05:00","close_reason":"PR #23 created","dependencies":[{"issue_id":"vgi-python-229","depends_on_id":"vgi-python-coi","type":"blocks","created_at":"2026-01-05T15:45:14.210202-05:00","created_by":"rusty"}]} {"id":"vgi-python-29x","title":"Add tests for varargs metadata validation","description":"In tests/test_metadata.py:\n- Varargs must be positional - error if named\n- Only one varargs allowed - error if multiple\n- Varargs must be last positional - error if regular arg after\n- Varargs + TableInput ordering works correctly\n- Arrow serialization round-trip preserves is_varargs\n- ParameterInfo.is_varargs correctly extracted","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-05T10:49:20.406998-05:00","created_by":"rusty","updated_at":"2026-01-05T11:02:41.043316-05:00","closed_at":"2026-01-05T11:02:41.043316-05:00","close_reason":"Added tests for varargs metadata extraction and validation","dependencies":[{"issue_id":"vgi-python-29x","depends_on_id":"vgi-python-jrf","type":"blocks","created_at":"2026-01-05T10:49:26.482596-05:00","created_by":"rusty"},{"issue_id":"vgi-python-29x","depends_on_id":"vgi-python-0fe","type":"blocks","created_at":"2026-01-05T10:49:26.512138-05:00","created_by":"rusty"}]} {"id":"vgi-python-2ln","title":"Add varargs support for trailing positional arguments","description":"Allow a single trailing positional argument to accept one or more values of the same type using Arg[T](position, varargs=True). Returns tuple[T, ...]. Requires at least 1 value. Must be last positional arg (before TableInput if present).","status":"closed","priority":2,"issue_type":"feature","created_at":"2026-01-05T10:49:07.327391-05:00","created_by":"rusty","updated_at":"2026-01-05T11:02:41.151847-05:00","closed_at":"2026-01-05T11:02:41.151847-05:00","close_reason":"Completed varargs support for trailing positional arguments"} {"id":"vgi-python-35i","title":"Test SchemaValidationError detailed message paths","notes":"Coverage: 67% in vgi/exceptions.py. Missing tests for:\n- Lines 116-123: Type mismatch detection in _build_detailed_message\n- Lines 128-131: Field order difference detection \n- Lines 149-151: Type mismatch reporting\n- Lines 155-157: Field order difference reporting\n\nTest scenarios needed:\n1. Schema with same fields but different types\n2. Schema with nullable vs non-nullable mismatch\n3. Schema with same fields in different order","status":"closed","priority":3,"issue_type":"task","created_at":"2026-01-04T22:15:25.858704-05:00","created_by":"rusty","updated_at":"2026-01-04T22:25:58.697852-05:00","closed_at":"2026-01-04T22:25:58.697852-05:00","close_reason":"Added comprehensive tests for SchemaValidationError. Coverage improved from 67% to 99%."}