port `PyObject::downcast` to `Bound` API (#3856)
* port `PyObject::downcast` to `Bound` API * relax traits bounds for unchecked variant in `Bound` API * deprecate `Python::(checked_)cast_as` * reword deprecation warning
This commit is contained in:
parent
0dd568d397
commit
1d295a12a0
|
@ -121,7 +121,7 @@ mod tests {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m = map.to_object(py);
|
let m = map.to_object(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -143,7 +143,7 @@ mod tests {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m: PyObject = map.into_py(py);
|
let m: PyObject = map.into_py(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -149,7 +149,7 @@ mod test_indexmap {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m = map.to_object(py);
|
let m = map.to_object(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -175,7 +175,7 @@ mod test_indexmap {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m: PyObject = map.into_py(py);
|
let m: PyObject = map.into_py(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -239,7 +239,7 @@ mod tests {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let array: [Foo; 8] = [Foo, Foo, Foo, Foo, Foo, Foo, Foo, Foo];
|
let array: [Foo; 8] = [Foo, Foo, Foo, Foo, Foo, Foo, Foo, Foo];
|
||||||
let pyobject = array.into_py(py);
|
let pyobject = array.into_py(py);
|
||||||
let list: &PyList = pyobject.downcast(py).unwrap();
|
let list = pyobject.downcast_bound::<PyList>(py).unwrap();
|
||||||
let _cell: &crate::PyCell<Foo> = list.get_item(4).unwrap().extract().unwrap();
|
let _cell: &crate::PyCell<Foo> = list.get_item(4).unwrap().extract().unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ mod tests {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m = map.to_object(py);
|
let m = map.to_object(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -144,7 +144,7 @@ mod tests {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m = map.to_object(py);
|
let m = map.to_object(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -167,7 +167,7 @@ mod tests {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m: PyObject = map.into_py(py);
|
let m: PyObject = map.into_py(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -189,7 +189,7 @@ mod tests {
|
||||||
map.insert(1, 1);
|
map.insert(1, 1);
|
||||||
|
|
||||||
let m: PyObject = map.into_py(py);
|
let m: PyObject = map.into_py(py);
|
||||||
let py_map: &PyDict = m.downcast(py).unwrap();
|
let py_map = m.downcast_bound::<PyDict>(py).unwrap();
|
||||||
|
|
||||||
assert!(py_map.len() == 1);
|
assert!(py_map.len() == 1);
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -62,6 +62,15 @@ impl<'a> PyDowncastError<'a> {
|
||||||
to: to.into(),
|
to: to.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compatibility API to convert the Bound variant `DowncastError` into the
|
||||||
|
/// gil-ref variant
|
||||||
|
pub(crate) fn from_downcast_err(DowncastError { from, to }: DowncastError<'a, 'a>) -> Self {
|
||||||
|
Self {
|
||||||
|
from: from.as_gil_ref(),
|
||||||
|
to,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error that indicates a failure to convert a PyAny to a more specific Python type.
|
/// Error that indicates a failure to convert a PyAny to a more specific Python type.
|
||||||
|
|
|
@ -7,8 +7,8 @@ use crate::types::any::PyAnyMethods;
|
||||||
use crate::types::string::PyStringMethods;
|
use crate::types::string::PyStringMethods;
|
||||||
use crate::types::{PyDict, PyString, PyTuple};
|
use crate::types::{PyDict, PyString, PyTuple};
|
||||||
use crate::{
|
use crate::{
|
||||||
ffi, AsPyPointer, FromPyObject, IntoPy, PyAny, PyClass, PyClassInitializer, PyRef, PyRefMut,
|
ffi, AsPyPointer, DowncastError, FromPyObject, IntoPy, PyAny, PyClass, PyClassInitializer,
|
||||||
PyTypeInfo, Python, ToPyObject,
|
PyRef, PyRefMut, PyTypeInfo, Python, ToPyObject,
|
||||||
};
|
};
|
||||||
use crate::{gil, PyTypeCheck};
|
use crate::{gil, PyTypeCheck};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
@ -1686,6 +1686,23 @@ impl<T> std::fmt::Debug for Py<T> {
|
||||||
pub type PyObject = Py<PyAny>;
|
pub type PyObject = Py<PyAny>;
|
||||||
|
|
||||||
impl PyObject {
|
impl PyObject {
|
||||||
|
/// Deprecated form of [`PyObject::downcast_bound`]
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "gil-refs"),
|
||||||
|
deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "`PyObject::downcast` will be replaced by `PyObject::downcast_bound` in a future PyO3 version"
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
#[inline]
|
||||||
|
pub fn downcast<'py, T>(&'py self, py: Python<'py>) -> Result<&'py T, PyDowncastError<'py>>
|
||||||
|
where
|
||||||
|
T: PyTypeCheck<AsRefTarget = T>,
|
||||||
|
{
|
||||||
|
self.downcast_bound::<T>(py)
|
||||||
|
.map(Bound::as_gil_ref)
|
||||||
|
.map_err(PyDowncastError::from_downcast_err)
|
||||||
|
}
|
||||||
/// Downcast this `PyObject` to a concrete Python type or pyclass.
|
/// Downcast this `PyObject` to a concrete Python type or pyclass.
|
||||||
///
|
///
|
||||||
/// Note that you can often avoid downcasting yourself by just specifying
|
/// Note that you can often avoid downcasting yourself by just specifying
|
||||||
|
@ -1703,8 +1720,8 @@ impl PyObject {
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let any: PyObject = PyDict::new_bound(py).into();
|
/// let any: PyObject = PyDict::new_bound(py).into();
|
||||||
///
|
///
|
||||||
/// assert!(any.downcast::<PyDict>(py).is_ok());
|
/// assert!(any.downcast_bound::<PyDict>(py).is_ok());
|
||||||
/// assert!(any.downcast::<PyList>(py).is_err());
|
/// assert!(any.downcast_bound::<PyList>(py).is_err());
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -1725,9 +1742,9 @@ impl PyObject {
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let class: PyObject = Py::new(py, Class { i: 0 }).unwrap().into_py(py);
|
/// let class: PyObject = Py::new(py, Class { i: 0 }).unwrap().into_py(py);
|
||||||
///
|
///
|
||||||
/// let class_cell: &PyCell<Class> = class.downcast(py)?;
|
/// let class_bound = class.downcast_bound::<Class>(py)?;
|
||||||
///
|
///
|
||||||
/// class_cell.borrow_mut().i += 1;
|
/// class_bound.borrow_mut().i += 1;
|
||||||
///
|
///
|
||||||
/// // Alternatively you can get a `PyRefMut` directly
|
/// // Alternatively you can get a `PyRefMut` directly
|
||||||
/// let class_ref: PyRefMut<'_, Class> = class.extract(py)?;
|
/// let class_ref: PyRefMut<'_, Class> = class.extract(py)?;
|
||||||
|
@ -1737,11 +1754,34 @@ impl PyObject {
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn downcast<'py, T>(&'py self, py: Python<'py>) -> Result<&'py T, PyDowncastError<'py>>
|
pub fn downcast_bound<'py, T>(
|
||||||
|
&self,
|
||||||
|
py: Python<'py>,
|
||||||
|
) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>
|
||||||
where
|
where
|
||||||
T: PyTypeCheck<AsRefTarget = T>,
|
T: PyTypeCheck,
|
||||||
{
|
{
|
||||||
self.as_ref(py).downcast()
|
self.bind(py).downcast()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deprecated form of [`PyObject::downcast_bound_unchecked`]
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Callers must ensure that the type is valid or risk type confusion.
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "gil-refs"),
|
||||||
|
deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "`PyObject::downcast_unchecked` will be replaced by `PyObject::downcast_bound_unchecked` in a future PyO3 version"
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn downcast_unchecked<'py, T>(&'py self, py: Python<'py>) -> &T
|
||||||
|
where
|
||||||
|
T: HasPyGilRef<AsRefTarget = T>,
|
||||||
|
{
|
||||||
|
self.downcast_bound_unchecked::<T>(py).as_gil_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Casts the PyObject to a concrete Python object type without checking validity.
|
/// Casts the PyObject to a concrete Python object type without checking validity.
|
||||||
|
@ -1750,11 +1790,8 @@ impl PyObject {
|
||||||
///
|
///
|
||||||
/// Callers must ensure that the type is valid or risk type confusion.
|
/// Callers must ensure that the type is valid or risk type confusion.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn downcast_unchecked<'p, T>(&'p self, py: Python<'p>) -> &T
|
pub unsafe fn downcast_bound_unchecked<'py, T>(&self, py: Python<'py>) -> &Bound<'py, T> {
|
||||||
where
|
self.bind(py).downcast_unchecked()
|
||||||
T: HasPyGilRef<AsRefTarget = T>,
|
|
||||||
{
|
|
||||||
self.as_ref(py).downcast_unchecked()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -826,6 +826,13 @@ impl<'py> Python<'py> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers the object in the release pool, and tries to downcast to specific type.
|
/// Registers the object in the release pool, and tries to downcast to specific type.
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "gil-refs"),
|
||||||
|
deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "part of the deprecated GIL Ref API; to migrate use `obj.downcast_bound::<T>(py)` instead of `py.checked_cast_as::<T>(obj)`"
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'py T, PyDowncastError<'py>>
|
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'py T, PyDowncastError<'py>>
|
||||||
where
|
where
|
||||||
T: PyTypeCheck<AsRefTarget = T>,
|
T: PyTypeCheck<AsRefTarget = T>,
|
||||||
|
@ -839,6 +846,13 @@ impl<'py> Python<'py> {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Callers must ensure that ensure that the cast is valid.
|
/// Callers must ensure that ensure that the cast is valid.
|
||||||
|
#[cfg_attr(
|
||||||
|
not(feature = "gil-refs"),
|
||||||
|
deprecated(
|
||||||
|
since = "0.21.0",
|
||||||
|
note = "part of the deprecated GIL Ref API; to migrate use `obj.downcast_bound_unchecked::<T>(py)` instead of `py.cast_as::<T>(obj)`"
|
||||||
|
)
|
||||||
|
)]
|
||||||
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py T
|
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'py T
|
||||||
where
|
where
|
||||||
T: HasPyGilRef<AsRefTarget = T>,
|
T: HasPyGilRef<AsRefTarget = T>,
|
||||||
|
|
|
@ -299,13 +299,13 @@ mod tests {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let mut v = HashMap::new();
|
let mut v = HashMap::new();
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
assert_eq!(0, mapping.len().unwrap());
|
assert_eq!(0, mapping.len().unwrap());
|
||||||
assert!(mapping.is_empty().unwrap());
|
assert!(mapping.is_empty().unwrap());
|
||||||
|
|
||||||
v.insert(7, 32);
|
v.insert(7, 32);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping2: &PyMapping = ob.downcast(py).unwrap();
|
let mapping2 = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
assert_eq!(1, mapping2.len().unwrap());
|
assert_eq!(1, mapping2.len().unwrap());
|
||||||
assert!(!mapping2.is_empty().unwrap());
|
assert!(!mapping2.is_empty().unwrap());
|
||||||
});
|
});
|
||||||
|
@ -317,7 +317,7 @@ mod tests {
|
||||||
let mut v = HashMap::new();
|
let mut v = HashMap::new();
|
||||||
v.insert("key0", 1234);
|
v.insert("key0", 1234);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
mapping.set_item("key1", "foo").unwrap();
|
mapping.set_item("key1", "foo").unwrap();
|
||||||
|
|
||||||
assert!(mapping.contains("key0").unwrap());
|
assert!(mapping.contains("key0").unwrap());
|
||||||
|
@ -332,7 +332,7 @@ mod tests {
|
||||||
let mut v = HashMap::new();
|
let mut v = HashMap::new();
|
||||||
v.insert(7, 32);
|
v.insert(7, 32);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
32,
|
32,
|
||||||
mapping.get_item(7i32).unwrap().extract::<i32>().unwrap()
|
mapping.get_item(7i32).unwrap().extract::<i32>().unwrap()
|
||||||
|
@ -350,7 +350,7 @@ mod tests {
|
||||||
let mut v = HashMap::new();
|
let mut v = HashMap::new();
|
||||||
v.insert(7, 32);
|
v.insert(7, 32);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
assert!(mapping.set_item(7i32, 42i32).is_ok()); // change
|
assert!(mapping.set_item(7i32, 42i32).is_ok()); // change
|
||||||
assert!(mapping.set_item(8i32, 123i32).is_ok()); // insert
|
assert!(mapping.set_item(8i32, 123i32).is_ok()); // insert
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -370,7 +370,7 @@ mod tests {
|
||||||
let mut v = HashMap::new();
|
let mut v = HashMap::new();
|
||||||
v.insert(7, 32);
|
v.insert(7, 32);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
assert!(mapping.del_item(7i32).is_ok());
|
assert!(mapping.del_item(7i32).is_ok());
|
||||||
assert_eq!(0, mapping.len().unwrap());
|
assert_eq!(0, mapping.len().unwrap());
|
||||||
assert!(mapping
|
assert!(mapping
|
||||||
|
@ -388,12 +388,12 @@ mod tests {
|
||||||
v.insert(8, 42);
|
v.insert(8, 42);
|
||||||
v.insert(9, 123);
|
v.insert(9, 123);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||||
let mut key_sum = 0;
|
let mut key_sum = 0;
|
||||||
let mut value_sum = 0;
|
let mut value_sum = 0;
|
||||||
for el in mapping.items().unwrap().iter().unwrap() {
|
for el in mapping.items().unwrap().iter().unwrap() {
|
||||||
let tuple = el.unwrap().downcast::<PyTuple>().unwrap();
|
let tuple = el.unwrap().downcast_into::<PyTuple>().unwrap();
|
||||||
key_sum += tuple.get_item(0).unwrap().extract::<i32>().unwrap();
|
key_sum += tuple.get_item(0).unwrap().extract::<i32>().unwrap();
|
||||||
value_sum += tuple.get_item(1).unwrap().extract::<i32>().unwrap();
|
value_sum += tuple.get_item(1).unwrap().extract::<i32>().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -410,7 +410,7 @@ mod tests {
|
||||||
v.insert(8, 42);
|
v.insert(8, 42);
|
||||||
v.insert(9, 123);
|
v.insert(9, 123);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||||
let mut key_sum = 0;
|
let mut key_sum = 0;
|
||||||
for el in mapping.keys().unwrap().iter().unwrap() {
|
for el in mapping.keys().unwrap().iter().unwrap() {
|
||||||
|
@ -428,7 +428,7 @@ mod tests {
|
||||||
v.insert(8, 42);
|
v.insert(8, 42);
|
||||||
v.insert(9, 123);
|
v.insert(9, 123);
|
||||||
let ob = v.to_object(py);
|
let ob = v.to_object(py);
|
||||||
let mapping: &PyMapping = ob.downcast(py).unwrap();
|
let mapping = ob.downcast_bound::<PyMapping>(py).unwrap();
|
||||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||||
let mut values_sum = 0;
|
let mut values_sum = 0;
|
||||||
for el in mapping.values().unwrap().iter().unwrap() {
|
for el in mapping.values().unwrap().iter().unwrap() {
|
||||||
|
|
|
@ -103,7 +103,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unit_to_object_is_none() {
|
fn test_unit_to_object_is_none() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
assert!(().to_object(py).downcast::<PyNone>(py).is_ok());
|
assert!(().to_object(py).downcast_bound::<PyNone>(py).is_ok());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ mod tests {
|
||||||
fn test_unit_into_py_is_none() {
|
fn test_unit_into_py_is_none() {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let obj: PyObject = ().into_py(py);
|
let obj: PyObject = ().into_py(py);
|
||||||
assert!(obj.downcast::<PyNone>(py).is_ok());
|
assert!(obj.downcast_bound::<PyNone>(py).is_ok());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ impl PyTuple {
|
||||||
/// # fn main() -> PyResult<()> {
|
/// # fn main() -> PyResult<()> {
|
||||||
/// Python::with_gil(|py| -> PyResult<()> {
|
/// Python::with_gil(|py| -> PyResult<()> {
|
||||||
/// let ob = (1, 2, 3).to_object(py);
|
/// let ob = (1, 2, 3).to_object(py);
|
||||||
/// let tuple: &PyTuple = ob.downcast(py).unwrap();
|
/// let tuple = ob.downcast_bound::<PyTuple>(py).unwrap();
|
||||||
/// let obj = tuple.get_item(0);
|
/// let obj = tuple.get_item(0);
|
||||||
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 1);
|
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 1);
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
|
@ -273,7 +273,7 @@ pub trait PyTupleMethods<'py> {
|
||||||
/// # fn main() -> PyResult<()> {
|
/// # fn main() -> PyResult<()> {
|
||||||
/// Python::with_gil(|py| -> PyResult<()> {
|
/// Python::with_gil(|py| -> PyResult<()> {
|
||||||
/// let ob = (1, 2, 3).to_object(py);
|
/// let ob = (1, 2, 3).to_object(py);
|
||||||
/// let tuple: &PyTuple = ob.downcast(py).unwrap();
|
/// let tuple = ob.downcast_bound::<PyTuple>(py).unwrap();
|
||||||
/// let obj = tuple.get_item(0);
|
/// let obj = tuple.get_item(0);
|
||||||
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 1);
|
/// assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 1);
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
|
|
Loading…
Reference in New Issue