diff --git a/src/objects/sequence.rs b/src/objects/sequence.rs index 5c009d5b..993fe501 100644 --- a/src/objects/sequence.rs +++ b/src/objects/sequence.rs @@ -28,23 +28,17 @@ pub struct PySequence<'p>(PyObject<'p>); pyobject_newtype!(PySequence, PySequence_Check); impl <'p> PySequence<'p> { - /// Returns the number of objects in sequence. + /// Returns the number of objects in sequence. This is equivalent to Python `size` or `length`. #[inline] - pub fn size(&self) -> PyResult<'p, usize> { + pub fn len(&self) -> PyResult<'p, isize> { let v = unsafe { ffi::PySequence_Size(self.as_ptr()) }; if v == -1 { Err(PyErr::fetch(self.python())) } else { - Ok(v as usize) + Ok(v as isize) } } - /// Returns the number of objects in sequence. Same as size but included for completeness. - #[inline] - pub fn length(&self) -> PyResult<'p, usize> { - self.size() - } - /// Return the concatenation of o1 and o2. Equivalent to python `o1 + o2` #[inline] pub fn concat(&self, other: &PySequence<'p>) -> PyResult<'p, PySequence> { @@ -57,8 +51,9 @@ impl <'p> PySequence<'p> { /// Return the result of repeating sequence object o count times. /// Equivalent to python `o * count` + /// NB: Python accepts negative counts; it returns an empty Sequence. #[inline] - pub fn repeat(&self, count: usize) -> PyResult<'p, PySequence> { + pub fn repeat(&self, count: isize) -> PyResult<'p, PySequence> { let seq = try!(unsafe { let py = self.python(); result_from_owned_ptr(py, ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t)) @@ -78,8 +73,9 @@ impl <'p> PySequence<'p> { /// Return the result of repeating sequence object o count times. /// Equivalent to python `o *= count` + /// NB: Python accepts negative counts; it empties the Sequence. #[inline] - pub fn in_place_repeat(&self, count: usize) -> PyResult<'p, PySequence> { + pub fn in_place_repeat(&self, count: isize) -> PyResult<'p, PySequence> { let seq = try!(unsafe { let py = self.python(); result_from_owned_ptr(py, @@ -90,18 +86,19 @@ impl <'p> PySequence<'p> { /// Return the ith element of the Sequence. Equivalent to python `o[index]` #[inline] - pub fn get_item(&self, index: usize) -> PyObject<'p> { - assert!(index < self.length().unwrap()); + pub fn get_item(&self, index: isize) -> PyObject<'p> { + assert!(index < self.len().unwrap()); unsafe { let py = self.python(); - PyObject::from_borrowed_ptr(py, ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t)) + PyObject::from_owned_ptr(py, + ffi::PySequence_GetItem(self.as_ptr(), index as Py_ssize_t)) } } /// Return the slice of sequence object o between begin and end. /// This is the equivalent of the Python expression `o[begin:end]` #[inline] - pub fn get_slice(&self, begin : usize, end : usize) -> PyResult<'p, PySequence> { + pub fn get_slice(&self, begin : isize, end : isize) -> PyResult<'p, PySequence> { let slice = try!(unsafe { let py = self.python(); result_from_owned_ptr(py, @@ -113,7 +110,7 @@ impl <'p> PySequence<'p> { /// Assign object v to the ith element of o. /// Equivalent to Python statement `o[i] = v` #[inline] - pub fn set_item(&self, i: usize, v: &PyObject<'p>) -> PyResult<'p, ()> { + pub fn set_item(&self, i: isize, v: &PyObject<'p>) -> PyResult<'p, ()> { let v = unsafe { ffi::PySequence_SetItem(self.as_ptr(), i as Py_ssize_t, v.as_ptr()) }; @@ -127,7 +124,7 @@ impl <'p> PySequence<'p> { /// Delete the ith element of object o. /// Python statement `del o[i]` #[inline] - pub fn del_item(&self, i: usize) -> PyResult<'p, ()> { + pub fn del_item(&self, i: isize) -> PyResult<'p, ()> { let v = unsafe { ffi::PySequence_DelItem(self.as_ptr(), i as Py_ssize_t) }; if v == -1 { Err(PyErr::fetch(self.python())) @@ -139,7 +136,7 @@ impl <'p> PySequence<'p> { /// Assign the sequence object v to the slice in sequence object o from i1 to i2. /// This is the equivalent of the Python statement `o[i1:i2] = v` #[inline] - pub fn set_slice(&self, i1: usize, i2: usize, v: &PyObject<'p>) -> PyResult<'p, ()> { + pub fn set_slice(&self, i1: isize, i2: isize, v: &PyObject<'p>) -> PyResult<'p, ()> { let v = unsafe { ffi::PySequence_SetSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t, v.as_ptr()) }; @@ -153,8 +150,10 @@ impl <'p> PySequence<'p> { /// Delete the slice in sequence object o from i1 to i2. /// equivalent of the Python statement `del o[i1:i2]` #[inline] - pub fn del_slice(&self, i1: i64, i2: i64) -> PyResult<'p, ()> { - let v = unsafe { ffi::PySequence_DelSlice(self.as_ptr(), i1, i2) }; + pub fn del_slice(&self, i1: isize, i2: isize) -> PyResult<'p, ()> { + let v = unsafe { + ffi::PySequence_DelSlice(self.as_ptr(), i1 as Py_ssize_t, i2 as Py_ssize_t) + }; if v == -1 { Err(PyErr::fetch(self.python())) } else { @@ -220,7 +219,7 @@ impl <'p> PySequence<'p> { pub struct PySequenceIterator<'p> { sequence : PySequence<'p>, - index : usize + index : isize } impl <'p> IntoIterator for PySequence<'p> { @@ -248,9 +247,9 @@ impl <'p> Iterator for PySequenceIterator<'p> { #[inline] fn next(&mut self) -> Option> { // can't report any errors in underlying size check so we panic. - let len = self.sequence.length().unwrap(); + let len = self.sequence.len().unwrap(); if self.index < len { - let item = self.sequence.get_item(self.index) ; + let item = self.sequence.get_item(self.index); self.index += 1; Some(item) } else { @@ -287,8 +286,7 @@ mod test { let py = gil.python(); let v : Vec = vec![]; let seq = v.to_py_object(py).into_object().cast_into::().unwrap(); - assert_eq!(0, seq.length().unwrap()); - assert_eq!(0, seq.size().unwrap()); + assert_eq!(0, seq.len().unwrap()); let needle = 7i32.to_py_object(py).into_object(); assert_eq!(false, seq.contains(&needle).unwrap()); @@ -300,8 +298,7 @@ mod test { let py = gil.python(); let v : Vec = vec![1, 1, 2, 3, 5, 8]; let seq = v.to_py_object(py).into_object().cast_into::().unwrap(); - assert_eq!(6, seq.length().unwrap()); - assert_eq!(6, seq.size().unwrap()); + assert_eq!(6, seq.len().unwrap()); let bad_needle = 7i32.to_py_object(py).into_object(); assert_eq!(false, seq.contains(&bad_needle).unwrap()); @@ -325,6 +322,11 @@ mod test { assert_eq!(3, seq.get_item(3).extract::().unwrap()); assert_eq!(5, seq.get_item(4).extract::().unwrap()); assert_eq!(8, seq.get_item(5).extract::().unwrap()); + assert_eq!(8, seq.get_item(-1).extract::().unwrap()); + assert_eq!(5, seq.get_item(-2).extract::().unwrap()); + assert_eq!(3, seq.get_item(-3).extract::().unwrap()); + assert_eq!(2, seq.get_item(-4).extract::().unwrap()); + assert_eq!(1, seq.get_item(-5).extract::().unwrap()); //assert!(seq.get_item(5).extract::().is_err()); // panics. } @@ -351,7 +353,7 @@ mod test { assert!(seq.del_item(0).is_ok()); assert_eq!(8, seq.get_item(0).extract::().unwrap()); assert!(seq.del_item(0).is_ok()); - assert_eq!(0, seq.length().unwrap()); + assert_eq!(0, seq.len().unwrap()); assert!(seq.del_item(0).is_err()); } @@ -432,7 +434,7 @@ mod test { let v : Vec = vec![1, 2, 3]; let seq = v.to_py_object(py).into_object().cast_into::().unwrap(); let concat_seq = seq.concat(&seq).unwrap(); - assert_eq!(6, concat_seq.length().unwrap()); + assert_eq!(6, concat_seq.len().unwrap()); //let concat_v : Vec = vec![1, 2, 3, 1, 2, 3]; //assert_eq!(concat_v, concat_seq.into_object().extract::>().unwrap()); } @@ -444,7 +446,7 @@ mod test { let v = "string"; let seq = v.to_py_object(py).into_object().cast_into::().unwrap(); let concat_seq = seq.concat(&seq).unwrap(); - assert_eq!(12, concat_seq.length().unwrap()); + assert_eq!(12, concat_seq.len().unwrap()); //let concat_v = "stringstring"; //assert_eq!(concat_v, concat_seq.into_object().extract::().unwrap()); } @@ -456,7 +458,7 @@ mod test { let v = vec!["foo", "bar"]; let seq = v.to_py_object(py).into_object().cast_into::().unwrap(); let repeat_seq = seq.repeat(3).unwrap(); - assert_eq!(6, repeat_seq.length().unwrap()); + assert_eq!(6, repeat_seq.len().unwrap()); //let repeated = vec!["foo", "bar", "foo", "bar", "foo", "bar"]; //assert_eq!(repeated, repeat_seq.into_object().extract::>().unwrap()); }