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

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


The following commit(s) were added to refs/heads/branch-4.x by this push:
     new 3909ebe6f254 [SPARK-60530][PYTHON] Drop redundant run-level 
fail_on_stopiteration in ArrowElementwiseUDFHandler
3909ebe6f254 is described below

commit 3909ebe6f25462ff103930f66b518553d535bf29
Author: Yicong Huang <[email protected]>
AuthorDate: Mon Oct 26 18:50:05 2026 +0000

    [SPARK-60530][PYTHON] Drop redundant run-level fail_on_stopiteration in 
ArrowElementwiseUDFHandler
    
    ### What changes were proposed in this pull request?
    
    Remove the `fail_on_stopiteration` decorator on `_evaluate_elementwise_udf` 
in `ArrowElementwiseUDFHandler.run` (`SQL_ARROW_ELEMENTWISE_UDF`), and the 
now-unused import.
    
    ### Why are the changes needed?
    
    The handler keeps the default `_fail_on_stopiteration = True`, so 
`EvalTypeHandler.__init__` already wraps each UDF in `fail_on_stopiteration`. A 
`StopIteration` from the UDF becomes `STOP_ITERATION_OCCURRED` at that inner 
layer, on both the sequential path and inside the `ThreadPoolExecutor` path, so 
the outer decorator never sees a `StopIteration`.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No.
    
    ### How was this patch tested?
    
    Extended `test_stop_iteration_raises_runtime_error` in 
`test_elementwise_eval_type_handlers.py` to cover both the sequential and the 
thread-pool (`arrow.concurrency.level > 0`) paths and assert the 
`STOP_ITERATION_OCCURRED` condition.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Opus 5.5
    
    This pull request and its description were written by Isaac.
    
    Closes #59775 from Yicong-Huang/elementwise-drop-double-stopiteration-wrap.
    
    Authored-by: Yicong Huang <[email protected]>
    Signed-off-by: Yicong-Huang <[email protected]>
    (cherry picked from commit 6c9dcb9b354d378e39b6321af58d64e86f26441e)
    Signed-off-by: Yicong-Huang <[email protected]>
---
 python/pyspark/eval_handlers/_elementwise.py                 |  3 +--
 .../tests/test_elementwise_eval_type_handlers.py             | 12 +++++++++---
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/python/pyspark/eval_handlers/_elementwise.py 
b/python/pyspark/eval_handlers/_elementwise.py
index c5a1ce4e3dd3..66d5994039b4 100644
--- a/python/pyspark/eval_handlers/_elementwise.py
+++ b/python/pyspark/eval_handlers/_elementwise.py
@@ -57,7 +57,7 @@ from pyspark.sql.conversion import (
 from pyspark.sql.pandas.types import to_arrow_type
 from pyspark.sql.pandas.utils import require_minimum_pyarrow_version
 from pyspark.sql.types import ArrayType, DataType, StructField, StructType
-from pyspark.util import PythonEvalType, fail_on_stopiteration
+from pyspark.util import PythonEvalType
 
 if TYPE_CHECKING:
     import pyarrow as pa
@@ -240,7 +240,6 @@ class 
ArrowElementwiseUDFHandler(BatchEvalTypeHandler["pa.RecordBatch"]):
     def run(self, split_index: int, data: Iterator[pa.RecordBatch]) -> 
Iterator[pa.RecordBatch]:
         import pyarrow as pa
 
-        @fail_on_stopiteration
         def _evaluate_elementwise_udf(udf_func: Any, rows: Iterator[tuple]) -> 
list[Any]:
             if self._runner_conf.arrow_concurrency_level <= 0:
                 return [udf_func(*row) for row in rows]
diff --git 
a/python/pyspark/eval_handlers/tests/test_elementwise_eval_type_handlers.py 
b/python/pyspark/eval_handlers/tests/test_elementwise_eval_type_handlers.py
index 9dbf346607bf..2b018efc46c7 100644
--- a/python/pyspark/eval_handlers/tests/test_elementwise_eval_type_handlers.py
+++ b/python/pyspark/eval_handlers/tests/test_elementwise_eval_type_handlers.py
@@ -216,9 +216,15 @@ class 
ArrowElementwiseUDFHandlerTests(ElementwiseEvalTypeHandlerTestCase):
         def stop(x):
             raise StopIteration()
 
-        handler = self._handler(ArrowElementwiseUDFHandler, (stop, [0], {}, 
LongType()))
-        with self.assertRaises(PySparkRuntimeError):
-            list(handler.run(0, iter([self._batch()])))
+        for level in ("0", "4"):
+            with self.subTest(concurrency_level=level):
+                conf = 
{"spark.sql.execution.pythonUDF.arrow.concurrency.level": level}
+                handler = self._handler(
+                    ArrowElementwiseUDFHandler, (stop, [0], {}, LongType()), 
runner_conf=conf
+                )
+                with self.assertRaises(PySparkRuntimeError) as ctx:
+                    list(handler.run(0, iter([self._batch()])))
+                self.assertEqual(ctx.exception.getCondition(), 
"STOP_ITERATION_OCCURRED")
 
 
 class ScalarElementwiseUDFHandlerTestsMixin:


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

Reply via email to