Introduce PyDownCastImpl and Change PyTryFrom and FromPyPointer
This commit is contained in:
parent
a2408cacbb
commit
5d4e7374e9
|
@ -11,14 +11,9 @@
|
|||
use crate::callback::{BoolCallbackConverter, HashConverter, PyObjectCallbackConverter};
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::PyAny;
|
||||
use crate::FromPyObject;
|
||||
use crate::IntoPyPointer;
|
||||
use crate::Python;
|
||||
use crate::{exceptions, IntoPy, PyObject};
|
||||
use crate::{exceptions, ffi, FromPyObject, IntoPy, IntoPyPointer, PyClass, PyObject, Python};
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr;
|
||||
|
||||
|
@ -35,7 +30,7 @@ pub enum CompareOp {
|
|||
|
||||
/// Basic python class customization
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyObjectProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyObjectProtocol<'p>: PyClass {
|
||||
fn __getattr__(&'p self, name: Self::Name) -> Self::Result
|
||||
where
|
||||
Self: PyObjectGetAttrProtocol<'p>,
|
||||
|
@ -237,7 +232,7 @@ where
|
|||
return existing;
|
||||
}
|
||||
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<crate::types::PyAny>(arg);
|
||||
|
||||
let result = match arg.extract() {
|
||||
|
@ -513,7 +508,7 @@ where
|
|||
{
|
||||
let py = Python::assume_gil_acquired();
|
||||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<PyAny>(arg);
|
||||
|
||||
let res = match extract_op(op) {
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
//! c-api
|
||||
use crate::callback::UnitCallbackConverter;
|
||||
use crate::err::PyResult;
|
||||
use crate::ffi;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::{ffi, PyClass};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Buffer protocol interface
|
||||
|
@ -15,7 +14,7 @@ use std::os::raw::c_int;
|
|||
/// For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html)
|
||||
/// c-api
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyBufferProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyBufferProtocol<'p>: PyClass {
|
||||
fn bf_getbuffer(&'p self, view: *mut ffi::Py_buffer, flags: c_int) -> Self::Result
|
||||
where
|
||||
Self: PyBufferGetBufferProtocol<'p>,
|
||||
|
@ -94,7 +93,7 @@ where
|
|||
{
|
||||
let py = crate::Python::assume_gil_acquired();
|
||||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
|
||||
let result = slf.bf_getbuffer(arg1, arg2).into();
|
||||
crate::callback::cb_convert(UnitCallbackConverter, py, result)
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::PyResult;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::PyObject;
|
||||
use crate::{PyClass, PyObject};
|
||||
|
||||
/// Context manager interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyContextProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyContextProtocol<'p>: PyClass {
|
||||
fn __enter__(&'p mut self) -> Self::Result
|
||||
where
|
||||
Self: PyContextEnterProtocol<'p>,
|
||||
|
|
|
@ -8,15 +8,13 @@
|
|||
use crate::callback::{PyObjectCallbackConverter, UnitCallbackConverter};
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::PyResult;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::{PyAny, PyType};
|
||||
use crate::FromPyObject;
|
||||
use crate::{ffi, IntoPy, PyObject};
|
||||
use crate::{ffi, FromPyObject, IntoPy, PyClass, PyObject};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Descriptor interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyDescrProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyDescrProtocol<'p>: PyClass {
|
||||
fn __get__(&'p self, instance: &'p PyAny, owner: Option<&'p PyType>) -> Self::Result
|
||||
where
|
||||
Self: PyDescrGetProtocol<'p>,
|
||||
|
|
|
@ -3,17 +3,14 @@
|
|||
//! Python GC support
|
||||
//!
|
||||
|
||||
use crate::ffi;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::AsPyPointer;
|
||||
use crate::Python;
|
||||
use crate::{ffi, AsPyPointer, PyCell, PyClass, Python};
|
||||
use std::os::raw::{c_int, c_void};
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct PyTraverseError(c_int);
|
||||
|
||||
/// GC support
|
||||
pub trait PyGCProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyGCProtocol<'p>: PyClass {
|
||||
fn __traverse__(&'p self, visit: PyVisit) -> Result<(), PyTraverseError>;
|
||||
fn __clear__(&'p mut self);
|
||||
}
|
||||
|
@ -94,7 +91,7 @@ where
|
|||
{
|
||||
let py = Python::assume_gil_acquired();
|
||||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
let visit = PyVisit {
|
||||
visit,
|
||||
|
@ -136,7 +133,7 @@ where
|
|||
{
|
||||
let py = Python::assume_gil_acquired();
|
||||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
slf.__clear__();
|
||||
0
|
||||
|
|
|
@ -19,7 +19,7 @@ macro_rules! py_unary_func {
|
|||
{
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let res = slf.$f().into();
|
||||
$crate::callback::cb_convert($conv, py, res.map(|x| x))
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ macro_rules! py_len_func {
|
|||
{
|
||||
let py = Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
|
||||
let result = slf.$f().into();
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
|
@ -86,7 +86,7 @@ macro_rules! py_binary_func {
|
|||
use $crate::ObjectProtocol;
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<$crate::types::PyAny>(arg);
|
||||
|
||||
let result = match arg.extract() {
|
||||
|
@ -146,7 +146,7 @@ macro_rules! py_binary_self_func {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf1 = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf1 = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg = py.from_borrowed_ptr::<$crate::types::PyAny>(arg);
|
||||
|
||||
let result = match arg.extract() {
|
||||
|
@ -182,7 +182,7 @@ macro_rules! py_ssizearg_func {
|
|||
{
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let result = slf.$f(arg.into()).into();
|
||||
$crate::callback::cb_convert($conv, py, result)
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ macro_rules! py_ternary_func {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg1 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg1);
|
||||
let arg2 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg2);
|
||||
|
||||
|
@ -286,7 +286,7 @@ macro_rules! py_ternary_self_func {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf1 = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf1 = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
|
||||
let arg1 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg1);
|
||||
let arg2 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg2);
|
||||
|
||||
|
@ -325,7 +325,7 @@ macro_rules! py_func_set {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<$generic>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf);
|
||||
|
||||
let result = if value.is_null() {
|
||||
Err($crate::PyErr::new::<exceptions::NotImplementedError, _>(
|
||||
|
@ -335,7 +335,7 @@ macro_rules! py_func_set {
|
|||
),
|
||||
))
|
||||
} else {
|
||||
let name = py.mut_from_borrowed_ptr::<$crate::types::PyAny>(name);
|
||||
let name = py.from_borrowed_ptr::<$crate::types::PyAny>(name);
|
||||
let value = py.from_borrowed_ptr::<$crate::types::PyAny>(value);
|
||||
match name.extract() {
|
||||
Ok(name) => match value.extract() {
|
||||
|
@ -375,7 +375,7 @@ macro_rules! py_func_del {
|
|||
let _pool = $crate::GILPool::new(py);
|
||||
|
||||
let result = if value.is_null() {
|
||||
let slf = py.mut_from_borrowed_ptr::<U>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<U>>(slf);
|
||||
let name = py.from_borrowed_ptr::<$crate::types::PyAny>(name);
|
||||
|
||||
match name.extract() {
|
||||
|
@ -415,7 +415,7 @@ macro_rules! py_func_set_del {
|
|||
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
let _pool = $crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<$generic>(slf);
|
||||
let slf = py.from_borrowed_ptr::<$crate::PyCell<$generic>>(slf);
|
||||
let name = py.from_borrowed_ptr::<$crate::types::PyAny>(name);
|
||||
|
||||
let result = if value.is_null() {
|
||||
|
|
|
@ -6,15 +6,11 @@
|
|||
use crate::callback::{LenResultConverter, PyObjectCallbackConverter};
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::FromPyObject;
|
||||
use crate::Python;
|
||||
use crate::{exceptions, IntoPy, PyObject};
|
||||
use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject, Python};
|
||||
|
||||
/// Mapping interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyMappingProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyMappingProtocol<'p>: PyClass {
|
||||
fn __len__(&'p self) -> Self::Result
|
||||
where
|
||||
Self: PyMappingLenProtocol<'p>,
|
||||
|
|
|
@ -7,13 +7,11 @@ use crate::callback::PyObjectCallbackConverter;
|
|||
use crate::class::basic::PyObjectProtocolImpl;
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::PyResult;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::FromPyObject;
|
||||
use crate::{ffi, IntoPy, PyObject};
|
||||
use crate::{ffi, FromPyObject, IntoPy, PyClass, PyObject};
|
||||
|
||||
/// Number interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyNumberProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyNumberProtocol<'p>: PyClass {
|
||||
fn __add__(lhs: Self::Left, rhs: Self::Right) -> Self::Result
|
||||
where
|
||||
Self: PyNumberAddProtocol<'p>,
|
||||
|
|
|
@ -11,15 +11,13 @@
|
|||
use crate::callback::PyObjectCallbackConverter;
|
||||
use crate::class::methods::PyMethodDef;
|
||||
use crate::err::PyResult;
|
||||
use crate::ffi;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::PyObject;
|
||||
use crate::{ffi, PyClass, PyObject};
|
||||
|
||||
/// Python Async/Await support interface.
|
||||
///
|
||||
/// Each method in this trait corresponds to Python async/await implementation.
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyAsyncProtocol<'p>: PyTypeInfo {
|
||||
pub trait PyAsyncProtocol<'p>: PyClass {
|
||||
fn __await__(&'p self) -> Self::Result
|
||||
where
|
||||
Self: PyAsyncAwaitProtocol<'p>,
|
||||
|
|
|
@ -5,18 +5,14 @@
|
|||
|
||||
use crate::callback::{BoolCallbackConverter, LenResultConverter, PyObjectCallbackConverter};
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::PyAny;
|
||||
use crate::FromPyObject;
|
||||
use crate::Python;
|
||||
use crate::{exceptions, IntoPy, PyObject};
|
||||
use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject, Python};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
/// Sequence interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PySequenceProtocol<'p>: PyTypeInfo + Sized {
|
||||
pub trait PySequenceProtocol<'p>: PyClass + Sized {
|
||||
fn __len__(&'p self) -> Self::Result
|
||||
where
|
||||
Self: PySequenceLenProtocol<'p>,
|
||||
|
@ -267,7 +263,7 @@ mod sq_ass_item_impl {
|
|||
{
|
||||
let py = Python::assume_gil_acquired();
|
||||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
|
||||
let result = if value.is_null() {
|
||||
Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
|
||||
|
@ -322,7 +318,7 @@ mod sq_ass_item_impl {
|
|||
{
|
||||
let py = Python::assume_gil_acquired();
|
||||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
|
||||
let result = if value.is_null() {
|
||||
slf.__delitem__(key.into()).into()
|
||||
|
@ -373,7 +369,7 @@ mod sq_ass_item_impl {
|
|||
{
|
||||
let py = Python::assume_gil_acquired();
|
||||
let _pool = crate::GILPool::new(py);
|
||||
let slf = py.mut_from_borrowed_ptr::<T>(slf);
|
||||
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
|
||||
|
||||
let result = if value.is_null() {
|
||||
slf.__delitem__(key.into()).into()
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//! Conversions between various states of rust and python types and their wrappers.
|
||||
use crate::err::{self, PyDowncastError, PyResult};
|
||||
use crate::object::PyObject;
|
||||
use crate::type_object::{PyObjectLayout, PyTypeInfo};
|
||||
use crate::type_object::{PyDowncastImpl, PyTypeInfo};
|
||||
use crate::types::PyAny;
|
||||
use crate::types::PyTuple;
|
||||
use crate::{ffi, gil, Py, Python};
|
||||
|
@ -254,11 +254,10 @@ pub mod extract_impl {
|
|||
|
||||
pub struct Cloned;
|
||||
pub struct Reference;
|
||||
pub struct MutReference;
|
||||
|
||||
impl<'a, T: 'a> ExtractImpl<'a, T> for Cloned
|
||||
where
|
||||
T: Clone,
|
||||
T: Clone + PyTryFrom<'a>,
|
||||
Reference: ExtractImpl<'a, &'a T>,
|
||||
{
|
||||
fn extract(source: &'a PyAny) -> PyResult<T> {
|
||||
|
@ -266,7 +265,7 @@ pub mod extract_impl {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ExtractImpl<'a, &'a T> for Reference
|
||||
impl<'a, T: 'a> ExtractImpl<'a, &'a T> for Reference
|
||||
where
|
||||
T: PyTryFrom<'a>,
|
||||
{
|
||||
|
@ -274,15 +273,6 @@ pub mod extract_impl {
|
|||
Ok(T::try_from(source)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ExtractImpl<'a, &'a mut T> for MutReference
|
||||
where
|
||||
T: PyTryFrom<'a>,
|
||||
{
|
||||
fn extract(source: &'a PyAny) -> PyResult<&'a mut T> {
|
||||
Ok(T::try_from_mut(source)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use extract_impl::ExtractImpl;
|
||||
|
@ -312,8 +302,8 @@ pub trait FromPyObjectImpl {
|
|||
|
||||
impl<'a, T> FromPyObject<'a> for T
|
||||
where
|
||||
T: FromPyObjectImpl,
|
||||
<T as FromPyObjectImpl>::Impl: ExtractImpl<'a, Self>,
|
||||
T: FromPyObjectImpl + 'a,
|
||||
<T as FromPyObjectImpl>::Impl: ExtractImpl<'a, T>,
|
||||
{
|
||||
#[inline]
|
||||
fn extract(ob: &'a PyAny) -> PyResult<T> {
|
||||
|
@ -337,108 +327,50 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
/// This trait is similar to `std::convert::TryInto`
|
||||
pub trait PyTryInto<T>: Sized {
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_into(&self) -> Result<&T, PyDowncastError>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type. With exact type check.
|
||||
fn try_into_exact(&self) -> Result<&T, PyDowncastError>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_into_mut(&self) -> Result<&mut T, PyDowncastError>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type. With exact type check.
|
||||
fn try_into_mut_exact(&self) -> Result<&mut T, PyDowncastError>;
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
/// This trait is similar to `std::convert::TryFrom`
|
||||
pub trait PyTryFrom<'v>: Sized {
|
||||
pub trait PyTryFrom<'v>: Sized + PyDowncastImpl<'v> {
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from_mut<V: Into<&'v PyAny>>(value: V) -> Result<&'v mut Self, PyDowncastError>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_mut_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v mut Self, PyDowncastError>;
|
||||
|
||||
/// Cast a PyAny to a specific type of PyObject. The caller must
|
||||
/// have already verified the reference is for this type.
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self;
|
||||
|
||||
/// Cast a PyAny to a specific type of PyObject. The caller must
|
||||
/// have already verified the reference is for this type.
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v mut Self;
|
||||
}
|
||||
|
||||
// TryFrom implies TryInto
|
||||
impl<U> PyTryInto<U> for PyAny
|
||||
where
|
||||
U: for<'v> PyTryFrom<'v>,
|
||||
{
|
||||
fn try_into(&self) -> Result<&U, PyDowncastError> {
|
||||
U::try_from(self)
|
||||
}
|
||||
fn try_into_exact(&self) -> Result<&U, PyDowncastError> {
|
||||
U::try_from_exact(self)
|
||||
}
|
||||
fn try_into_mut(&self) -> Result<&mut U, PyDowncastError> {
|
||||
U::try_from_mut(self)
|
||||
}
|
||||
fn try_into_mut_exact(&self) -> Result<&mut U, PyDowncastError> {
|
||||
U::try_from_mut_exact(self)
|
||||
}
|
||||
}
|
||||
// /// Trait implemented by Python object types that allow a checked downcast.
|
||||
// /// This trait is similar to `std::convert::TryInto`
|
||||
// pub trait PyTryInto<'v, T: PyDowncastImpl<'v>>: Sized {
|
||||
// /// Cast from PyObject to a concrete Python object type.
|
||||
// fn try_into(&self) -> Result<&T, PyDowncastError>;
|
||||
|
||||
// /// Cast from PyObject to a concrete Python object type. With exact type check.
|
||||
// fn try_into_exact(&self) -> Result<&T, PyDowncastError>;
|
||||
// }
|
||||
|
||||
impl<'v, T> PyTryFrom<'v> for T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: PyDowncastImpl<'v> + PyTypeInfo,
|
||||
{
|
||||
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v T, PyDowncastError> {
|
||||
fn try_from<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_instance(value) {
|
||||
Ok(PyTryFrom::try_from_unchecked(value))
|
||||
Ok(Self::try_from_unchecked(value))
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v T, PyDowncastError> {
|
||||
fn try_from_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v Self, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_exact_instance(value) {
|
||||
Ok(PyTryFrom::try_from_unchecked(value))
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_mut<V: Into<&'v PyAny>>(value: V) -> Result<&'v mut T, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_instance(value) {
|
||||
Ok(PyTryFrom::try_from_mut_unchecked(value))
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact<V: Into<&'v PyAny>>(value: V) -> Result<&'v mut T, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if T::is_exact_instance(value) {
|
||||
Ok(PyTryFrom::try_from_mut_unchecked(value))
|
||||
Ok(Self::try_from_unchecked(value))
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
|
@ -446,15 +378,8 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v T {
|
||||
let value = value.into();
|
||||
T::ConcreteLayout::internal_ref_cast(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v mut T {
|
||||
let value = value.into();
|
||||
T::ConcreteLayout::internal_mut_cast(value)
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v Self {
|
||||
Self::unchecked_downcast(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,33 +392,37 @@ impl FromPy<()> for Py<PyTuple> {
|
|||
|
||||
/// Raw level conversion between `*mut ffi::PyObject` and PyO3 types.
|
||||
pub unsafe trait FromPyPointer<'p>: Sized {
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self>;
|
||||
unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self>;
|
||||
unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
|
||||
match Self::from_owned_ptr_or_opt(py, ptr) {
|
||||
Some(s) => s,
|
||||
None => err::panic_after_error(),
|
||||
}
|
||||
}
|
||||
unsafe fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
unsafe fn from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
|
||||
Self::from_owned_ptr_or_panic(py, ptr)
|
||||
}
|
||||
unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<Self> {
|
||||
unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<&'p Self> {
|
||||
match Self::from_owned_ptr_or_opt(py, ptr) {
|
||||
Some(s) => Ok(s),
|
||||
None => Err(err::PyErr::fetch(py)),
|
||||
}
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self>;
|
||||
unsafe fn from_borrowed_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Option<&'p Self>;
|
||||
unsafe fn from_borrowed_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
|
||||
match Self::from_borrowed_ptr_or_opt(py, ptr) {
|
||||
Some(s) => s,
|
||||
None => err::panic_after_error(),
|
||||
}
|
||||
}
|
||||
unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> Self {
|
||||
unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> &'p Self {
|
||||
Self::from_borrowed_ptr_or_panic(py, ptr)
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyResult<Self> {
|
||||
unsafe fn from_borrowed_ptr_or_err(
|
||||
py: Python<'p>,
|
||||
ptr: *mut ffi::PyObject,
|
||||
) -> PyResult<&'p Self> {
|
||||
match Self::from_borrowed_ptr_or_opt(py, ptr) {
|
||||
Some(s) => Ok(s),
|
||||
None => Err(err::PyErr::fetch(py)),
|
||||
|
@ -501,29 +430,18 @@ pub unsafe trait FromPyPointer<'p>: Sized {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p T
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: 'p + crate::PyNativeType,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| T::ConcreteLayout::internal_ref_cast(gil::register_owned(py, p)))
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self> {
|
||||
NonNull::new(ptr).map(|p| Self::unchecked_downcast(gil::register_owned(py, p)))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr)
|
||||
.map(|p| T::ConcreteLayout::internal_ref_cast(gil::register_borrowed(py, p)))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p mut T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr).map(|p| T::ConcreteLayout::internal_mut_cast(gil::register_owned(py, p)))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr)
|
||||
.map(|p| T::ConcreteLayout::internal_mut_cast(gil::register_borrowed(py, p)))
|
||||
unsafe fn from_borrowed_ptr_or_opt(
|
||||
py: Python<'p>,
|
||||
ptr: *mut ffi::PyObject,
|
||||
) -> Option<&'p Self> {
|
||||
NonNull::new(ptr).map(|p| Self::unchecked_downcast(gil::register_borrowed(py, p)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::instance::PyNativeType;
|
|||
use crate::pyclass::PyClass;
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
|
||||
use crate::{ffi, GILPool, IntoPy, PyObject, Python};
|
||||
use crate::{ffi, AsPyRef, GILPool, IntoPy, PyObject, Python};
|
||||
use std::ptr;
|
||||
|
||||
/// Description of a python parameter; used for `parse_args()`.
|
||||
|
@ -100,8 +100,7 @@ pub fn parse_fn_args<'p>(
|
|||
// Adjust the remaining args
|
||||
let args = if accept_args {
|
||||
let py = args.py();
|
||||
let slice = args.slice(used_args as isize, nargs as isize).into_py(py);
|
||||
py.checked_cast_as(slice).unwrap()
|
||||
args.slice(used_args as isize, nargs as isize).as_ref(py)
|
||||
} else {
|
||||
args
|
||||
};
|
||||
|
|
|
@ -127,7 +127,7 @@ pub trait AsPyRef<T: PyTypeInfo>: Sized {
|
|||
impl<T: PyTypeInfo> AsPyRef<T> for Py<T> {
|
||||
fn as_ref(&self, _py: Python) -> &T {
|
||||
let any = self as *const Py<T> as *const PyAny;
|
||||
unsafe { T::ConcreteLayout::internal_ref_cast(&*any) }
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@
|
|||
|
||||
pub use crate::class::*;
|
||||
pub use crate::conversion::{
|
||||
AsPyPointer, FromPy, FromPyObject, FromPyPointer, IntoPy, IntoPyPointer, PyTryFrom, PyTryInto,
|
||||
AsPyPointer, FromPy, FromPyObject, FromPyPointer, IntoPy, IntoPyPointer, PyTryFrom,
|
||||
ToBorrowedObject, ToPyObject,
|
||||
};
|
||||
pub use crate::err::{PyDowncastError, PyErr, PyErrArguments, PyErrValue, PyResult};
|
||||
|
@ -165,6 +165,7 @@ pub mod ffi;
|
|||
pub mod freelist;
|
||||
mod gil;
|
||||
mod instance;
|
||||
mod pyref;
|
||||
#[macro_use]
|
||||
mod internal_tricks;
|
||||
pub mod marshal;
|
||||
|
|
|
@ -149,9 +149,9 @@ impl PyObject {
|
|||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
pub fn cast_as<D>(&self, py: Python) -> Result<&D, PyDowncastError>
|
||||
pub fn cast_as<'p, D>(&'p self, py: Python<'p>) -> Result<&'p D, PyDowncastError>
|
||||
where
|
||||
D: for<'v> PyTryFrom<'v>,
|
||||
D: PyTryFrom<'p>,
|
||||
{
|
||||
D::try_from(self.as_ref(py))
|
||||
}
|
||||
|
|
|
@ -3,16 +3,11 @@
|
|||
use crate::class::basic::CompareOp;
|
||||
use crate::err::{self, PyDowncastError, PyErr, PyResult};
|
||||
use crate::exceptions::TypeError;
|
||||
use crate::ffi;
|
||||
use crate::instance::PyNativeType;
|
||||
use crate::object::PyObject;
|
||||
use crate::type_object::PyTypeInfo;
|
||||
use crate::types::{PyAny, PyDict, PyIterator, PyString, PyTuple, PyType};
|
||||
use crate::AsPyPointer;
|
||||
use crate::IntoPyPointer;
|
||||
use crate::Py;
|
||||
use crate::Python;
|
||||
use crate::{FromPyObject, IntoPy, PyTryFrom, ToBorrowedObject, ToPyObject};
|
||||
use crate::{
|
||||
ffi, AsPyPointer, FromPyObject, FromPyPointer, IntoPy, IntoPyPointer, Py, PyNativeType,
|
||||
PyObject, PyTryFrom, PyTypeInfo, Python, ToBorrowedObject, ToPyObject,
|
||||
};
|
||||
use std::cmp::Ordering;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
|
@ -176,15 +171,10 @@ pub trait ObjectProtocol {
|
|||
fn get_type_ptr(&self) -> *mut ffi::PyTypeObject;
|
||||
|
||||
/// Gets the Python base object for this object.
|
||||
fn get_base(&self) -> &<Self as PyTypeInfo>::BaseType
|
||||
fn get_base<'py>(&'py self) -> &'py <Self as PyTypeInfo>::BaseType
|
||||
where
|
||||
Self: PyTypeInfo;
|
||||
|
||||
/// Gets the Python base object for this object.
|
||||
|
||||
fn get_mut_base(&mut self) -> &mut <Self as PyTypeInfo>::BaseType
|
||||
where
|
||||
Self: PyTypeInfo;
|
||||
Self: PyTypeInfo,
|
||||
<Self as PyTypeInfo>::BaseType: FromPyPointer<'py>;
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
|
||||
|
@ -455,20 +445,14 @@ where
|
|||
unsafe { (*self.as_ptr()).ob_type }
|
||||
}
|
||||
|
||||
fn get_base(&self) -> &<Self as PyTypeInfo>::BaseType
|
||||
fn get_base<'py>(&'py self) -> &'py <Self as PyTypeInfo>::BaseType
|
||||
where
|
||||
Self: PyTypeInfo,
|
||||
<Self as PyTypeInfo>::BaseType: FromPyPointer<'py>,
|
||||
{
|
||||
unsafe { self.py().from_borrowed_ptr(self.as_ptr()) }
|
||||
}
|
||||
|
||||
fn get_mut_base(&mut self) -> &mut <Self as PyTypeInfo>::BaseType
|
||||
where
|
||||
Self: PyTypeInfo,
|
||||
{
|
||||
unsafe { self.py().mut_from_borrowed_ptr(self.as_ptr()) }
|
||||
}
|
||||
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
|
||||
where
|
||||
D: PyTryFrom<'a>,
|
||||
|
|
|
@ -17,7 +17,7 @@ pub use crate::object::PyObject;
|
|||
pub use crate::objectprotocol::ObjectProtocol;
|
||||
pub use crate::pyclass_init::PyClassInitializer;
|
||||
pub use crate::python::Python;
|
||||
pub use crate::{FromPy, FromPyObject, IntoPy, IntoPyPointer, PyTryFrom, PyTryInto, ToPyObject};
|
||||
pub use crate::{FromPy, FromPyObject, IntoPy, IntoPyPointer, PyTryFrom, ToPyObject};
|
||||
// This is only part of the prelude because we need it for the pymodule function
|
||||
pub use crate::types::PyModule;
|
||||
pub use pyo3cls::pymodule;
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::conversion::{AsPyPointer, FromPyPointer, ToPyObject};
|
|||
use crate::pyclass::PyClass;
|
||||
use crate::pyclass_init::PyClassInitializer;
|
||||
use crate::pyclass_slots::{PyClassDict, PyClassWeakRef};
|
||||
use crate::type_object::{PyObjectLayout, PyObjectSizedLayout};
|
||||
use crate::type_object::{PyDowncastImpl, PyObjectLayout, PyObjectSizedLayout};
|
||||
use crate::types::PyAny;
|
||||
use crate::{ffi, gil, PyErr, PyObject, PyResult, PyTypeInfo, Python};
|
||||
use std::mem::ManuallyDrop;
|
||||
|
@ -42,20 +42,7 @@ pub struct PyCell<T: PyClass> {
|
|||
|
||||
impl<T: PyClass> PyCell<T> {
|
||||
/// Make new `PyCell` on the Python heap and returns the reference of it.
|
||||
pub fn new_ref(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
{
|
||||
unsafe {
|
||||
let initializer = value.into();
|
||||
let self_ = initializer.create_cell(py)?;
|
||||
FromPyPointer::from_owned_ptr_or_err(py, self_ as _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Make new `PyCell` on the Python heap and returns the mutable reference of it.
|
||||
pub fn new_mut(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&mut Self>
|
||||
pub fn new(py: Python, value: impl Into<PyClassInitializer<T>>) -> PyResult<&Self>
|
||||
where
|
||||
<T::BaseType as PyTypeInfo>::ConcreteLayout:
|
||||
crate::type_object::PyObjectSizedLayout<T::BaseType>,
|
||||
|
@ -98,14 +85,6 @@ impl<T: PyClass> PyObjectLayout<T> for PyCell<T> {
|
|||
fn get_super_or(&mut self) -> Option<&mut <T::BaseType as PyTypeInfo>::ConcreteLayout> {
|
||||
Some(&mut self.ob_base)
|
||||
}
|
||||
unsafe fn internal_ref_cast(obj: &PyAny) -> &T {
|
||||
let cell = obj.as_ptr() as *const Self;
|
||||
&(*cell).pyclass
|
||||
}
|
||||
unsafe fn internal_mut_cast(obj: &PyAny) -> &mut T {
|
||||
let cell = obj.as_ptr() as *const _ as *mut Self;
|
||||
&mut (*cell).pyclass
|
||||
}
|
||||
unsafe fn py_drop(&mut self, py: Python) {
|
||||
ManuallyDrop::drop(&mut self.pyclass);
|
||||
self.dict.clear_dict(py);
|
||||
|
@ -117,6 +96,13 @@ impl<T: PyClass> PyObjectLayout<T> for PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'py, T: 'py + PyClass> PyDowncastImpl<'py> for PyCell<T> {
|
||||
unsafe fn unchecked_downcast(obj: &PyAny) -> &'py Self {
|
||||
&*(obj.as_ptr() as *const Self)
|
||||
}
|
||||
private_impl! {}
|
||||
}
|
||||
|
||||
impl<T: PyClass> PyObjectSizedLayout<T> for PyCell<T> {}
|
||||
|
||||
impl<T: PyClass> AsPyPointer for PyCell<T> {
|
||||
|
@ -150,28 +136,17 @@ impl<T: PyClass> ToPyObject for &mut PyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p PyCell<T>
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for PyCell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<&'p Self> {
|
||||
NonNull::new(ptr).map(|p| &*(gil::register_owned(py, p).as_ptr() as *const PyCell<T>))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
unsafe fn from_borrowed_ptr_or_opt(
|
||||
py: Python<'p>,
|
||||
ptr: *mut ffi::PyObject,
|
||||
) -> Option<&'p Self> {
|
||||
NonNull::new(ptr).map(|p| &*(gil::register_borrowed(py, p).as_ptr() as *const PyCell<T>))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'p, T> FromPyPointer<'p> for &'p mut PyCell<T>
|
||||
where
|
||||
T: PyClass,
|
||||
{
|
||||
unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr)
|
||||
.map(|p| &mut *(gil::register_owned(py, p).as_ptr() as *const _ as *mut PyCell<T>))
|
||||
}
|
||||
unsafe fn from_borrowed_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<Self> {
|
||||
NonNull::new(ptr)
|
||||
.map(|p| &mut *(gil::register_borrowed(py, p).as_ptr() as *const _ as *mut PyCell<T>))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::ffi;
|
|||
use crate::gil::{self, GILGuard};
|
||||
use crate::instance::AsPyRef;
|
||||
use crate::object::PyObject;
|
||||
use crate::type_object::{PyObjectLayout, PyTypeInfo, PyTypeObject};
|
||||
use crate::type_object::{PyDowncastImpl, PyObjectLayout, PyTypeInfo, PyTypeObject};
|
||||
use crate::types::{PyAny, PyDict, PyModule, PyType};
|
||||
use crate::AsPyPointer;
|
||||
use crate::{FromPyPointer, IntoPyPointer, PyTryFrom};
|
||||
|
@ -275,19 +275,19 @@ impl<'p> Python<'p> {
|
|||
/// Register object in release pool, and try to downcast to specific type.
|
||||
pub fn checked_cast_as<T>(self, obj: PyObject) -> Result<&'p T, PyDowncastError>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: PyTryFrom<'p>,
|
||||
{
|
||||
let p = unsafe { gil::register_owned(self, obj.into_nonnull()) };
|
||||
<T as PyTryFrom>::try_from(p)
|
||||
let obj = unsafe { gil::register_owned(self, obj.into_nonnull()) };
|
||||
<T as PyTryFrom>::try_from(obj)
|
||||
}
|
||||
|
||||
/// Register object in release pool, and do unchecked downcast to specific type.
|
||||
pub unsafe fn cast_as<T>(self, obj: PyObject) -> &'p T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: PyDowncastImpl<'p> + PyTypeInfo,
|
||||
{
|
||||
let p = gil::register_owned(self, obj.into_nonnull());
|
||||
T::ConcreteLayout::internal_ref_cast(p)
|
||||
let obj = gil::register_owned(self, obj.into_nonnull());
|
||||
T::unchecked_downcast(obj)
|
||||
}
|
||||
|
||||
/// Register `ffi::PyObject` pointer in release pool
|
||||
|
@ -304,16 +304,7 @@ impl<'p> Python<'p> {
|
|||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_owned_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
FromPyPointer::from_owned_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register `ffi::PyObject` pointer in release pool,
|
||||
/// Do unchecked downcast to specific type. Returns mutable reference.
|
||||
pub unsafe fn mut_from_owned_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p mut T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: FromPyPointer<'p>,
|
||||
{
|
||||
FromPyPointer::from_owned_ptr(self, ptr)
|
||||
}
|
||||
|
@ -324,7 +315,7 @@ impl<'p> Python<'p> {
|
|||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_owned_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: FromPyPointer<'p>,
|
||||
{
|
||||
FromPyPointer::from_owned_ptr_or_err(self, ptr)
|
||||
}
|
||||
|
@ -335,7 +326,7 @@ impl<'p> Python<'p> {
|
|||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_owned_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: FromPyPointer<'p>,
|
||||
{
|
||||
FromPyPointer::from_owned_ptr_or_opt(self, ptr)
|
||||
}
|
||||
|
@ -346,17 +337,7 @@ impl<'p> Python<'p> {
|
|||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
{
|
||||
FromPyPointer::from_borrowed_ptr(self, ptr)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
/// Panics if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
pub unsafe fn mut_from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p mut T
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: FromPyPointer<'p>,
|
||||
{
|
||||
FromPyPointer::from_borrowed_ptr(self, ptr)
|
||||
}
|
||||
|
@ -367,7 +348,7 @@ impl<'p> Python<'p> {
|
|||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: FromPyPointer<'p>,
|
||||
{
|
||||
FromPyPointer::from_borrowed_ptr_or_err(self, ptr)
|
||||
}
|
||||
|
@ -378,7 +359,7 @@ impl<'p> Python<'p> {
|
|||
#[allow(clippy::wrong_self_convention)]
|
||||
pub unsafe fn from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
|
||||
where
|
||||
T: PyTypeInfo,
|
||||
T: FromPyPointer<'p>,
|
||||
{
|
||||
FromPyPointer::from_borrowed_ptr_or_opt(self, ptr)
|
||||
}
|
||||
|
|
|
@ -22,15 +22,6 @@ pub trait PyObjectLayout<T: PyTypeInfo> {
|
|||
None
|
||||
}
|
||||
|
||||
unsafe fn internal_ref_cast(obj: &PyAny) -> &T {
|
||||
&*(obj as *const _ as *const T)
|
||||
}
|
||||
|
||||
#[allow(clippy::mut_from_ref)]
|
||||
unsafe fn internal_mut_cast(obj: &PyAny) -> &mut T {
|
||||
&mut *(obj as *const _ as *const T as *mut T)
|
||||
}
|
||||
|
||||
unsafe fn py_init(&mut self, _value: T) {}
|
||||
unsafe fn py_drop(&mut self, _py: Python) {}
|
||||
}
|
||||
|
@ -61,6 +52,25 @@ pub mod type_flags {
|
|||
pub const EXTENDED: usize = 1 << 4;
|
||||
}
|
||||
|
||||
/// Reference abstraction for `PyClass` and `PyNativeType`.
|
||||
// NOTE: This trait is separated from PyTypeInfo since make it PyTypeInfo<`py> is confusing...
|
||||
// When GAT and type Ref<'py> becomes stable, let's merge this trait to
|
||||
// PyConcreteLayout or Py
|
||||
pub unsafe trait PyDowncastImpl<'py> {
|
||||
unsafe fn unchecked_downcast(obj: &PyAny) -> &'py Self;
|
||||
private_decl! {}
|
||||
}
|
||||
|
||||
unsafe impl<'py, T> PyDowncastImpl<'py> for T
|
||||
where
|
||||
T: 'py + crate::PyNativeType,
|
||||
{
|
||||
unsafe fn unchecked_downcast(obj: &PyAny) -> &'py Self {
|
||||
&*(obj as *const _ as *const Self)
|
||||
}
|
||||
private_impl! {}
|
||||
}
|
||||
|
||||
/// Python type information.
|
||||
/// All Python native types(e.g., `PyDict`) and `#[pyclass]` structs implement this trait.
|
||||
///
|
||||
|
|
|
@ -36,17 +36,10 @@ pyobject_native_type_convert!(
|
|||
pyobject_native_type_extract!(PyAny);
|
||||
|
||||
impl PyAny {
|
||||
pub fn downcast_ref<T>(&self) -> Result<&T, PyDowncastError>
|
||||
pub fn downcast<T>(&self) -> Result<&T, PyDowncastError>
|
||||
where
|
||||
T: for<'gil> PyTryFrom<'gil>,
|
||||
for<'py> T: PyTryFrom<'py>,
|
||||
{
|
||||
T::try_from(self)
|
||||
}
|
||||
|
||||
pub fn downcast_mut<T>(&self) -> Result<&mut T, PyDowncastError>
|
||||
where
|
||||
T: for<'gil> PyTryFrom<'gil>,
|
||||
{
|
||||
T::try_from_mut(self)
|
||||
<T as PyTryFrom>::try_from(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ impl PyModule {
|
|||
/// Return the index (`__all__`) of the module, creating one if needed.
|
||||
pub fn index(&self) -> PyResult<&PyList> {
|
||||
match self.getattr("__all__") {
|
||||
Ok(idx) => idx.downcast_ref().map_err(PyErr::from),
|
||||
Ok(idx) => idx.downcast().map_err(PyErr::from),
|
||||
Err(err) => {
|
||||
if err.is_instance::<exceptions::AttributeError>(self.py()) {
|
||||
let l = PyList::empty(self.py());
|
||||
|
|
|
@ -298,34 +298,11 @@ impl<'v> PyTryFrom<'v> for PySequence {
|
|||
<PySequence as PyTryFrom>::try_from(value)
|
||||
}
|
||||
|
||||
fn try_from_mut<V: Into<&'v PyAny>>(value: V) -> Result<&'v mut PySequence, PyDowncastError> {
|
||||
let value = value.into();
|
||||
unsafe {
|
||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||
Ok(<PySequence as PyTryFrom>::try_from_mut_unchecked(value))
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact<V: Into<&'v PyAny>>(
|
||||
value: V,
|
||||
) -> Result<&'v mut PySequence, PyDowncastError> {
|
||||
<PySequence as PyTryFrom>::try_from_mut(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v PySequence {
|
||||
let ptr = value.into() as *const _ as *const PySequence;
|
||||
&*ptr
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn try_from_mut_unchecked<V: Into<&'v PyAny>>(value: V) -> &'v mut PySequence {
|
||||
let ptr = value.into() as *const _ as *mut PySequence;
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -3,15 +3,11 @@
|
|||
use crate::conversion::FromPyObject;
|
||||
use crate::conversion::{PyTryFrom, ToPyObject};
|
||||
use crate::err::{PyErr, PyResult};
|
||||
use crate::gil;
|
||||
use crate::instance::PyNativeType;
|
||||
use crate::internal_tricks::Unsendable;
|
||||
use crate::object::PyObject;
|
||||
use crate::types::PyAny;
|
||||
use crate::AsPyPointer;
|
||||
use crate::IntoPy;
|
||||
use crate::Python;
|
||||
use crate::{ffi, FromPy};
|
||||
use crate::{ffi, gil, AsPyPointer, FromPy, IntoPy, Python};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
|
|
Loading…
Reference in a new issue