Call __length_hint__ on object to be extracted.

This commit is contained in:
jfh committed 2021-09-04 15:04:32 +03:00
1 parent 54e8c71c3e
commit 022eb28c09
4 files changed
+23 -13

No files matched your search

-2
View File
@@ -252,8 +252,6 @@ class NoneLengthHint(object):
class TestLengthHintExceptions(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_issue1242657(self):
self.assertRaises(RuntimeError, list, BadLen())
self.assertRaises(RuntimeError, list, BadLengthHint())
+7 -8
View File
@@ -6,7 +6,7 @@ use crate::builtins::int::{self, PyInt};
use crate::builtins::iter::PySequenceIterator;
use crate::exceptions::PyBaseExceptionRef;
use crate::vm::VirtualMachine;
use crate::{IdProtocol, PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol};
use crate::{IdProtocol, PyObjectRef, PyResult, PyValue, TypeProtocol};
use num_traits::Signed;
/*
@@ -73,16 +73,15 @@ pub fn get_next_object(
}
}
/* Retrieve all elements from an iterator */
pub fn get_all<T: TryFromObject>(vm: &VirtualMachine, iter_obj: &PyObjectRef) -> PyResult<Vec<T>> {
try_map(vm, iter_obj, |obj| T::try_from_object(vm, obj))
}
pub fn try_map<F, R>(vm: &VirtualMachine, iter_obj: &PyObjectRef, mut f: F) -> PyResult<Vec<R>>
pub fn try_map<F, R>(
vm: &VirtualMachine,
iter_obj: &PyObjectRef,
cap: usize,
mut f: F,
) -> PyResult<Vec<R>>
where
F: FnMut(PyObjectRef) -> PyResult<R>,
{
let cap = length_hint(vm, iter_obj.clone())?.unwrap_or(0);
// TODO: fix extend to do this check (?), see test_extend in Lib/test/list_tests.py,
// https://github.com/python/cpython/blob/v3.9.0/Objects/listobject.c#L922-L928
if cap >= isize::max_value() as usize {
-1
View File
@@ -204,7 +204,6 @@ mod _collections {
#[pymethod]
fn extend(&self, iter: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
// TODO: use length_hint here and for extendleft
self.state.fetch_add(1);
let max_len = self.maxlen;
let mut elements: Vec<PyObjectRef> = vm.extract_elements(&iter)?;
+16 -2
View File
@@ -1261,7 +1261,13 @@ impl VirtualMachine {
.collect()
} else {
let iter = iterator::get_iter(self, value.clone())?;
iterator::try_map(self, &iter, |obj| func(obj))
let cap = match iterator::length_hint(self, value.clone()) {
Err(e) if e.class().is(&self.ctx.exceptions.runtime_error) => return Err(e),
Ok(Some(value)) => value,
// Use a power of 2 as a default capacity.
_ => 4,
};
iterator::try_map(self, &iter, cap, |obj| func(obj))
}
}
@@ -1303,7 +1309,15 @@ impl VirtualMachine {
// TODO: put internal iterable type
obj => {
let iter = iterator::get_iter(self, obj.clone())?;
Ok(iterator::try_map(self, &iter, f))
let cap = match iterator::length_hint(self, obj.clone()) {
Err(e) if e.class().is(&self.ctx.exceptions.runtime_error) => {
return Ok(Err(e))
}
Ok(Some(value)) => value,
// Use a power of 2 as a default capacity.
_ => 4,
};
Ok(iterator::try_map(self, &iter, cap, f))
}
})
}