itertools: defer dropwhile predicate validation (#8504)

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
This commit is contained in:
이광효 authored and GitHub committed 2026-08-13 04:32:35 +09:00
1 parent 7e6eaa8e3c
commit 1178841eab
2 files changed
+4 -6

No files matched your search

-1
View File
@@ -1260,7 +1260,6 @@ class TestBasicOps(unittest.TestCase):
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])
+4 -5
View File
@@ -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<bool>,
}
@@ -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));