Skip to content

Commit 95eee71

Browse files
timsaucerclaude
andcommitted
feat: type SessionContext codec setters with exportable Protocols
PR #1541 introduced `with_logical_extension_codec` / `with_physical_extension_codec` setters typed as `codec: Any`. The Rust extractors accept either a raw `PyCapsule` or any object exposing `__datafusion_logical_extension_codec__` / `__datafusion_physical_extension_codec__`. Add `LogicalExtensionCodecExportable` / `PhysicalExtensionCodecExportable` Protocols in `python/datafusion/user_defined.py` (matching the existing `ScalarUDFExportable` pattern) and tighten both setter signatures to `Protocol | _PyCapsule`. Pure typing change; no runtime behavior diff. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a2e086d commit 95eee71

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

python/datafusion/context.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,16 @@
8686

8787
import pandas as pd
8888
import polars as pl # type: ignore[import]
89+
from _typeshed import CapsuleType as _PyCapsule
8990

9091
from datafusion.catalog import CatalogProvider, Table
9192
from datafusion.common import DFSchema
9293
from datafusion.expr import Expr, SortKey
9394
from datafusion.plan import ExecutionPlan, LogicalPlan
9495
from datafusion.user_defined import (
9596
AggregateUDF,
97+
LogicalExtensionCodecExportable,
98+
PhysicalExtensionCodecExportable,
9699
ScalarUDF,
97100
TableFunction,
98101
WindowUDF,
@@ -1744,11 +1747,15 @@ def __datafusion_logical_extension_codec__(self) -> Any:
17441747
"""Access the PyCapsule FFI_LogicalExtensionCodec."""
17451748
return self.ctx.__datafusion_logical_extension_codec__()
17461749

1747-
def with_logical_extension_codec(self, codec: Any) -> SessionContext:
1750+
def with_logical_extension_codec(
1751+
self, codec: LogicalExtensionCodecExportable | _PyCapsule
1752+
) -> SessionContext:
17481753
"""Create a new session context with specified codec.
17491754
17501755
This only supports codecs that have been implemented using the
1751-
FFI interface.
1756+
FFI interface. ``codec`` must either be a raw ``FFI_LogicalExtensionCodec``
1757+
``PyCapsule`` or an object exposing
1758+
``__datafusion_logical_extension_codec__``.
17521759
"""
17531760
new_internal = self.ctx.with_logical_extension_codec(codec)
17541761
new = SessionContext.__new__(SessionContext)
@@ -1759,11 +1766,15 @@ def __datafusion_physical_extension_codec__(self) -> Any:
17591766
"""Access the PyCapsule FFI_PhysicalExtensionCodec."""
17601767
return self.ctx.__datafusion_physical_extension_codec__()
17611768

1762-
def with_physical_extension_codec(self, codec: Any) -> SessionContext:
1769+
def with_physical_extension_codec(
1770+
self, codec: PhysicalExtensionCodecExportable | _PyCapsule
1771+
) -> SessionContext:
17631772
"""Create a new session context with the specified physical codec.
17641773
17651774
This only supports codecs that have been implemented using the
1766-
FFI interface.
1775+
FFI interface. ``codec`` must either be a raw
1776+
``FFI_PhysicalExtensionCodec`` ``PyCapsule`` or an object exposing
1777+
``__datafusion_physical_extension_codec__``.
17671778
"""
17681779
new_internal = self.ctx.with_physical_extension_codec(codec)
17691780
new = SessionContext.__new__(SessionContext)

python/datafusion/user_defined.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,18 @@ def _is_pycapsule(value: object) -> TypeGuard[_PyCapsule]:
113113
return value.__class__.__name__ == "PyCapsule"
114114

115115

116+
class LogicalExtensionCodecExportable(Protocol):
117+
"""Type hint for objects exposing ``__datafusion_logical_extension_codec__``."""
118+
119+
def __datafusion_logical_extension_codec__(self) -> object: ... # noqa: D105
120+
121+
122+
class PhysicalExtensionCodecExportable(Protocol):
123+
"""Type hint for objects exposing ``__datafusion_physical_extension_codec__``."""
124+
125+
def __datafusion_physical_extension_codec__(self) -> object: ... # noqa: D105
126+
127+
116128
class ScalarUDF:
117129
"""Class for performing scalar user-defined functions (UDF).
118130

0 commit comments

Comments
 (0)