Skip to content

Commit e4a5ce2

Browse files
Add typed Protocols for FFI capsule exports (part of #1577)
Adds TableFunctionExportable, ExtensionOptionsExportable, and TaskContextProviderExportable Protocol classes describing the PyCapsule dunder methods DataFusion's Rust side already expects, following the existing TableProviderExportable pattern. No runtime behavior changes.
1 parent cc2ec5c commit e4a5ce2

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

python/datafusion/context.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,29 @@ class PhysicalOptimizerRuleExportable(Protocol):
145145
def __datafusion_physical_optimizer_rule__(self) -> object: ... # noqa: D105
146146

147147

148+
class ExtensionOptionsExportable(Protocol):
149+
"""Type hint for object that has __datafusion_extension_options__ PyCapsule.
150+
151+
The method returns a PyCapsule wrapping an ``FFI_ExtensionOptions``,
152+
typically produced by a separate compiled extension and consumed by
153+
:py:meth:`SessionConfig.with_extension`.
154+
"""
155+
156+
def __datafusion_extension_options__(self) -> object: ... # noqa: D105
157+
158+
159+
class TaskContextProviderExportable(Protocol):
160+
"""Type hint for object that has __datafusion_task_context_provider__ PyCapsule.
161+
162+
The method returns a PyCapsule wrapping an ``FFI_TaskContextProvider``.
163+
:py:class:`SessionContext` exposes one for its own task context; a
164+
separate compiled extension can decode it (or one of its own) using
165+
the matching Rust-side ``from_pycapsule`` helper.
166+
"""
167+
168+
def __datafusion_task_context_provider__(self) -> object: ... # noqa: D105
169+
170+
148171
class SessionConfig:
149172
"""Session configuration options."""
150173

@@ -337,12 +360,14 @@ def set(self, key: str, value: str) -> SessionConfig:
337360
self.config_internal = self.config_internal.set(key, value)
338361
return self
339362

340-
def with_extension(self, extension: Any) -> SessionConfig:
363+
def with_extension(self, extension: ExtensionOptionsExportable) -> SessionConfig:
341364
"""Create a new configuration using an extension.
342365
343366
Args:
344367
extension: A custom configuration extension object. These are
345-
shared from another DataFusion extension library.
368+
shared from another DataFusion extension library. It must expose
369+
an ``__datafusion_extension_options__`` PyCapsule, see
370+
:py:class:`ExtensionOptionsExportable`.
346371
347372
Returns:
348373
A new :py:class:`SessionConfig` object with the updated setting.

python/datafusion/user_defined.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,15 @@ def adapter(*args: Any, session: Any, **kwargs: Any) -> Any:
11211121
return adapter
11221122

11231123

1124+
class TableFunctionExportable(Protocol):
1125+
"""Type hint for object that has __datafusion_table_function__ PyCapsule.
1126+
1127+
https://datafusion.apache.org/python/user-guide/io/table_provider.html
1128+
"""
1129+
1130+
def __datafusion_table_function__(self, session: Any) -> object: ... # noqa: D105
1131+
1132+
11241133
class TableFunction:
11251134
"""Class for performing user-defined table functions (UDTF).
11261135
@@ -1131,7 +1140,7 @@ class TableFunction:
11311140
def __init__(
11321141
self,
11331142
name: str,
1134-
func: Callable[..., Any],
1143+
func: Callable[..., Any] | TableFunctionExportable,
11351144
ctx: SessionContext | None = None,
11361145
*,
11371146
with_session: bool = False,
@@ -1190,6 +1199,10 @@ def udtf(
11901199
with_session: bool = False,
11911200
) -> TableFunction: ...
11921201

1202+
@overload
1203+
@staticmethod
1204+
def udtf(func: TableFunctionExportable, name: str) -> TableFunction: ...
1205+
11931206
@staticmethod
11941207
def udtf(*args: Any, with_session: bool = False, **kwargs: Any):
11951208
"""Create a new User-Defined Table Function (UDTF).

0 commit comments

Comments
 (0)