add __new__ method to deque iterator and reverse iterator (#2987)

* add __new__ method to deque iterator and reverse iterator
This commit is contained in:
Myunghoon Park authored and GitHub committed 2021-08-29 17:13:19 +03:00
1 parent 2aa58cc551
commit e4953efac1
3 files changed
+136 -8

No files matched your search

-4
View File
@@ -646,8 +646,6 @@ class TestBasic(unittest.TestCase):
self.assertEqual(id(e[-1]), id(e))
self.assertEqual(e.maxlen, d.maxlen)
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_iterator_pickle(self):
orig = deque(range(200))
data = [i*1.01 for i in orig]
@@ -729,8 +727,6 @@ class TestBasic(unittest.TestCase):
for s in ('abcd', range(2000)):
self.assertEqual(list(reversed(deque(s))), list(reversed(s)))
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_reversed_new(self):
klass = type(reversed(deque()))
for s in ('abcd', range(2000)):
+85
View File
@@ -0,0 +1,85 @@
from collections import deque
def test_deque_iterator__new__():
klass = type(iter(deque()))
s = 'abcd'
d = klass(deque(s))
assert (list(d) == list(s))
test_deque_iterator__new__()
def test_deque_iterator__new__positional_index():
klass = type(iter(deque()))
# index between 0 and len
for s in ('abcd', range(2000)):
for i in range(len(s)):
d = klass(deque(s), i)
assert (list(d) == list(s)[i:])
# negative index
for s in ('abcd', range(2000)):
for i in range(-1000, 0):
d = klass(deque(s), i)
assert (list(d) == list(s))
# index ge len
for s in ('abcd', range(2000)):
for i in range(len(s), 4000):
d = klass(deque(s), i)
assert (list(d) == list())
test_deque_iterator__new__positional_index()
def test_deque_iterator__new__not_using_keyword_index():
klass = type(iter(deque()))
for s in ('abcd', range(2000)):
for i in range(-1000, 4000):
d = klass(deque(s), index=i)
assert (list(d) == list(s))
test_deque_iterator__new__not_using_keyword_index()
def test_deque_reverse_iterator__new__positional_index():
klass = type(reversed(deque()))
# index between 0 and len
for s in ('abcd', range(2000)):
for i in range(len(s)):
d = klass(deque(s), i)
assert (list(d) == list(reversed(s))[i:])
# negative index
for s in ('abcd', range(2000)):
for i in range(-1000, 0):
d = klass(deque(s), i)
assert (list(d) == list(reversed(s)))
# index ge len
for s in ('abcd', range(2000)):
for i in range(len(s), 4000):
d = klass(deque(s), i)
assert (list(d) == list())
test_deque_reverse_iterator__new__positional_index()
def test_deque_reverse_iterator__new__not_using_keyword_index():
klass = type(reversed(deque()))
for s in ('abcd', range(2000)):
for i in range(-1000, 4000):
d = klass(deque(s), index=i)
assert (list(d) == list(reversed(s)))
test_deque_reverse_iterator__new__not_using_keyword_index()
+51 -4
View File
@@ -3,7 +3,7 @@ pub(crate) use _collections::make_module;
#[pymodule]
mod _collections {
use crate::common::lock::{PyRwLock, PyRwLockReadGuard, PyRwLockWriteGuard};
use crate::function::{FuncArgs, OptionalArg};
use crate::function::{FuncArgs, KwArgs, OptionalArg};
use crate::slots::{Comparable, Hashable, Iterable, PyComparisonOp, PyIter, Unhashable};
use crate::vm::ReprGuard;
use crate::VirtualMachine;
@@ -361,15 +361,14 @@ mod _collections {
}
#[pymethod(magic)]
fn reversed(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
fn reversed(zelf: PyRef<Self>) -> PyResult<PyReverseDequeIterator> {
let length = zelf.len();
Ok(PyReverseDequeIterator {
position: AtomicCell::new(length),
status: AtomicCell::new(if length > 0 { Active } else { Exhausted }),
length,
deque: zelf,
}
.into_object(vm))
})
}
#[pymethod]
@@ -581,6 +580,15 @@ mod _collections {
}
}
#[derive(FromArgs)]
struct DequeIterArgs {
#[pyarg(positional)]
deque: PyDequeRef,
#[pyarg(positional, optional)]
index: OptionalArg<isize>,
}
#[pyimpl(with(PyIter))]
impl PyDequeIterator {
pub(crate) fn new(deque: PyDequeRef) -> Self {
@@ -592,6 +600,26 @@ mod _collections {
}
}
#[pyslot]
fn tp_new(
cls: PyTypeRef,
DequeIterArgs { deque, index }: DequeIterArgs,
_kwargs: KwArgs,
vm: &VirtualMachine,
) -> PyResult<PyRef<Self>> {
let len = deque.len();
let iter = PyDequeIterator::new(deque);
if let OptionalArg::Present(index) = index {
let index = max(index, 0) as usize;
iter.position.store(min(index, len));
if len.le(&index) {
iter.status.store(Exhausted);
}
}
iter.into_ref_with_type(vm, cls)
}
#[pymethod(magic)]
fn length_hint(&self) -> usize {
match self.status.load() {
@@ -663,6 +691,25 @@ mod _collections {
}
}
#[pyslot]
fn tp_new(
cls: PyTypeRef,
DequeIterArgs { deque, index }: DequeIterArgs,
_kwargs: KwArgs,
vm: &VirtualMachine,
) -> PyResult<PyRef<Self>> {
let len = deque.len();
let iter = PyDeque::reversed(deque)?;
if let OptionalArg::Present(index) = index {
let index = max(index, 0) as usize;
if len.le(&index) {
iter.status.store(Exhausted);
}
iter.position.store(len.saturating_sub(index));
}
iter.into_ref_with_type(vm, cls)
}
#[pymethod(magic)]
fn reduce(
zelf: PyRef<Self>,