improve tuple methods test coverage
This commit is contained in:
parent
53d25f7ff2
commit
823b5feed3
|
@ -60,9 +60,12 @@ pyobject_native_type_core!(PyTuple, pyobject_native_static_type_object!(ffi::PyT
|
|||
impl PyTuple {
|
||||
/// Deprecated form of `PyTuple::new_bound`.
|
||||
#[track_caller]
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyTuple::new` will be replaced by `PyTuple::new_bound` in a future PyO3 version"
|
||||
#[cfg_attr(
|
||||
not(feature = "gil-refs"),
|
||||
deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyTuple::new` will be replaced by `PyTuple::new_bound` in a future PyO3 version"
|
||||
)
|
||||
)]
|
||||
pub fn new<T, U>(
|
||||
py: Python<'_>,
|
||||
|
@ -115,9 +118,12 @@ impl PyTuple {
|
|||
}
|
||||
|
||||
/// Deprecated form of `PyTuple::empty_bound`.
|
||||
#[deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyTuple::empty` will be replaced by `PyTuple::empty_bound` in a future PyO3 version"
|
||||
#[cfg_attr(
|
||||
not(feature = "gil-refs"),
|
||||
deprecated(
|
||||
since = "0.21.0",
|
||||
note = "`PyTuple::empty` will be replaced by `PyTuple::empty_bound` in a future PyO3 version"
|
||||
)
|
||||
)]
|
||||
pub fn empty(py: Python<'_>) -> &PyTuple {
|
||||
Self::empty_bound(py).into_gil_ref()
|
||||
|
@ -361,7 +367,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
|
|||
}
|
||||
|
||||
fn get_borrowed_item<'a>(&'a self, index: usize) -> PyResult<Borrowed<'a, 'py, PyAny>> {
|
||||
Borrowed::from(self).get_borrowed_item(index)
|
||||
self.as_borrowed().get_borrowed_item(index)
|
||||
}
|
||||
|
||||
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||
|
@ -371,7 +377,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
|
|||
|
||||
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||
unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny> {
|
||||
Borrowed::from(self).get_borrowed_item_unchecked(index)
|
||||
self.as_borrowed().get_borrowed_item_unchecked(index)
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
|
@ -406,7 +412,7 @@ impl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {
|
|||
}
|
||||
|
||||
fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py> {
|
||||
BorrowedTupleIterator::new(Borrowed::from(self))
|
||||
BorrowedTupleIterator::new(self.as_borrowed())
|
||||
}
|
||||
|
||||
fn to_list(&self) -> Bound<'py, PyList> {
|
||||
|
@ -496,7 +502,7 @@ impl<'py> Iterator for BoundTupleIterator<'py> {
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.length {
|
||||
let item = unsafe {
|
||||
BorrowedTupleIterator::get_item(Borrowed::from(&self.tuple), self.index).to_owned()
|
||||
BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.index).to_owned()
|
||||
};
|
||||
self.index += 1;
|
||||
Some(item)
|
||||
|
@ -517,7 +523,7 @@ impl<'py> DoubleEndedIterator for BoundTupleIterator<'py> {
|
|||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if self.index < self.length {
|
||||
let item = unsafe {
|
||||
BorrowedTupleIterator::get_item(Borrowed::from(&self.tuple), self.length - 1)
|
||||
BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.length - 1)
|
||||
.to_owned()
|
||||
};
|
||||
self.length -= 1;
|
||||
|
@ -797,7 +803,7 @@ tuple_conversion!(
|
|||
#[cfg(test)]
|
||||
#[allow(deprecated)] // TODO: remove allow when GIL Pool is removed
|
||||
mod tests {
|
||||
use crate::types::{PyAny, PyList, PyTuple};
|
||||
use crate::types::{any::PyAnyMethods, tuple::PyTupleMethods, PyAny, PyList, PyTuple};
|
||||
use crate::{Python, ToPyObject};
|
||||
use std::collections::HashSet;
|
||||
|
||||
|
@ -822,11 +828,21 @@ mod tests {
|
|||
let ob = (1, 2, 3).to_object(py);
|
||||
let tuple: &PyTuple = ob.downcast(py).unwrap();
|
||||
assert_eq!(3, tuple.len());
|
||||
assert!(!tuple.is_empty());
|
||||
let ob: &PyAny = tuple.into();
|
||||
assert_eq!((1, 2, 3), ob.extract().unwrap());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
Python::with_gil(|py| {
|
||||
let tuple = PyTuple::empty(py);
|
||||
assert!(tuple.is_empty());
|
||||
assert_eq!(0, tuple.len());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_slice() {
|
||||
Python::with_gil(|py| {
|
||||
|
@ -886,6 +902,52 @@ mod tests {
|
|||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bound_iter() {
|
||||
Python::with_gil(|py| {
|
||||
let tuple = PyTuple::new_bound(py, [1, 2, 3]);
|
||||
assert_eq!(3, tuple.len());
|
||||
let mut iter = tuple.iter();
|
||||
|
||||
assert_eq!(iter.size_hint(), (3, Some(3)));
|
||||
|
||||
assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());
|
||||
assert_eq!(iter.size_hint(), (2, Some(2)));
|
||||
|
||||
assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());
|
||||
assert_eq!(iter.size_hint(), (1, Some(1)));
|
||||
|
||||
assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());
|
||||
assert_eq!(iter.size_hint(), (0, Some(0)));
|
||||
|
||||
assert!(iter.next().is_none());
|
||||
assert!(iter.next().is_none());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bound_iter_rev() {
|
||||
Python::with_gil(|py| {
|
||||
let tuple = PyTuple::new_bound(py, [1, 2, 3]);
|
||||
assert_eq!(3, tuple.len());
|
||||
let mut iter = tuple.iter().rev();
|
||||
|
||||
assert_eq!(iter.size_hint(), (3, Some(3)));
|
||||
|
||||
assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());
|
||||
assert_eq!(iter.size_hint(), (2, Some(2)));
|
||||
|
||||
assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());
|
||||
assert_eq!(iter.size_hint(), (1, Some(1)));
|
||||
|
||||
assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());
|
||||
assert_eq!(iter.size_hint(), (0, Some(0)));
|
||||
|
||||
assert!(iter.next().is_none());
|
||||
assert!(iter.next().is_none());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_into_iter() {
|
||||
Python::with_gil(|py| {
|
||||
|
@ -1308,4 +1370,50 @@ mod tests {
|
|||
assert!(list.eq(list_expected).unwrap());
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_as_sequence() {
|
||||
Python::with_gil(|py| {
|
||||
let tuple = PyTuple::new(py, vec![1, 2, 3]);
|
||||
let sequence = tuple.as_sequence();
|
||||
assert!(tuple.get_item(0).unwrap().eq(1).unwrap());
|
||||
assert!(sequence.get_item(0).unwrap().eq(1).unwrap());
|
||||
|
||||
assert_eq!(tuple.len(), 3);
|
||||
assert_eq!(sequence.len().unwrap(), 3);
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bound_tuple_get_item() {
|
||||
Python::with_gil(|py| {
|
||||
let tuple = PyTuple::new_bound(py, vec![1, 2, 3, 4]);
|
||||
|
||||
assert_eq!(tuple.len(), 4);
|
||||
assert_eq!(tuple.get_item(0).unwrap().extract::<i32>().unwrap(), 1);
|
||||
assert_eq!(
|
||||
tuple
|
||||
.get_borrowed_item(1)
|
||||
.unwrap()
|
||||
.extract::<i32>()
|
||||
.unwrap(),
|
||||
2
|
||||
);
|
||||
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
|
||||
{
|
||||
assert_eq!(
|
||||
unsafe { tuple.get_item_unchecked(2) }
|
||||
.extract::<i32>()
|
||||
.unwrap(),
|
||||
3
|
||||
);
|
||||
assert_eq!(
|
||||
unsafe { tuple.get_borrowed_item_unchecked(3) }
|
||||
.extract::<i32>()
|
||||
.unwrap(),
|
||||
4
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ error[E0277]: the trait bound `PyErr: From<MyError>` is not satisfied
|
|||
|
|
||||
= help: the following other types implement trait `From<T>`:
|
||||
<PyErr as From<PyBorrowError>>
|
||||
<PyErr as From<std::io::Error>>
|
||||
<PyErr as From<PyBorrowMutError>>
|
||||
<PyErr as From<std::io::Error>>
|
||||
<PyErr as From<PyDowncastError<'a>>>
|
||||
<PyErr as From<DowncastError<'_, '_>>>
|
||||
<PyErr as From<DowncastIntoError<'_>>>
|
||||
|
|
Loading…
Reference in a new issue