This is an automated email from the ASF dual-hosted git repository.

Yicong-Huang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/spark.git


The following commit(s) were added to refs/heads/master by this push:
     new 523ab88c1791 [SPARK-59942][PYTHON] Use real RunnerConf in Arrow eval 
type handler tests
523ab88c1791 is described below

commit 523ab88c17914e59ceed7094b2b2ae004c8a9178
Author: Yicong Huang <[email protected]>
AuthorDate: Fri Oct 2 05:26:32 2026 +0000

    [SPARK-59942][PYTHON] Use real RunnerConf in Arrow eval type handler tests
    
    ### What changes were proposed in this pull request?
    
    The Arrow eval type handler tests built handlers with a hand-written 
`_RunnerConf` stand-in that exposed only a few hard-coded fields. This replaces 
it with the worker's real `RunnerConf`, constructed from a plain conf dict 
(`RunnerConf({...})`), matching the pattern already used by the incremental 
aggregate/window handler tests added in SPARK-59727. Window-frame tests now 
pass the bound types through the real conf key 
(`RunnerConf({"window_bound_types": "unbounded"})` / `"bounded"`)  [...]
    
    ### Why are the changes needed?
    
    The fake config duplicated field defaults that can silently drift from the 
real `RunnerConf`, and it hid the actual conf keys the handlers read. Building 
the real config from a conf dict exercises the same code path as production and 
keeps the tests honest. This is a test improvement following the Arrow eval 
handler migrations under SPARK-59415.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. Test-only change.
    
    ### How was this patch tested?
    
    `pyspark.eval_handlers.tests.test_arrow_eval_type_handlers` and 
`pyspark.eval_handlers.tests.test_base_eval_type_handlers` pass (38 tests).
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 4.8
    
    This pull request and its description were written by Isaac.
    
    Closes #59195 from Yicong-Huang/arrow-eval-conf-test.
    
    Authored-by: Yicong Huang <[email protected]>
    Signed-off-by: Yicong-Huang <[email protected]>
---
 .../tests/test_arrow_eval_type_handlers.py         | 35 ++++++++--------------
 .../tests/test_base_eval_type_handlers.py          | 22 ++++++--------
 2 files changed, 22 insertions(+), 35 deletions(-)

diff --git 
a/python/pyspark/eval_handlers/tests/test_arrow_eval_type_handlers.py 
b/python/pyspark/eval_handlers/tests/test_arrow_eval_type_handlers.py
index 5c47ae609f41..e8a6cc24e5f8 100644
--- a/python/pyspark/eval_handlers/tests/test_arrow_eval_type_handlers.py
+++ b/python/pyspark/eval_handlers/tests/test_arrow_eval_type_handlers.py
@@ -57,17 +57,6 @@ if have_pyarrow:
     from pyspark.sql.conversion import ArrowBatchTransformer
 
 
-class _RunnerConf:
-    """Minimal stand-in for the worker's RunnerConf, exposing only the fields
-    the handlers under test read."""
-
-    use_large_var_types = False
-    assign_cols_by_name = True
-    map_in_batch_legacy_accept_any_iterable = False
-    # One bound type per window UDF; the bounded test overrides this per 
instance.
-    window_bound_types = ["unbounded"]
-
-
 class _SumAggregator:
     """Incremental ``Aggregator`` stub: sums non-null inputs, with a ``(sum, 
count)`` buffer.
 
@@ -136,7 +125,9 @@ def _scalar_handler(handler_cls, udf):
 
     The scalar UDF tuple is ``(func, args_offsets, kwargs_offsets, 
return_type)``.
     """
-    return handler_cls(udfs=[(udf, [0], {}, LongType())], 
runner_conf=_RunnerConf(), eval_conf=None)
+    return handler_cls(
+        udfs=[(udf, [0], {}, LongType())], runner_conf=RunnerConf({}), 
eval_conf=None
+    )
 
 
 def _grouped_handler(handler_cls, udf, arg_offsets, num_udf_args):
