Skip to content

Commit e39311c

Browse files
timsaucerclaude
andcommitted
refactor(ctx): make with_python_udf_inlining enabled keyword-only
`ctx.with_python_udf_inlining(True)` and `ctx.with_python_udf_inlining(False)` read identically at the call site — a bare positional `True` / `False` does not convey which direction the toggle moves. Forcing `enabled=` at the call site disambiguates: `with_python_udf_inlining(enabled=False)` is unambiguously the opt-out form. The Rust constructor stays positional (internal API); only the public Python wrapper changes signature. All in-tree callers (tests, docs, FFI example test) already used or now use the keyword form. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 69b0ddb commit e39311c

4 files changed

Lines changed: 20 additions & 14 deletions

File tree

docs/source/user-guide/io/distributing_work.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ worker slots are unused.
170170
To opt into the strict format,
171171
:py:func:`~datafusion.ipc.set_sender_ctx`
172172
with a session built via
173-
:py:meth:`SessionContext.with_python_udf_inlining(False)
173+
:py:meth:`SessionContext.with_python_udf_inlining(enabled=False)
174174
<datafusion.SessionContext.with_python_udf_inlining>`.
175175

176176
2. *Worker side — what registrations does decode need?* For built-ins
@@ -265,7 +265,7 @@ Disabling Python UDF inlining
265265
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
266266

267267
For a stricter wire format, call
268-
:py:meth:`SessionContext.with_python_udf_inlining(False)
268+
:py:meth:`SessionContext.with_python_udf_inlining(enabled=False)
269269
<datafusion.SessionContext.with_python_udf_inlining>` on the session
270270
producing or consuming the bytes. With inlining disabled, Python
271271
UDFs travel by name only — the same way FFI-capsule UDFs do — and
@@ -295,7 +295,7 @@ session as the driver's *sender context*:
295295
from datafusion import SessionContext
296296
from datafusion.ipc import set_sender_ctx
297297
298-
set_sender_ctx(SessionContext().with_python_udf_inlining(False))
298+
set_sender_ctx(SessionContext().with_python_udf_inlining(enabled=False))
299299
# Every subsequent pickle.dumps(expr) on this thread encodes
300300
# without inlining the Python callable.
301301

python/datafusion/context.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1770,9 +1770,15 @@ def with_physical_extension_codec(self, codec: Any) -> SessionContext:
17701770
new.ctx = new_internal
17711771
return new
17721772

1773-
def with_python_udf_inlining(self, enabled: bool) -> SessionContext:
1773+
def with_python_udf_inlining(self, *, enabled: bool) -> SessionContext:
17741774
"""Toggle inline encoding of Python-defined UDFs on this session.
17751775
1776+
``enabled`` is keyword-only:
1777+
``with_python_udf_inlining(enabled=False)`` reads at the call
1778+
site as the inverse of
1779+
``with_python_udf_inlining(enabled=True)``, where a positional
1780+
``True`` / ``False`` would not.
1781+
17761782
When ``True`` (the default), Python scalar, aggregate, and window
17771783
UDFs travel inside the serialized expression and are
17781784
reconstructed on the receiver without pre-registration.

python/datafusion/ipc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def init_worker():
4949
from datafusion import SessionContext
5050
from datafusion.ipc import set_sender_ctx
5151
52-
driver_ctx = SessionContext().with_python_udf_inlining(False)
52+
driver_ctx = SessionContext().with_python_udf_inlining(enabled=False)
5353
set_sender_ctx(driver_ctx)
5454
pickle.dumps(expr) # encoded with inlining disabled
5555

python/tests/test_pickle_expr.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ def test_window_udf_decodes_via_pickle_with_no_worker_ctx(self):
247247

248248

249249
class TestPythonUdfInliningToggle:
250-
"""`SessionContext.with_python_udf_inlining(False)` opts out of
250+
"""`SessionContext.with_python_udf_inlining(enabled=False)` opts out of
251251
inline Python UDF encoding for both encode and decode paths."""
252252

253253
def _build_double_udf(self):
@@ -263,7 +263,7 @@ def test_strict_encoder_emits_smaller_blob(self):
263263
"""Strict mode skips cloudpickle of the Python callable, so the
264264
encoded bytes are dramatically smaller than the inline form."""
265265
ctx_inline = SessionContext()
266-
ctx_strict = ctx_inline.with_python_udf_inlining(False)
266+
ctx_strict = ctx_inline.with_python_udf_inlining(enabled=False)
267267
u = self._build_double_udf()
268268
e = u(col("a"))
269269

@@ -276,11 +276,11 @@ def test_strict_roundtrip_via_registry(self):
276276
"""When both sender and receiver disable inlining, the UDF
277277
travels by name only and the receiver resolves it from its
278278
registered functions."""
279-
strict_sender = SessionContext().with_python_udf_inlining(False)
279+
strict_sender = SessionContext().with_python_udf_inlining(enabled=False)
280280
u = self._build_double_udf()
281281
blob = u(col("a")).to_bytes(strict_sender)
282282

283-
receiver = SessionContext().with_python_udf_inlining(False)
283+
receiver = SessionContext().with_python_udf_inlining(enabled=False)
284284
receiver.register_udf(u)
285285
restored = Expr.from_bytes(blob, ctx=receiver)
286286
assert "double" in restored.canonical_name()
@@ -292,7 +292,7 @@ def test_strict_decoder_refuses_inline_payload(self):
292292
u = self._build_double_udf()
293293
blob = u(col("a")).to_bytes(sender)
294294

295-
strict_receiver = SessionContext().with_python_udf_inlining(False)
295+
strict_receiver = SessionContext().with_python_udf_inlining(enabled=False)
296296
strict_receiver.register_udf(u)
297297
# `RuntimeError` (not bare `Exception`): the codec refusal is
298298
# surfaced through `parse_expr` → `PyRuntimeError`. Tightening
@@ -314,7 +314,7 @@ def test_sender_ctx_propagates_through_pickle(self):
314314

315315
blob_default = pickle.dumps(e)
316316

317-
strict_sender = SessionContext().with_python_udf_inlining(False)
317+
strict_sender = SessionContext().with_python_udf_inlining(enabled=False)
318318
set_sender_ctx(strict_sender)
319319
try:
320320
blob_strict = pickle.dumps(e)
@@ -333,14 +333,14 @@ def test_sender_ctx_strict_roundtrip_via_pickle(self):
333333
u = self._build_double_udf()
334334
e = u(col("a"))
335335

336-
strict_sender = SessionContext().with_python_udf_inlining(False)
336+
strict_sender = SessionContext().with_python_udf_inlining(enabled=False)
337337
set_sender_ctx(strict_sender)
338338
try:
339339
blob = pickle.dumps(e)
340340
finally:
341341
clear_sender_ctx()
342342

343-
worker = SessionContext().with_python_udf_inlining(False)
343+
worker = SessionContext().with_python_udf_inlining(enabled=False)
344344
worker.register_udf(u)
345345
set_worker_ctx(worker)
346346
try:
@@ -358,7 +358,7 @@ def test_sender_ctx_strict_pickle_accepted_by_inline_worker_with_registry(self):
358358
u = self._build_double_udf()
359359
e = u(col("a"))
360360

361-
strict_sender = SessionContext().with_python_udf_inlining(False)
361+
strict_sender = SessionContext().with_python_udf_inlining(enabled=False)
362362
set_sender_ctx(strict_sender)
363363
try:
364364
blob = pickle.dumps(e)

0 commit comments

Comments
 (0)