@@ -38,11 +38,10 @@ def test_type_bound_passes_for_valid_type(self) -> None:
3838 """Type bound validation should pass when predicate returns True."""
3939
4040 class TestFunc (ScalarFunction ):
41- col = Arg [AnyArrow ](0 , type_bound = pa .types .is_integer )
41+ class Meta :
42+ output_type = pa .int64 ()
4243
43- @classmethod
44- def catalog_output_type (cls ) -> pa .DataType :
45- return pa .int64 ()
44+ col = Arg [AnyArrow ](0 , type_bound = pa .types .is_integer )
4645
4746 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
4847 return batch .column (self .col .value )
@@ -58,11 +57,10 @@ def test_type_bound_fails_for_invalid_type(self) -> None:
5857 """Type bound validation should raise when predicate returns False."""
5958
6059 class TestFunc (ScalarFunction ):
61- col = Arg [AnyArrow ](0 , type_bound = pa .types .is_integer )
60+ class Meta :
61+ output_type = pa .int64 ()
6262
63- @classmethod
64- def catalog_output_type (cls ) -> pa .DataType :
65- return pa .int64 ()
63+ col = Arg [AnyArrow ](0 , type_bound = pa .types .is_integer )
6664
6765 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
6866 return batch .column (self .col .value )
@@ -78,14 +76,13 @@ def test_multiple_type_bounds_or_logic_passes(self) -> None:
7876 """When multiple predicates are given, any match should pass (OR logic)."""
7977
8078 class TestFunc (ScalarFunction ):
79+ class Meta :
80+ output_type = pa .float64 ()
81+
8182 col = Arg [AnyArrow ](
8283 0 , type_bound = [pa .types .is_integer , pa .types .is_floating ]
8384 )
8485
85- @classmethod
86- def catalog_output_type (cls ) -> pa .DataType :
87- return pa .float64 ()
88-
8986 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
9087 return batch .column (self .col .value )
9188
@@ -100,14 +97,13 @@ def test_multiple_type_bounds_or_logic_fails(self) -> None:
10097 """When multiple predicates fail, validation should raise."""
10198
10299 class TestFunc (ScalarFunction ):
100+ class Meta :
101+ output_type = pa .float64 ()
102+
103103 col = Arg [AnyArrow ](
104104 0 , type_bound = [pa .types .is_integer , pa .types .is_floating ]
105105 )
106106
107- @classmethod
108- def catalog_output_type (cls ) -> pa .DataType :
109- return pa .float64 ()
110-
111107 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
112108 return batch .column (self .col .value )
113109
@@ -123,11 +119,10 @@ def test_type_bound_on_non_anyarrow_warns(self) -> None:
123119 with pytest .warns (UserWarning , match = "only meaningful for Arg\\ [AnyArrow\\ ]" ):
124120
125121 class TestFunc (ScalarFunction ):
126- col = Arg [str ](0 , type_bound = pa .types .is_integer )
122+ class Meta :
123+ output_type = pa .string ()
127124
128- @classmethod
129- def catalog_output_type (cls ) -> pa .DataType :
130- return pa .string ()
125+ col = Arg [str ](0 , type_bound = pa .types .is_integer )
131126
132127 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
133128 return batch .column (self .col )
@@ -174,11 +169,10 @@ def test_error_message_includes_context(self) -> None:
174169 """Error messages should include argument name and predicate names."""
175170
176171 class TestFunc (ScalarFunction ):
177- my_column = Arg [AnyArrow ](0 , type_bound = pa .types .is_integer )
172+ class Meta :
173+ output_type = pa .int64 ()
178174
179- @classmethod
180- def catalog_output_type (cls ) -> pa .DataType :
181- return pa .int64 ()
175+ my_column = Arg [AnyArrow ](0 , type_bound = pa .types .is_integer )
182176
183177 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
184178 return batch .column (self .my_column .value )
@@ -205,11 +199,10 @@ def is_large_int(dtype: pa.DataType) -> bool:
205199 return dtype in (pa .int64 (), pa .uint64 ())
206200
207201 class TestFunc (ScalarFunction ):
208- col = Arg [AnyArrow ](0 , type_bound = is_large_int )
202+ class Meta :
203+ output_type = pa .int64 ()
209204
210- @classmethod
211- def catalog_output_type (cls ) -> pa .DataType :
212- return pa .int64 ()
205+ col = Arg [AnyArrow ](0 , type_bound = is_large_int )
213206
214207 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
215208 return batch .column (self .col .value )
@@ -230,11 +223,10 @@ def test_type_bound_with_lambda(self) -> None:
230223 """Lambda predicates should work and show in error messages."""
231224
232225 class TestFunc (ScalarFunction ):
233- col = Arg [AnyArrow ](0 , type_bound = lambda t : pa .types .is_integer (t ))
226+ class Meta :
227+ output_type = pa .int64 ()
234228
235- @classmethod
236- def catalog_output_type (cls ) -> pa .DataType :
237- return pa .int64 ()
229+ col = Arg [AnyArrow ](0 , type_bound = lambda t : pa .types .is_integer (t ))
238230
239231 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
240232 return batch .column (self .col .value )
@@ -261,11 +253,10 @@ def test_varargs_type_bound_passes_for_all_valid_types(self) -> None:
261253 """Type bound validation passes when all varargs elements are valid."""
262254
263255 class TestFunc (ScalarFunction ):
264- columns = Arg [AnyArrow ](0 , varargs = True , type_bound = pa .types .is_integer )
256+ class Meta :
257+ output_type = pa .int64 ()
265258
266- @classmethod
267- def catalog_output_type (cls ) -> pa .DataType :
268- return pa .int64 ()
259+ columns = Arg [AnyArrow ](0 , varargs = True , type_bound = pa .types .is_integer )
269260
270261 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
271262 # Sum all integer columns (varargs returns tuple at runtime)
@@ -288,11 +279,10 @@ def test_varargs_type_bound_fails_when_any_element_invalid(self) -> None:
288279 """Type bound validation should fail if any varargs element has invalid type."""
289280
290281 class TestFunc (ScalarFunction ):
291- columns = Arg [AnyArrow ](0 , varargs = True , type_bound = pa .types .is_integer )
282+ class Meta :
283+ output_type = pa .int64 ()
292284
293- @classmethod
294- def catalog_output_type (cls ) -> pa .DataType :
295- return pa .int64 ()
285+ columns = Arg [AnyArrow ](0 , varargs = True , type_bound = pa .types .is_integer )
296286
297287 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
298288 result = batch .column (self .columns [0 ]) # type: ignore[index]
@@ -313,14 +303,13 @@ def test_varargs_type_bound_with_multiple_predicates(self) -> None:
313303 """Varargs with multiple type bounds should use OR logic per element."""
314304
315305 class TestFunc (ScalarFunction ):
306+ class Meta :
307+ output_type = pa .float64 ()
308+
316309 columns = Arg [AnyArrow ](
317310 0 , varargs = True , type_bound = [pa .types .is_integer , pa .types .is_floating ]
318311 )
319312
320- @classmethod
321- def catalog_output_type (cls ) -> pa .DataType :
322- return pa .float64 ()
323-
324313 def compute (self , batch : pa .RecordBatch ) -> pa .Array [Any ]:
325314 return batch .column (self .columns [0 ]) # type: ignore[index]
326315
0 commit comments