Skip to content

Commit 741fbe0

Browse files
rustyconoverclaude
andcommitted
Merge feature/example-arrow-type into test/arg-arrow-type
Resolve conflict in tests/test_argument_spec.py by keeping both: - TestArgArrowType and TestExtractArgumentSpecsAutoInference (from this branch) - TestArgumentSpecRepr (from feature/example-arrow-type) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2 parents 26ed879 + 5cd20f0 commit 741fbe0

4 files changed

Lines changed: 100 additions & 1 deletion

File tree

.beads/issues.jsonl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{"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"}]}
22
{"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"}
33
{"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."}
4-
{"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"}]}
4+
{"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"}]}
55
{"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"}]}
66
{"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"}
77
{"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%."}

tests/test_argument_spec.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,3 +674,57 @@ class FunctionWithExplicit(TableInOutFunction):
674674

675675
specs = extract_argument_specs(FunctionWithExplicit)
676676
assert specs[0].arrow_type == pa.int32()
677+
678+
679+
class TestArgumentSpecRepr:
680+
"""Test ArgumentSpec __repr__ method."""
681+
682+
def test_positional_argument_repr(self) -> None:
683+
"""Positional argument should show integer position."""
684+
spec = ArgumentSpec(name="count", position=0, arrow_type=pa.int64())
685+
result = repr(spec)
686+
assert 'name="count"' in result
687+
assert "pos=0" in result
688+
assert "int64" in result
689+
assert "flags=" not in result # No flags when all False
690+
691+
def test_named_argument_repr(self) -> None:
692+
"""Named argument should show quoted string position."""
693+
spec = ArgumentSpec(name="format", position="format", arrow_type=pa.utf8())
694+
result = repr(spec)
695+
assert 'name="format"' in result
696+
assert 'pos="format"' in result
697+
assert "string" in result or "utf8" in result
698+
699+
def test_flags_shown_when_true(self) -> None:
700+
"""Flags should only appear when True."""
701+
spec = ArgumentSpec(
702+
name="data",
703+
position=0,
704+
arrow_type=pa.null(),
705+
is_table_input=True,
706+
)
707+
result = repr(spec)
708+
assert "flags=[table_input]" in result
709+
710+
def test_multiple_flags(self) -> None:
711+
"""Multiple flags should all be shown."""
712+
spec = ArgumentSpec(
713+
name="cols",
714+
position=0,
715+
arrow_type=pa.utf8(),
716+
is_varargs=True,
717+
)
718+
result = repr(spec)
719+
assert "varargs" in result
720+
721+
def test_any_type_flag(self) -> None:
722+
"""any_type flag should be shown."""
723+
spec = ArgumentSpec(
724+
name="value",
725+
position=0,
726+
arrow_type=pa.null(),
727+
is_any_type=True,
728+
)
729+
result = repr(spec)
730+
assert "any_type" in result

vgi/argument_spec.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ class ArgumentSpec:
109109
is_varargs: True if this argument collects all remaining positional
110110
arguments (varargs=True).
111111
112+
Note:
113+
For named arguments, the Python attribute name (``name``) and the SQL
114+
key (``position``) are assumed to be identical. This is the standard
115+
convention::
116+
117+
format = Arg[str]("format") # name="format", position="format"
118+
119+
If they differ, the ``position`` value will be lost during schema
120+
round-trip serialization, as only ``name`` is stored in the Arrow
121+
schema field name.
122+
112123
"""
113124

114125
name: str
@@ -118,6 +129,27 @@ class ArgumentSpec:
118129
is_any_type: bool = False
119130
is_varargs: bool = False
120131

132+
def __repr__(self) -> str:
133+
"""Return concise repr showing key attributes."""
134+
# Build position display: integer or quoted string
135+
pos = self.position if isinstance(self.position, int) else f'"{self.position}"'
136+
137+
# Build flags list (only show if True)
138+
flags = []
139+
if self.is_table_input:
140+
flags.append("table_input")
141+
if self.is_any_type:
142+
flags.append("any_type")
143+
if self.is_varargs:
144+
flags.append("varargs")
145+
146+
flags_str = f", flags=[{', '.join(flags)}]" if flags else ""
147+
148+
return (
149+
f'ArgumentSpec(name="{self.name}", pos={pos}, '
150+
f"type={self.arrow_type}{flags_str})"
151+
)
152+
121153

122154
# =============================================================================
123155
# Serialization Functions

vgi/arguments.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,19 @@ def transform(self, batch):
530530
# Validation happens automatically on first access
531531
...
532532
533+
Note:
534+
For named arguments (string position), the Python attribute name should
535+
match the SQL key. This is the standard convention::
536+
537+
format = Arg[str]("format") # Recommended: attribute == key
538+
539+
Avoid using different names::
540+
541+
output_format = Arg[str]("format") # Not recommended
542+
543+
While this works at runtime, it can cause issues with metadata
544+
serialization where only one name is preserved.
545+
533546
"""
534547

535548
__slots__ = (

0 commit comments

Comments
 (0)