diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py index 7296ceaa9..cc70a0300 100644 --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -265,8 +265,6 @@ class TestBasic(unittest.TestCase): self.assertRaises(IndexError, d.__getitem__, 0) self.assertRaises(IndexError, d.__getitem__, -1) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_index(self): for n in 1, 2, 30, 40, 200: diff --git a/vm/src/stdlib/collections.rs b/vm/src/stdlib/collections.rs index f3d55eed0..f56d8b02a 100644 --- a/vm/src/stdlib/collections.rs +++ b/vm/src/stdlib/collections.rs @@ -19,6 +19,7 @@ mod _collections { use crossbeam_utils::atomic::AtomicCell; use itertools::Itertools; use num_traits::ToPrimitive; + use std::cmp::{max, min}; use std::collections::VecDeque; #[pyattr] @@ -240,26 +241,44 @@ mod _collections { Ok(()) } + fn adjust_negative_index(&self, index: isize) -> usize { + if index.is_negative() { + max(index + self.borrow_deque().len() as isize, 0) as usize + } else { + index as usize + } + } + #[pymethod] fn index( &self, obj: PyObjectRef, - start: OptionalArg, - stop: OptionalArg, + start: OptionalArg, + stop: OptionalArg, vm: &VirtualMachine, ) -> PyResult { let deque = self.borrow_deque().clone(); - let start = start.unwrap_or(0); let start_state = self.state.load(); - let stop = stop.unwrap_or_else(|| deque.len()); - for (i, elem) in deque.iter().skip(start).take(stop - start).enumerate() { + + let start = self.adjust_negative_index(start.unwrap_or(0)); + let stop = min( + self.adjust_negative_index(stop.unwrap_or_else(|| deque.len() as isize)), + deque.len(), + ); + + for (i, elem) in deque + .iter() + .skip(start) + .take(stop.saturating_sub(start)) + .enumerate() + { let is_element = vm.identical_or_equal(elem, &obj)?; if start_state != self.state.load() { return Err(vm.new_runtime_error("deque mutated during iteration".to_owned())); } if is_element { - return Ok(i); + return Ok(i + start); } } Err(vm.new_value_error(