Skip to main content
Vane Data / Reference

vane.cls

vane.cls converts a callable class into an Actor-backed scalar Expression UDF. Each Actor owns an independent instance, allowing a model, client, or reconstructible cache to be reused.

Signature

text
vane.cls(
    class_: type | None = None,
    *,
    actor_number: int | None = None,
    return_dtype: Any | None = None,
    name: str | None = None,
    gpus: float | None = 0,
) -> VaneClass | Callable[[type], VaneClass]

Parameters

NameTypeDescriptionDefault
class_Callable class or NoneClass to wrap. Omitting it returns a decoratorNone
actor_numberPositive integerNumber of independent Actor instances. Booleans, floats, and numeric strings are invalidRequired
return_dtypeSQL type string, Vane DuckDBPyType, or supported pyarrow.DataTypeScalar Expression result type; it is not inferredRequired
nameNon-empty str or NoneUDF name in the plan; defaults to the class __qualname__None
gpusFinite non-negative number or NoneGPU resource per Actor; positive values require Ray0

Returns and errors

Instantiate the decorated class, then use the instance in select(). Each input row produces one result of type return_dtype.

In a query, an input SQL NULL propagates to the result without calling __call__. A direct call keeps normal Python semantics and passes None to the local eager instance.

Query Actors are independent and work has no Actor affinity or global ordering. Actor reconstruction resets local state, so instance state must be a reconstructible resource or cache rather than shared or durable query state.

vane.cls validates the decorated class and its decorator options when the decorator is applied. The user constructor runs when the eager instance or a query Actor is created, and __call__ errors raise when the callable runs. In a query, values that do not match the declared return type raise when results are fetched. Distributed backends may retry calls, so external effects must be idempotent.

Example

example.py
import vane




@vane.cls(actor_number=2, return_dtype="VARCHAR")
class Prefix:
    def __init__(self, prefix):
        self.prefix = prefix


    def __call__(self, value):
        return f"{self.prefix}{value}"




prefix = Prefix("item-")
source = vane.sql("SELECT * FROM (VALUES (1), (2), (3)) AS t(value)")
result = source.select(prefix(vane.col("value")).alias("value"))


print(result.order("value").fetchall())
vane.close()

Output:

text
[('item-1',), ('item-2',), ('item-3',)]

Prefix("item-") captures the constructor argument without creating query Actors. At execution time, each Actor constructs an independent Prefix instance with that argument.