From d918a7e20da6f718f3189f445c4f1cdaf3dfbfa3 Mon Sep 17 00:00:00 2001 From: "widehyo@gmail.com" Date: Sun, 9 Aug 2026 14:43:25 +0900 Subject: [PATCH] itertools: defer dropwhile predicate validation Store the `dropwhile` predicate as a Python object and call it while advancing the iterator. This defers callable validation until the predicate is first needed, matching CPython for empty input while preserving exception propagation during iteration. Remove the now-passing `test_dropwhile` expected-failure marker. Assisted-by: Codex:gpt-5.6-sol --- Lib/test/test_itertools.py | 1 - crates/vm/src/stdlib/itertools.rs | 9 ++++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 585f6611ade..b91e3735d94 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -1260,7 +1260,6 @@ def test_takewhile(self): self.assertEqual(list(t), [1, 1, 1]) self.assertRaises(StopIteration, next, t) - @unittest.expectedFailure # TODO: RUSTPYTHON def test_dropwhile(self): data = [1, 3, 5, 20, 2, 4, 6, 8] self.assertEqual(list(dropwhile(underten, data)), [20, 2, 4, 6, 8]) diff --git a/crates/vm/src/stdlib/itertools.rs b/crates/vm/src/stdlib/itertools.rs index 041620298e7..30a4d8773be 100644 --- a/crates/vm/src/stdlib/itertools.rs +++ b/crates/vm/src/stdlib/itertools.rs @@ -10,7 +10,7 @@ mod decl { rc::PyRc, }, convert::ToPyObject, - function::{ArgCallable, FuncArgs, OptionalArg, OptionalOption, PosArgs}, + function::{FuncArgs, OptionalArg, OptionalOption, PosArgs}, protocol::{PyIter, PyIterReturn, PyNumber}, raise_if_stop, stdlib::sys, @@ -477,7 +477,7 @@ mod decl { #[pyclass(name = "dropwhile")] #[derive(Debug, PyPayload)] struct PyItertoolsDropwhile { - predicate: ArgCallable, + predicate: PyObjectRef, iterable: PyIter, start_flag: AtomicCell, } @@ -485,7 +485,7 @@ mod decl { #[derive(FromArgs)] struct DropwhileNewArgs { #[pyarg(positional)] - predicate: ArgCallable, + predicate: PyObjectRef, #[pyarg(positional)] iterable: PyIter, } @@ -522,8 +522,7 @@ mod decl { if !zelf.start_flag.load() { loop { let obj = raise_if_stop!(iterable.next(vm)?); - let pred = predicate.clone(); - let pred_value = pred.invoke((obj.clone(),), vm)?; + let pred_value = predicate.call((obj.clone(),), vm)?; if !pred_value.try_to_bool(vm)? { zelf.start_flag.store(true); return Ok(PyIterReturn::Return(obj));