@@ -146,7 +137,7 @@ def _grouped_handler(handler_cls, udf, arg_offsets, 
num_udf_args):
     """
     return handler_cls(
         udfs=[(udf, arg_offsets, _RETURN_TYPE, num_udf_args)],
-        runner_conf=_RunnerConf(),
+        runner_conf=RunnerConf({}),
         eval_conf=None,
     )
 
@@ -240,7 +231,7 @@ class ArrowMapUDFHandlerTests(unittest.TestCase):
                 yield _batch(v=[c.as_py() * 2 for c in batch.column("v")])
 
         handler = ArrowMapUDFHandler(
-            udfs=[(double_v, None, None, None)], runner_conf=_RunnerConf(), 
eval_conf=None
+            udfs=[(double_v, None, None, None)], runner_conf=RunnerConf({}), 
eval_conf=None
         )
         out = list(handler.run(0, iter([_struct_batch(v=[1, 2, 3])])))
         self.assertEqual(out[0].column(0).field("v").to_pylist(), [2, 4, 6])
@@ -320,7 +311,7 @@ class ArrowGroupedAggUDFHandlerTests(unittest.TestCase):
             return sum(c.as_py() for c in col)
 
         handler = ArrowGroupedAggUDFHandler(
-            udfs=[(sum_udf, [0], {}, LongType())], runner_conf=_RunnerConf(), 
eval_conf=None
+            udfs=[(sum_udf, [0], {}, LongType())], runner_conf=RunnerConf({}), 
eval_conf=None
         )
         out = list(handler.run(0, _one_group(_batch(v=[1, 2, 3]), 
_batch(v=[4]))))
         self.assertEqual(out[0].column("_0").to_pylist(), [10])
@@ -334,7 +325,7 @@ class ArrowGroupedAggIterUDFHandlerTests(unittest.TestCase):
             return sum(c.as_py() for col in col_iter for c in col)
 
         handler = ArrowGroupedAggIterUDFHandler(
-            udfs=[(sum_iter_udf, [0], {}, LongType())], 
runner_conf=_RunnerConf(), eval_conf=None
+            udfs=[(sum_iter_udf, [0], {}, LongType())], 
runner_conf=RunnerConf({}), eval_conf=None
         )
         out = list(handler.run(0, _one_group(_batch(v=[10]), _batch(v=[20]))))
         self.assertEqual(out[0].column("_0").to_pylist(), [30])
@@ -347,10 +338,10 @@ class ArrowWindowAggUDFHandlerTests(unittest.TestCase):
         def sum_udf(col):
             return sum(c.as_py() for c in col)
 
-        conf = _RunnerConf()
-        conf.window_bound_types = ["unbounded"]
         handler = ArrowWindowAggUDFHandler(
-            udfs=[(sum_udf, [0], {}, LongType())], runner_conf=conf, 
eval_conf=None
+            udfs=[(sum_udf, [0], {}, LongType())],
+            runner_conf=RunnerConf({"window_bound_types": "unbounded"}),
+            eval_conf=None,
         )
         out = list(handler.run(0, _one_group(_batch(v=[1, 2, 3]))))
         self.assertEqual(out[0].column("_0").to_pylist(), [6, 6, 6])
@@ -360,10 +351,10 @@ class ArrowWindowAggUDFHandlerTests(unittest.TestCase):
         def sum_udf(col):
             return sum(c.as_py() for c in col)
 
-        conf = _RunnerConf()
-        conf.window_bound_types = ["bounded"]
         handler = ArrowWindowAggUDFHandler(
-            udfs=[(sum_udf, [0, 1, 2], {}, LongType())], runner_conf=conf, 
eval_conf=None
+            udfs=[(sum_udf, [0, 1, 2], {}, LongType())],
+            runner_conf=RunnerConf({"window_bound_types": "bounded"}),
+            eval_conf=None,
         )
         # Row 0 frame [0, 1) -> [10]; row 1 frame [0, 2) -> [10, 20].
         out = list(handler.run(0, _one_group(_batch(begin=[0, 0], end=[1, 2], 
v=[10, 20]))))
diff --git a/python/pyspark/eval_handlers/tests/test_base_eval_type_handlers.py 
b/python/pyspark/eval_handlers/tests/test_base_eval_type_handlers.py
index c5fff82312ac..5fe45119bc88 100644
--- a/python/pyspark/eval_handlers/tests/test_base_eval_type_handlers.py
+++ b/python/pyspark/eval_handlers/tests/test_base_eval_type_handlers.py
@@ -21,7 +21,9 @@ Handler-flavor tests live alongside their module, e.g. the 
Arrow handlers in
 ``test_arrow_eval_type_handlers``.
 """
 
+import os
 import unittest
+from unittest.mock import patch
 
 from pyspark.eval_handlers._base import (
     BatchEvalTypeHandler,
@@ -37,14 +39,8 @@ from pyspark.sql.pandas.serializers import (
     ArrowStreamSerializer,
 )
 
-
-class _RunnerConf:
-    """Minimal stand-in for the worker's RunnerConf, exposing only the fields
-    the handlers under test read."""
-
-    use_large_var_types = False
-    assign_cols_by_name = True
-    map_in_batch_legacy_accept_any_iterable = False
+with patch.dict(os.environ, {"SPARK_PYTHON_RUNTIME": "PYTHON_WORKER"}):
+    from pyspark.worker_util import RunnerConf
 
 
 class EvalTypeHandlerTests(unittest.TestCase):
@@ -58,7 +54,7 @@ class EvalTypeHandlerTests(unittest.TestCase):
             CoGroupedEvalTypeHandler,
         ):
             with self.assertRaises(TypeError):
-                base([], _RunnerConf(), None)
+                base([], RunnerConf({}), None)
 
     def test_category_bases_are_not_registered(self):
         # Only concrete subclasses that declare an eval type are registered.
@@ -84,12 +80,12 @@ class EvalTypeHandlerTests(unittest.TestCase):
             def run(self, split_index, data):
                 return data
 
-        self.assertIsInstance(_Batch([], _RunnerConf(), None).serializer, 
ArrowStreamSerializer)
+        self.assertIsInstance(_Batch([], RunnerConf({}), None).serializer, 
ArrowStreamSerializer)
         self.assertIsInstance(
-            _Grouped([], _RunnerConf(), None).serializer, 
ArrowStreamGroupSerializer
+            _Grouped([], RunnerConf({}), None).serializer, 
ArrowStreamGroupSerializer
         )
         self.assertIsInstance(
-            _CoGrouped([], _RunnerConf(), None).serializer, 
ArrowStreamCoGroupSerializer
+            _CoGrouped([], RunnerConf({}), None).serializer, 
ArrowStreamCoGroupSerializer
         )
 
     def test_run_produces_output(self):
@@ -98,7 +94,7 @@ class EvalTypeHandlerTests(unittest.TestCase):
                 for item in data:
                     yield item * 2
 
-        handler = _Doubler([], _RunnerConf(), None)
+        handler = _Doubler([], RunnerConf({}), None)
         self.assertEqual(list(handler.run(0, iter([1, 2, 3]))), [2, 4, 6])
 
     def test_duplicate_eval_type_rejected(self):


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to