Skip to content

Commit 90705a6

Browse files
timsaucerclaude
andcommitted
refactor(udf): add _from_internal classmethod to UDF wrappers
`SessionContext.udf` / `udaf` / `udwf` previously constructed wrapper objects by calling `__new__` directly and writing the private `_udf` / `_udaf` / `_udwf` attribute from outside the owning module. Three near-identical blocks coupled `context.py` to wrapper internals. Add a `_from_internal` classmethod on each wrapper that takes an already-constructed `df_internal` handle and returns a wrapper without re-running `__init__`. The lookup methods now collapse to a single call, the `__new__` bypass is documented on the wrapper class itself, and renaming the private field is a one-spot edit. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 3bdca9e commit 90705a6

2 files changed

Lines changed: 39 additions & 9 deletions

File tree

python/datafusion/context.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,9 +1354,7 @@ def udf(self, name: str) -> ScalarUDF:
13541354
"""
13551355
from datafusion.user_defined import ScalarUDF as _ScalarUDF # noqa: PLC0415
13561356

1357-
wrapper = _ScalarUDF.__new__(_ScalarUDF)
1358-
wrapper._udf = self.ctx.udf(name)
1359-
return wrapper
1357+
return _ScalarUDF._from_internal(self.ctx.udf(name))
13601358

13611359
def udaf(self, name: str) -> AggregateUDF:
13621360
"""Look up a registered aggregate UDF by name.
@@ -1387,9 +1385,7 @@ def udaf(self, name: str) -> AggregateUDF:
13871385
AggregateUDF as _AggregateUDF,
13881386
)
13891387

1390-
wrapper = _AggregateUDF.__new__(_AggregateUDF)
1391-
wrapper._udaf = self.ctx.udaf(name)
1392-
return wrapper
1388+
return _AggregateUDF._from_internal(self.ctx.udaf(name))
13931389

13941390
def udwf(self, name: str) -> WindowUDF:
13951391
"""Look up a registered window UDF by name.
@@ -1418,9 +1414,7 @@ def udwf(self, name: str) -> WindowUDF:
14181414
"""
14191415
from datafusion.user_defined import WindowUDF as _WindowUDF # noqa: PLC0415
14201416

1421-
wrapper = _WindowUDF.__new__(_WindowUDF)
1422-
wrapper._udwf = self.ctx.udwf(name)
1423-
return wrapper
1417+
return _WindowUDF._from_internal(self.ctx.udwf(name))
14241418

14251419
def udfs(self) -> list[str]:
14261420
"""Return the sorted names of all registered scalar UDFs.

python/datafusion/user_defined.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,18 @@ def __init__(
153153
name, func, input_fields, return_field, str(volatility)
154154
)
155155

156+
@classmethod
157+
def _from_internal(cls, internal: df_internal.ScalarUDF) -> ScalarUDF:
158+
"""Wrap an already-constructed internal ``ScalarUDF`` handle.
159+
160+
Used by :py:meth:`SessionContext.udf` to surface a function looked
161+
up from the session's function registry without re-running
162+
:py:meth:`__init__`.
163+
"""
164+
wrapper = cls.__new__(cls)
165+
wrapper._udf = internal
166+
return wrapper
167+
156168
@property
157169
def name(self) -> str:
158170
"""Return the registered name of this UDF.
@@ -453,6 +465,18 @@ def __init__(
453465
str(volatility),
454466
)
455467

468+
@classmethod
469+
def _from_internal(cls, internal: df_internal.AggregateUDF) -> AggregateUDF:
470+
"""Wrap an already-constructed internal ``AggregateUDF`` handle.
471+
472+
Used by :py:meth:`SessionContext.udaf` to surface a function looked
473+
up from the session's function registry without re-running
474+
:py:meth:`__init__`.
475+
"""
476+
wrapper = cls.__new__(cls)
477+
wrapper._udaf = internal
478+
return wrapper
479+
456480
@property
457481
def name(self) -> str:
458482
"""Return the registered name of this UDAF.
@@ -873,6 +897,18 @@ def __init__(
873897
name, func, input_types, return_type, str(volatility)
874898
)
875899

900+
@classmethod
901+
def _from_internal(cls, internal: df_internal.WindowUDF) -> WindowUDF:
902+
"""Wrap an already-constructed internal ``WindowUDF`` handle.
903+
904+
Used by :py:meth:`SessionContext.udwf` to surface a function looked
905+
up from the session's function registry without re-running
906+
:py:meth:`__init__`.
907+
"""
908+
wrapper = cls.__new__(cls)
909+
wrapper._udwf = internal
910+
return wrapper
911+
876912
@property
877913
def name(self) -> str:
878914
"""Return the registered name of this UDWF.

0 commit comments

Comments
 (0)