Skip to content

Commit 048da88

Browse files
rustyconoverclaude
andcommitted
Merge feature/example-arrow-type into test/example-functions-serialization
Resolve conflict in tests/test_argument_spec.py by keeping both: - TestExampleFunctionsSerialization (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 185ee2d + c8a162f commit 048da88

3 files changed

Lines changed: 99 additions & 0 deletions

File tree

tests/test_argument_spec.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,3 +769,57 @@ def test_double_column_uses_explicit_utf8(self) -> None:
769769
specs = extract_argument_specs(DoubleColumnFunction)
770770
column_spec = next(s for s in specs if s.name == "column")
771771
assert column_spec.arrow_type == pa.utf8()
772+
773+
774+
class TestArgumentSpecRepr:
775+
"""Test ArgumentSpec __repr__ method."""
776+
777+
def test_positional_argument_repr(self) -> None:
778+
"""Positional argument should show integer position."""
779+
spec = ArgumentSpec(name="count", position=0, arrow_type=pa.int64())
780+
result = repr(spec)
781+
assert 'name="count"' in result
782+
assert "pos=0" in result
783+
assert "int64" in result
784+
assert "flags=" not in result # No flags when all False
785+
786+
def test_named_argument_repr(self) -> None:
787+
"""Named argument should show quoted string position."""
788+
spec = ArgumentSpec(name="format", position="format", arrow_type=pa.utf8())
789+
result = repr(spec)
790+
assert 'name="format"' in result
791+
assert 'pos="format"' in result
792+
assert "string" in result or "utf8" in result
793+
794+
def test_flags_shown_when_true(self) -> None:
795+
"""Flags should only appear when True."""
796+
spec = ArgumentSpec(
797+
name="data",
798+
position=0,
799+
arrow_type=pa.null(),
800+
is_table_input=True,
801+
)
802+
result = repr(spec)
803+
assert "flags=[table_input]" in result
804+
805+
def test_multiple_flags(self) -> None:
806+
"""Multiple flags should all be shown."""
807+
spec = ArgumentSpec(
808+
name="cols",
809+
position=0,
810+
arrow_type=pa.utf8(),
811+
is_varargs=True,
812+
)
813+
result = repr(spec)
814+
assert "varargs" in result
815+
816+
def test_any_type_flag(self) -> None:
817+
"""any_type flag should be shown."""
818+
spec = ArgumentSpec(
819+
name="value",
820+
position=0,
821+
arrow_type=pa.null(),
822+
is_any_type=True,
823+
)
824+
result = repr(spec)
825+
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)