Skip to content

Commit e1854ce

Browse files
committed
itertools.dropwhile: Implement itertools.dropwhile
1 parent cfeb746 commit e1854ce

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

tests/snippets/stdlib_itertools.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,4 +200,13 @@ def assert_matches_seq(it, seq):
200200
assert None == next(it)
201201
assert False == next(it)
202202
assert [] == next(it)
203-
assert {} == next(it)
203+
assert {} == next(it)
204+
205+
206+
# itertools.dropwhile
207+
it = itertools.dropwhile(lambda x: x<5, [1,4,6,4,1])
208+
assert 6 == next(it)
209+
assert 4 == next(it)
210+
assert 1 == next(it)
211+
with assertRaises(StopIteration):
212+
next(it)

vm/src/stdlib/itertools.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,69 @@ impl PyItertoolsTakewhile {
290290
}
291291
}
292292

293+
#[pyclass]
294+
#[derive(Debug)]
295+
struct PyItertoolsDropwhile {
296+
predicate: PyObjectRef,
297+
iterable: PyObjectRef,
298+
start_flag: RefCell<bool>,
299+
}
300+
301+
impl PyValue for PyItertoolsDropwhile {
302+
fn class(vm: &VirtualMachine) -> PyClassRef {
303+
vm.class("itertools", "dropwhile")
304+
}
305+
}
306+
307+
#[pyimpl]
308+
impl PyItertoolsDropwhile {
309+
#[pymethod(name = "__new__")]
310+
#[allow(clippy::new_ret_no_self)]
311+
fn new(
312+
_cls: PyClassRef,
313+
predicate: PyObjectRef,
314+
iterable: PyObjectRef,
315+
vm: &VirtualMachine,
316+
) -> PyResult {
317+
let iter = get_iter(vm, &iterable)?;
318+
319+
Ok(PyItertoolsDropwhile {
320+
predicate,
321+
iterable: iter,
322+
start_flag: RefCell::new(false),
323+
}
324+
.into_ref(vm)
325+
.into_object())
326+
}
327+
328+
#[pymethod(name = "__next__")]
329+
fn next(&self, vm: &VirtualMachine) -> PyResult {
330+
let predicate = &self.predicate;
331+
let iterable = &self.iterable;
332+
333+
if !*self.start_flag.borrow_mut() {
334+
loop {
335+
let obj = call_next(vm, iterable)?;
336+
let pred_value = vm.invoke(predicate, vec![obj.clone()])?;
337+
if !objbool::boolval(vm, pred_value)? {
338+
*self.start_flag.borrow_mut() = true;
339+
return Ok(obj);
340+
}
341+
}
342+
}
343+
344+
loop {
345+
let obj = call_next(vm, iterable)?;
346+
return Ok(obj);
347+
}
348+
}
349+
350+
#[pymethod(name = "__iter__")]
351+
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
352+
zelf
353+
}
354+
}
355+
293356
#[pyclass(name = "islice")]
294357
#[derive(Debug)]
295358
struct PyItertoolsIslice {
@@ -484,6 +547,9 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
484547
let count = ctx.new_class("count", ctx.object());
485548
PyItertoolsCount::extend_class(ctx, &count);
486549

550+
let dropwhile = ctx.new_class("dropwhile", ctx.object());
551+
PyItertoolsDropwhile::extend_class(ctx, &dropwhile);
552+
487553
let repeat = ctx.new_class("repeat", ctx.object());
488554
PyItertoolsRepeat::extend_class(ctx, &repeat);
489555

@@ -500,6 +566,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
500566
py_module!(vm, "itertools", {
501567
"chain" => chain,
502568
"count" => count,
569+
"dropwhile" => dropwhile,
503570
"repeat" => repeat,
504571
"starmap" => starmap,
505572
"takewhile" => takewhile,

0 commit comments

Comments
 (0)