Skip to content

Commit c05e2d5

Browse files
rustyconoverclaude
andcommitted
Fix ty type checker errors in vgi source and tests
- test_streaming_decorator.py: Fix method override by using correct parameter name 'batch' instead of 'b' - vgi/arguments.py: Restructure type_bound normalization for better type narrowing (if/else instead of ternary) - vgi/function.py: Use getattr() instead of hasattr() for __orig_bases__ to make iteration type-safe - vgi/worker.py: Cast dynamic type() result to type[CatalogInterface] Reduces ty diagnostics from 17 to 14 (remaining are pyarrow stub issues). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7951422 commit c05e2d5

4 files changed

Lines changed: 19 additions & 14 deletions

File tree

tests/table_in_out/test_streaming_decorator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,10 @@ def test_equivalent_output(self) -> None:
172172
"""@streaming decorated function should produce same output as manual."""
173173

174174
class ManualEcho(TableInOutGenerator):
175-
def process(self, b: pa.RecordBatch) -> OutputGenerator:
175+
def process(self, batch: pa.RecordBatch) -> OutputGenerator:
176176
"""Manual process without decorator."""
177177
_ = yield None
178-
current: pa.RecordBatch | None = b
178+
current: pa.RecordBatch | None = batch
179179
while True:
180180
# Combined yield-and-receive (correct pattern)
181181
current = yield Output(current)

vgi/arguments.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,9 +1136,10 @@ def validate_type_bound(self, field_type: pa.DataType) -> None:
11361136
return
11371137

11381138
# Normalize to sequence
1139-
predicates: list[TypeBoundPredicate] = (
1140-
[self.type_bound] if callable(self.type_bound) else list(self.type_bound)
1141-
)
1139+
if callable(self.type_bound):
1140+
predicates: list[TypeBoundPredicate] = [self.type_bound]
1141+
else:
1142+
predicates = list(self.type_bound)
11421143

11431144
# OR logic: at least one predicate must pass
11441145
if not any(predicate(field_type) for predicate in predicates):

vgi/function.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,9 @@ def _get_init_input_type(cls) -> type["FunctionInitInput"]:
295295
return cls._init_input_type_cache[cls]
296296

297297
for base in cls.__mro__:
298-
if hasattr(base, "__orig_bases__"):
299-
for orig_base in base.__orig_bases__:
298+
orig_bases = getattr(base, "__orig_bases__", None)
299+
if orig_bases is not None:
300+
for orig_base in orig_bases:
300301
origin = get_origin(orig_base)
301302
if origin is not None and origin.__name__ == "Function":
302303
args = get_args(orig_base)

vgi/worker.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,16 @@ def _get_catalog_interface(cls) -> type[CatalogInterface] | None:
212212
from vgi.catalog import ReadOnlyCatalogInterface
213213

214214
# Create a dynamic subclass with the worker's functions
215-
cls._default_catalog_interface = type(
216-
f"{cls.__name__}Catalog",
217-
(ReadOnlyCatalogInterface,),
218-
{
219-
"catalog_name": cls.catalog_name,
220-
"functions": list(cls.functions),
221-
},
215+
cls._default_catalog_interface = cast(
216+
type[CatalogInterface],
217+
type(
218+
f"{cls.__name__}Catalog",
219+
(ReadOnlyCatalogInterface,),
220+
{
221+
"catalog_name": cls.catalog_name,
222+
"functions": list(cls.functions),
223+
},
224+
),
222225
)
223226

224227
return cls._default_catalog_interface

0 commit comments

Comments
 (0)