refactor downcast process
This commit is contained in:
parent
d78692017e
commit
325070f6c9
|
@ -85,20 +85,6 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
f(self.as_ptr())
|
||||
}
|
||||
}
|
||||
impl<'a> _pyo3::IntoPyObject for &'a #cls
|
||||
{
|
||||
#[inline]
|
||||
fn into_object<'p>(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
||||
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
impl<'a> _pyo3::IntoPyObject for &'a mut #cls
|
||||
{
|
||||
#[inline]
|
||||
fn into_object<'p>(self, py: _pyo3::Python) -> _pyo3::PyObject {
|
||||
unsafe { _pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
impl<'a> std::convert::From<&'a mut #cls> for &'a #cls
|
||||
{
|
||||
fn from(ob: &'a mut #cls) -> Self {
|
||||
|
@ -110,8 +96,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
unsafe {
|
||||
{self as *const _ as *mut u8}
|
||||
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET)
|
||||
as *mut ffi::PyObject
|
||||
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut ffi::PyObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,12 +193,6 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
static mut TYPE_OBJECT: _pyo3::ffi::PyTypeObject = _pyo3::ffi::PyTypeObject_INIT;
|
||||
&mut TYPE_OBJECT
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_instance(ptr: *mut _pyo3::ffi::PyObject) -> bool {
|
||||
unsafe {_pyo3::ffi::PyObject_TypeCheck(
|
||||
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0}
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::typeob::PyTypeObject for #cls {
|
||||
|
@ -236,89 +215,6 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
}
|
||||
}
|
||||
|
||||
impl _pyo3::PyDowncastFrom for #cls
|
||||
{
|
||||
fn try_downcast_from(ob: &_pyo3::PyObjectRef) -> Option<&#cls>
|
||||
{
|
||||
unsafe {
|
||||
let ptr = ob.as_ptr();
|
||||
let checked = ffi::PyObject_TypeCheck(
|
||||
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
||||
|
||||
if checked {
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_exact_downcast_from(ob: &_pyo3::PyObjectRef) -> Option<&#cls>
|
||||
{
|
||||
unsafe {
|
||||
let ptr = ob.as_ptr();
|
||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||
{
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
|
||||
{
|
||||
let ptr = (ob.as_ptr() as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
&*ptr
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self
|
||||
{
|
||||
let ptr = (ob.as_ptr() as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
impl _pyo3::PyMutDowncastFrom for #cls
|
||||
{
|
||||
fn try_mut_downcast_from(ob: &mut _pyo3::PyObjectRef) -> Option<&mut #cls>
|
||||
{
|
||||
unsafe {
|
||||
let ptr = ob.as_ptr();
|
||||
let checked = ffi::PyObject_TypeCheck(
|
||||
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
||||
|
||||
if checked {
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_mut().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
fn try_mut_exact_downcast_from(ob: &mut _pyo3::PyObjectRef) -> Option<&mut #cls>
|
||||
{
|
||||
unsafe {
|
||||
let ptr = ob.as_ptr();
|
||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||
{
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_mut().unwrap())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#extra
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
|
||||
|
||||
//! Python argument parsing
|
||||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use python::Python;
|
||||
use conversion::PyTryFrom;
|
||||
use objects::{PyObjectRef, PyTuple, PyDict, PyString, exc};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -80,8 +80,8 @@ pub fn parse_args<'p>(fname: Option<&str>, params: &[ParamDescription],
|
|||
if !accept_kwargs && used_keywords != nkeywords {
|
||||
// check for extraneous keyword arguments
|
||||
for item in kwargs.unwrap().items().iter() {
|
||||
let item = PyTuple::downcast_from(item)?;
|
||||
let key = PyString::downcast_from(item.get_item(0))?.to_string()?;
|
||||
let item = PyTuple::try_from(item)?;
|
||||
let key = PyString::try_from(item.get_item(0))?.to_string()?;
|
||||
if !params.iter().any(|p| p.name == key) {
|
||||
return Err(exc::TypeError::new(
|
||||
format!("'{}' is an invalid keyword argument for this function", key)));
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::PyDowncastFrom;
|
||||
use callback::PyObjectCallbackConverter;
|
||||
use typeob::PyTypeInfo;
|
||||
use class::methods::PyMethodDef;
|
||||
|
@ -20,7 +19,7 @@ use class::methods::PyMethodDef;
|
|||
///
|
||||
/// Each method in this trait corresponds to Python async/await implementation.
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyAsyncProtocol<'p>: PyTypeInfo + PyDowncastFrom {
|
||||
pub trait PyAsyncProtocol<'p>: PyTypeInfo {
|
||||
|
||||
fn __await__(&'p self)
|
||||
-> Self::Result where Self: PyAsyncAwaitProtocol<'p> { unimplemented!() }
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::os::raw::c_int;
|
|||
use ::CompareOp;
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::{Python, IntoPyPointer, PyDowncastFrom};
|
||||
use python::{Python, IntoPyPointer};
|
||||
use objects::{exc, PyObjectRef};
|
||||
use typeob::PyTypeInfo;
|
||||
use conversion::{FromPyObject, IntoPyObject};
|
||||
|
@ -23,7 +23,7 @@ use class::methods::PyMethodDef;
|
|||
|
||||
/// Basic python class customization
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyObjectProtocol<'p>: PyTypeInfo + PyDowncastFrom + Sized + 'static {
|
||||
pub trait PyObjectProtocol<'p>: PyTypeInfo {
|
||||
|
||||
fn __getattr__(&'p self, name: Self::Name)
|
||||
-> Self::Result where Self: PyObjectGetAttrProtocol<'p> {unimplemented!()}
|
||||
|
@ -351,14 +351,14 @@ impl<'p, T> PyObjectRichcmpProtocolImpl for T where T: PyObjectProtocol<'p>
|
|||
}
|
||||
}
|
||||
impl<T> PyObjectRichcmpProtocolImpl for T
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p> + PyDowncastFrom
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p>
|
||||
{
|
||||
#[inline]
|
||||
fn tp_richcompare() -> Option<ffi::richcmpfunc> {
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject,
|
||||
op: c_int) -> *mut ffi::PyObject
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p> + PyDowncastFrom
|
||||
where T: for<'p> PyObjectRichcmpProtocol<'p>
|
||||
{
|
||||
let _pool = ::GILPool::new();
|
||||
let py = Python::assume_gil_acquired();
|
||||
|
|
|
@ -10,7 +10,6 @@ use std::os::raw::c_int;
|
|||
use ffi;
|
||||
use err::PyResult;
|
||||
use typeob::PyTypeInfo;
|
||||
use python::PyDowncastFrom;
|
||||
use callback::UnitCallbackConverter;
|
||||
|
||||
|
||||
|
@ -19,7 +18,7 @@ use callback::UnitCallbackConverter;
|
|||
/// more information on buffer protocol can be found
|
||||
/// https://docs.python.org/3/c-api/buffer.html
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyBufferProtocol<'p> : PyTypeInfo + PyDowncastFrom
|
||||
pub trait PyBufferProtocol<'p> : PyTypeInfo
|
||||
{
|
||||
fn bf_getbuffer(&'p self,
|
||||
view: *mut ffi::Py_buffer, flags: c_int) -> Self::Result
|
||||
|
|
|
@ -9,7 +9,6 @@ use std::os::raw::c_int;
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::PyDowncastFrom;
|
||||
use objects::{PyType, PyObjectRef};
|
||||
use callback::{PyObjectCallbackConverter, UnitCallbackConverter};
|
||||
use typeob::PyTypeInfo;
|
||||
|
@ -19,7 +18,7 @@ use conversion::{IntoPyObject, FromPyObject};
|
|||
|
||||
/// Descriptor interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyDescrProtocol<'p>: PyTypeInfo + PyDowncastFrom {
|
||||
pub trait PyDescrProtocol<'p>: PyTypeInfo {
|
||||
|
||||
fn __get__(&'p self, instance: &'p PyObjectRef, owner: Option<&'p PyType>)
|
||||
-> Self::Result where Self: PyDescrGetProtocol<'p> { unimplemented!() }
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
use std::os::raw::{c_int, c_void};
|
||||
|
||||
use ffi;
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom};
|
||||
use python::{Python, ToPyPointer};
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
pub struct PyTraverseError(c_int);
|
||||
|
||||
/// GC support
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyGCProtocol<'p> : PyTypeInfo + PyDowncastFrom {
|
||||
pub trait PyGCProtocol<'p> : PyTypeInfo {
|
||||
|
||||
fn __traverse__(&'p self, visit: PyVisit)
|
||||
-> Result<(), PyTraverseError> { unimplemented!() }
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::ptr;
|
|||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::{Python, PyDowncastFrom, IntoPyPointer};
|
||||
use python::{Python, IntoPyPointer};
|
||||
use typeob::PyTypeInfo;
|
||||
use conversion::IntoPyObject;
|
||||
use callback::{CallbackConverter, PyObjectCallbackConverter};
|
||||
|
@ -17,7 +17,7 @@ use callback::{CallbackConverter, PyObjectCallbackConverter};
|
|||
/// more information
|
||||
/// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_iter
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyIterProtocol<'p> : PyTypeInfo + PyDowncastFrom {
|
||||
pub trait PyIterProtocol<'p> : PyTypeInfo {
|
||||
fn __iter__(&'p mut self)
|
||||
-> Self::Result where Self: PyIterIterProtocol<'p> { unimplemented!() }
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ macro_rules! py_unary_func {
|
|||
};
|
||||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:expr, $ret_type:ty) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
let _pool = $crate::GILPool::new();
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
|
@ -26,7 +26,7 @@ macro_rules! py_unary_func {
|
|||
($trait:ident, $class:ident :: $f:ident, $res_type:ty, $conv:ty) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject)
|
||||
-> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
let _pool = $crate::GILPool::new();
|
||||
|
@ -46,7 +46,7 @@ macro_rules! py_len_func {
|
|||
($trait:ident, $class:ident :: $f:ident, $conv:expr) => {{
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject)
|
||||
-> $crate::ffi::Py_ssize_t
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
let _pool = $crate::GILPool::new();
|
||||
let py = Python::assume_gil_acquired();
|
||||
|
@ -69,7 +69,7 @@ macro_rules! py_binary_func{
|
|||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject) -> $return
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
let _pool = $crate::GILPool::new();
|
||||
|
@ -94,7 +94,7 @@ macro_rules! py_binary_num_func{
|
|||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(lhs: *mut ffi::PyObject,
|
||||
rhs: *mut ffi::PyObject) -> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
let _pool = $crate::GILPool::new();
|
||||
|
@ -122,7 +122,7 @@ macro_rules! py_binary_self_func{
|
|||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: *mut ffi::PyObject) -> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
|
||||
|
@ -158,7 +158,7 @@ macro_rules! py_ssizearg_func {
|
|||
#[allow(unused_mut)]
|
||||
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject,
|
||||
arg: $crate::ffi::Py_ssize_t) -> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
let _pool = $crate::GILPool::new();
|
||||
let py = $crate::Python::assume_gil_acquired();
|
||||
|
@ -180,7 +180,7 @@ macro_rules! py_ternary_func{
|
|||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject,
|
||||
arg1: *mut $crate::ffi::PyObject,
|
||||
arg2: *mut $crate::ffi::PyObject) -> $return_type
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
|
||||
|
@ -211,7 +211,7 @@ macro_rules! py_ternary_num_func{
|
|||
unsafe extern "C" fn wrap<T>(arg1: *mut $crate::ffi::PyObject,
|
||||
arg2: *mut $crate::ffi::PyObject,
|
||||
arg3: *mut $crate::ffi::PyObject) -> *mut $crate::ffi::PyObject
|
||||
where T: for<'p> $trait<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
|
||||
|
@ -374,7 +374,7 @@ macro_rules! py_func_set_del{
|
|||
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject,
|
||||
name: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject) -> $crate::c_int
|
||||
where T: for<'p> $trait<'p> + for<'p> $trait2<'p> + $crate::PyDowncastFrom
|
||||
where T: for<'p> $trait<'p> + for<'p> $trait2<'p>
|
||||
{
|
||||
use $crate::ObjectProtocol;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
use ffi;
|
||||
use err::{PyErr, PyResult};
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use python::Python;
|
||||
use objects::exc;
|
||||
use callback::{PyObjectCallbackConverter, LenResultConverter};
|
||||
use conversion::{IntoPyObject, FromPyObject};
|
||||
|
@ -15,7 +15,7 @@ use class::methods::PyMethodDef;
|
|||
|
||||
/// Mapping interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyMappingProtocol<'p>: PyTypeInfo + PyDowncastFrom + Sized + 'static {
|
||||
pub trait PyMappingProtocol<'p>: PyTypeInfo {
|
||||
|
||||
fn __len__(&'p self)
|
||||
-> Self::Result where Self: PyMappingLenProtocol<'p> {unimplemented!()}
|
||||
|
|
|
@ -9,11 +9,11 @@ use callback::PyObjectCallbackConverter;
|
|||
use typeob::PyTypeInfo;
|
||||
use class::methods::PyMethodDef;
|
||||
use class::basic::PyObjectProtocolImpl;
|
||||
use {IntoPyObject, FromPyObject, PyDowncastFrom};
|
||||
use {IntoPyObject, FromPyObject};
|
||||
|
||||
/// Number interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PyNumberProtocol<'p>: PyTypeInfo + PyDowncastFrom {
|
||||
pub trait PyNumberProtocol<'p>: PyTypeInfo {
|
||||
|
||||
fn __add__(lhs: Self::Left, rhs: Self::Right)
|
||||
-> Self::Result where Self: PyNumberAddProtocol<'p> { unimplemented!() }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
use std::os::raw::c_int;
|
||||
|
||||
use ffi;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use python::Python;
|
||||
use err::{PyErr, PyResult};
|
||||
use objects::{exc, PyObjectRef};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
@ -17,7 +17,7 @@ use conversion::{IntoPyObject, FromPyObject};
|
|||
|
||||
/// Sequece interface
|
||||
#[allow(unused_variables)]
|
||||
pub trait PySequenceProtocol<'p>: PyTypeInfo + PyDowncastFrom
|
||||
pub trait PySequenceProtocol<'p>: PyTypeInfo + Sized
|
||||
{
|
||||
fn __len__(&'p self) -> Self::Result
|
||||
where Self: PySequenceLenProtocol<'p> { unimplemented!() }
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
//! This module contains some conversion traits
|
||||
|
||||
use ffi;
|
||||
use err::PyResult;
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom};
|
||||
use err::{PyResult, PyDowncastError};
|
||||
use python::{Python, ToPyPointer};
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyTuple};
|
||||
use typeob::PyTypeInfo;
|
||||
|
@ -115,15 +116,6 @@ impl <'a, T: ?Sized> ToPyObject for &'a T where T: ToPyObject {
|
|||
}
|
||||
}
|
||||
|
||||
impl <'a, T: ?Sized> ToBorrowedObject for &'a T where T: ToBorrowedObject {
|
||||
|
||||
#[inline]
|
||||
fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
|
||||
where F: FnOnce(*mut ffi::PyObject) -> R
|
||||
{
|
||||
<T as ToBorrowedObject>::with_borrowed_ptr(*self, py, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// `Option::Some<T>` is converted like `T`.
|
||||
/// `Option::None` is converted to Python `None`.
|
||||
|
@ -157,15 +149,29 @@ impl IntoPyObject for () {
|
|||
py.None()
|
||||
}
|
||||
}
|
||||
impl<'a, T> IntoPyObject for &'a T where T: ToPyPointer
|
||||
{
|
||||
#[inline]
|
||||
fn into_object<'p>(self, py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
impl<'a, T> IntoPyObject for &'a mut T where T: ToPyPointer
|
||||
{
|
||||
#[inline]
|
||||
fn into_object<'p>(self, py: Python) -> PyObject {
|
||||
unsafe { PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract reference to instance from `PyObject`
|
||||
impl<'a, T> FromPyObject<'a> for &'a T
|
||||
where T: PyTypeInfo + PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(ob: &'a PyObjectRef) -> PyResult<&'a T>
|
||||
{
|
||||
Ok(PyDowncastFrom::downcast_from(ob)?)
|
||||
Ok(T::try_from(ob)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,3 +189,128 @@ impl<'source, T> FromPyObject<'source> for Option<T> where T: FromPyObject<'sour
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
/// This trait is similar to `std::convert::TryInto`
|
||||
pub trait PyTryInto<T>: Sized {
|
||||
/// The type returned in the event of a conversion error.
|
||||
type Error;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_into(&self) -> Result<&T, Self::Error>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type. With exact type check.
|
||||
fn try_into_exact(&self) -> Result<&T, Self::Error>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_into_mut(&self) -> Result<&mut T, Self::Error>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type. With exact type check.
|
||||
fn try_into_mut_exact(&self) -> Result<&mut T, Self::Error>;
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
/// This trait is similar to `std::convert::TryFrom`
|
||||
pub trait PyTryFrom: Sized {
|
||||
/// The type returned in the event of a conversion error.
|
||||
type Error;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from(value: &PyObjectRef) -> Result<&Self, Self::Error>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&Self, Self::Error>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject.
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut Self, Self::Error>;
|
||||
|
||||
/// Cast from a concrete Python object type to PyObject. With exact type check.
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut Self, Self::Error>;
|
||||
}
|
||||
|
||||
// TryFrom implies TryInto
|
||||
impl<U> PyTryInto<U> for PyObjectRef where U: PyTryFrom
|
||||
{
|
||||
type Error = U::Error;
|
||||
|
||||
fn try_into(&self) -> Result<&U, U::Error> {
|
||||
U::try_from(self)
|
||||
}
|
||||
fn try_into_exact(&self) -> Result<&U, U::Error> {
|
||||
U::try_from_exact(self)
|
||||
}
|
||||
fn try_into_mut(&self) -> Result<&mut U, U::Error> {
|
||||
U::try_from_mut(self)
|
||||
}
|
||||
fn try_into_mut_exact(&self) -> Result<&mut U, U::Error> {
|
||||
U::try_from_mut_exact(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T> PyTryFrom for T
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
type Error = PyDowncastError;
|
||||
|
||||
fn try_from(value: &PyObjectRef) -> Result<&T, Self::Error> {
|
||||
unsafe {
|
||||
if T::is_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
value as *const _ as *mut u8 as *mut T
|
||||
} else {
|
||||
(value.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T
|
||||
};
|
||||
Ok(&*ptr)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&T, Self::Error> {
|
||||
unsafe {
|
||||
if T::is_exact_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
value as *const _ as *mut u8 as *mut T
|
||||
} else {
|
||||
(value.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T
|
||||
};
|
||||
Ok(&*ptr)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut T, Self::Error> {
|
||||
unsafe {
|
||||
if T::is_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
value as *const _ as *mut u8 as *mut T
|
||||
} else {
|
||||
(value.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T
|
||||
};
|
||||
Ok(&mut *ptr)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut T, Self::Error> {
|
||||
unsafe {
|
||||
if T::is_exact_instance(value.as_ptr()) {
|
||||
let ptr = if T::OFFSET == 0 {
|
||||
value as *const _ as *mut u8 as *mut T
|
||||
} else {
|
||||
(value.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T
|
||||
};
|
||||
Ok(&mut *ptr)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ use std::marker::PhantomData;
|
|||
|
||||
use ffi;
|
||||
use pythonrun;
|
||||
use err::{PyResult, PyErr, PyDowncastError};
|
||||
use err::{PyResult, PyErr};
|
||||
use object::PyObject;
|
||||
use objects::PyObjectRef;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use conversion::{ToPyObject, IntoPyObject, FromPyObject};
|
||||
use python::{Python, IntoPyPointer, ToPyPointer, PyDowncastInto, PyDowncastFrom};
|
||||
use python::{Python, IntoPyPointer, ToPyPointer};
|
||||
use typeob::{PyTypeInfo, PyObjectAlloc};
|
||||
|
||||
|
||||
|
@ -175,7 +175,7 @@ impl<T> Py<T> where T: PyTypeInfo,
|
|||
/// Returns references to `T`
|
||||
pub fn new_ref<F>(py: Python, f: F) -> PyResult<&T>
|
||||
where F: FnOnce(::PyToken) -> T,
|
||||
T: PyObjectAlloc<T> + PyDowncastFrom
|
||||
T: PyObjectAlloc<T>
|
||||
{
|
||||
let ob = f(PyToken(PhantomData));
|
||||
|
||||
|
@ -189,7 +189,7 @@ impl<T> Py<T> where T: PyTypeInfo,
|
|||
/// Returns mutable references to `T`
|
||||
pub fn new_mut<F>(py: Python, f: F) -> PyResult<&mut T>
|
||||
where F: FnOnce(::PyToken) -> T,
|
||||
T: PyObjectAlloc<T> + PyDowncastFrom
|
||||
T: PyObjectAlloc<T>
|
||||
{
|
||||
let ob = f(PyToken(PhantomData));
|
||||
|
||||
|
@ -323,45 +323,6 @@ impl<'a, T> std::convert::From<&'a mut T> for PyObject
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> PyDowncastInto for Py<T> where T: PyTypeInfo
|
||||
{
|
||||
fn downcast_into<I>(_py: Python, ob: I) -> Result<Self, PyDowncastError>
|
||||
where I: IntoPyPointer
|
||||
{
|
||||
unsafe{
|
||||
let ptr = ob.into_ptr();
|
||||
if T::is_instance(ptr) {
|
||||
Ok(Py::from_owned_ptr(ptr))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn downcast_into_from_ptr(_py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Result<Self, PyDowncastError>
|
||||
{
|
||||
unsafe{
|
||||
if T::is_instance(ptr) {
|
||||
Ok(Py::from_owned_ptr(ptr))
|
||||
} else {
|
||||
ffi::Py_DECREF(ptr);
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unchecked_downcast_into<I>(ob: I) -> Self
|
||||
where I: IntoPyPointer
|
||||
{
|
||||
unsafe{
|
||||
Py::from_owned_ptr(ob.into_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, T> FromPyObject<'a> for Py<T> where T: ToPyPointer + FromPyObject<'a>
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(specialization, proc_macro, const_fn)]
|
||||
#![feature(specialization, proc_macro, const_fn, try_from)]
|
||||
|
||||
//! Rust bindings to the Python interpreter.
|
||||
//!
|
||||
|
@ -154,11 +154,10 @@ pub use err::{PyErr, PyErrValue, PyResult, PyDowncastError, PyErrArguments};
|
|||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use object::PyObject;
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer,
|
||||
PyMutDowncastFrom, PyDowncastFrom, PyDowncastInto};
|
||||
pub use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
pub use pythonrun::{GILGuard, GILPool, prepare_freethreaded_python, prepare_pyo3_library};
|
||||
pub use instance::{PyToken, PyObjectWithToken, AsPyRef, Py, PyNativeType};
|
||||
pub use conversion::{FromPyObject, RefFromPyObject,
|
||||
pub use conversion::{FromPyObject, RefFromPyObject, PyTryFrom, PyTryInto,
|
||||
ToPyObject, ToBorrowedObject, IntoPyObject, IntoPyTuple};
|
||||
pub mod class;
|
||||
pub use class::*;
|
||||
|
|
|
@ -4,10 +4,10 @@ use std;
|
|||
|
||||
use ffi;
|
||||
use pythonrun;
|
||||
use err::{PyErr, PyResult};
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use instance::{AsPyRef, PyObjectWithToken};
|
||||
use objects::{PyObjectRef, PyDict};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyObject, IntoPyTuple, FromPyObject};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyObject, IntoPyTuple, FromPyObject, PyTryFrom};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
|
||||
|
||||
|
@ -151,10 +151,10 @@ impl PyObject {
|
|||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
#[inline]
|
||||
pub fn cast_as<D>(&self, py: Python) -> Option<&D>
|
||||
where D: ::PyDowncastFrom
|
||||
pub fn cast_as<D>(&self, py: Python) -> Result<&D, <D as PyTryFrom>::Error>
|
||||
where D: PyTryFrom<Error=PyDowncastError>
|
||||
{
|
||||
<D as ::PyDowncastFrom>::try_downcast_from(self.as_ref(py))
|
||||
D::try_from(self.as_ref(py))
|
||||
}
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
|
@ -283,14 +283,6 @@ impl IntoPyObject for PyObject
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoPyObject for &'a PyObject
|
||||
{
|
||||
#[inline]
|
||||
fn into_object(self, py: Python) -> PyObject {
|
||||
unsafe {PyObject::from_borrowed_ptr(py, self.as_ptr())}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromPyObject<'a> for PyObject
|
||||
{
|
||||
#[inline]
|
||||
|
|
|
@ -5,11 +5,11 @@ use std::cmp::Ordering;
|
|||
use std::os::raw::c_int;
|
||||
|
||||
use ffi;
|
||||
use err::{self, PyErr, PyResult};
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom};
|
||||
use err::{self, PyErr, PyResult, PyDowncastError};
|
||||
use python::{Python, ToPyPointer};
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyDict, PyString, PyIterator, PyType};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyTuple, FromPyObject};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyTuple, FromPyObject, PyTryFrom};
|
||||
use instance::PyObjectWithToken;
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
|
@ -124,12 +124,11 @@ pub trait ObjectProtocol {
|
|||
|
||||
/// Gets the Python super object for this object.
|
||||
/// This is equivalent to the Python expression: 'super()'
|
||||
fn get_super(&self) -> &<Self as PyTypeInfo>::BaseType
|
||||
where Self: PyTypeInfo, <Self as PyTypeInfo>::BaseType: PyDowncastFrom;
|
||||
fn get_super(&self) -> &<Self as PyTypeInfo>::BaseType where Self: PyTypeInfo;
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
fn cast_as<'a, D>(&'a self) -> Option<&'a D>
|
||||
where D: PyDowncastFrom,
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, <D as PyTryFrom>::Error>
|
||||
where D: PyTryFrom<Error=PyDowncastError>,
|
||||
&'a PyObjectRef: std::convert::From<&'a Self>;
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
|
@ -357,18 +356,17 @@ impl<T> ObjectProtocol for T where T: PyObjectWithToken + ToPyPointer {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_super(&self) -> &<Self as PyTypeInfo>::BaseType
|
||||
where Self: PyTypeInfo, <Self as PyTypeInfo>::BaseType: PyDowncastFrom
|
||||
fn get_super(&self) -> &<Self as PyTypeInfo>::BaseType where Self: PyTypeInfo
|
||||
{
|
||||
unsafe { self.py().cast_from_borrowed_ptr(self.as_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cast_as<'a, D>(&'a self) -> Option<&'a D>
|
||||
where D: PyDowncastFrom,
|
||||
&'a PyObjectRef: std::convert::From<&'a Self>
|
||||
fn cast_as<'a, D>(&'a self) -> Result<&'a D, <D as PyTryFrom>::Error>
|
||||
where D: PyTryFrom<Error=PyDowncastError>,
|
||||
&'a PyObjectRef: std::convert::From<&'a Self>
|
||||
{
|
||||
<D as PyDowncastFrom>::try_downcast_from(self.into())
|
||||
D::try_from(self.into())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -393,8 +391,8 @@ impl<T> ObjectProtocol for T where T: PyObjectWithToken + ToPyPointer {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use python::Python;
|
||||
use conversion::{ToPyObject, PyTryFrom};
|
||||
use objects::PyString;
|
||||
|
||||
#[test]
|
||||
|
@ -402,7 +400,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "Hello\n".to_object(py);
|
||||
let s = PyString::downcast_from(v.as_ref(py)).unwrap();
|
||||
let s = PyString::try_from(v.as_ref(py)).unwrap();
|
||||
assert_eq!(format!("{:?}", s), "'Hello\\n'");
|
||||
}
|
||||
|
||||
|
@ -411,7 +409,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "Hello\n".to_object(py);
|
||||
let s = PyString::downcast_from(v.as_ref(py)).unwrap();
|
||||
let s = PyString::try_from(v.as_ref(py)).unwrap();
|
||||
assert_eq!(format!("{}", s), "Hello\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
use ffi;
|
||||
use object::PyObject;
|
||||
use python::{ToPyPointer, Python, PyDowncastFrom};
|
||||
use conversion::{ToPyObject, IntoPyObject, ToBorrowedObject};
|
||||
use python::{Python, ToPyPointer};
|
||||
use conversion::{ToPyObject, IntoPyObject, ToBorrowedObject, PyTryFrom};
|
||||
|
||||
/// Represents a Python `bool`.
|
||||
pub struct PyBool(PyObject);
|
||||
|
@ -59,7 +59,7 @@ impl IntoPyObject for bool {
|
|||
///
|
||||
/// Fails with `TypeError` if the input is not a Python `bool`.
|
||||
pyobject_extract!(py, obj to bool => {
|
||||
Ok(PyBool::downcast_from(obj)?.is_true())
|
||||
Ok(PyBool::try_from(obj)?.is_true())
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -222,9 +222,9 @@ mod test {
|
|||
use std::collections::{BTreeMap, HashMap};
|
||||
use python::Python;
|
||||
use instance::AsPyRef;
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use conversion::{PyTryFrom, ToPyObject, IntoPyObject};
|
||||
use objects::{PyDict, PyTuple};
|
||||
use {PyDowncastFrom, ObjectProtocol};
|
||||
use ObjectProtocol;
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
|
@ -254,11 +254,11 @@ mod test {
|
|||
let py = gil.python();
|
||||
let mut v = HashMap::new();
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(0, dict.len());
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict2 = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict2 = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(1, dict2.len());
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(true, dict.contains(7i32).unwrap());
|
||||
assert_eq!(false, dict.contains(8i32).unwrap());
|
||||
}
|
||||
|
@ -281,7 +281,7 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(32, dict.get_item(7i32).unwrap().extract::<i32>().unwrap());
|
||||
assert_eq!(None, dict.get_item(8i32));
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.set_item(7i32, 42i32).is_ok()); // change
|
||||
assert!(dict.set_item(8i32, 123i32).is_ok()); // insert
|
||||
assert_eq!(42i32, dict.get_item(7i32).unwrap().extract::<i32>().unwrap());
|
||||
|
@ -325,7 +325,7 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.set_item(7i32, 42i32).is_ok()); // change
|
||||
assert!(dict.set_item(8i32, 123i32).is_ok()); // insert
|
||||
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
|
||||
|
@ -339,7 +339,7 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.del_item(7i32).is_ok());
|
||||
assert_eq!(0, dict.len());
|
||||
assert_eq!(None, dict.get_item(7i32));
|
||||
|
@ -352,7 +352,7 @@ mod test {
|
|||
let mut v = HashMap::new();
|
||||
v.insert(7, 32);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
assert!(dict.del_item(7i32).is_ok()); // change
|
||||
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ mod test {
|
|||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
|
@ -388,7 +388,7 @@ mod test {
|
|||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
for el in dict.keys().iter() {
|
||||
|
@ -406,7 +406,7 @@ mod test {
|
|||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut values_sum = 0;
|
||||
for el in dict.values().iter() {
|
||||
|
@ -424,7 +424,7 @@ mod test {
|
|||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
// Can't just compare against a vector of tuples since we don't have a guaranteed ordering.
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
|
@ -445,7 +445,7 @@ mod test {
|
|||
v.insert(8, 42);
|
||||
v.insert(9, 123);
|
||||
let ob = v.to_object(py);
|
||||
let dict = PyDict::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let dict = PyDict::try_from(ob.as_ref(py)).unwrap();
|
||||
let mut key_sum = 0;
|
||||
let mut value_sum = 0;
|
||||
for (key, value) in dict.iter() {
|
||||
|
@ -465,7 +465,7 @@ mod test {
|
|||
map.insert(1, 1);
|
||||
|
||||
let m = map.to_object(py);
|
||||
let py_map = PyDict::downcast_from(m.as_ref(py)).unwrap();
|
||||
let py_map = PyDict::try_from(m.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
|
@ -480,7 +480,7 @@ mod test {
|
|||
map.insert(1, 1);
|
||||
|
||||
let m = map.to_object(py);
|
||||
let py_map = PyDict::downcast_from(m.as_ref(py)).unwrap();
|
||||
let py_map = PyDict::try_from(m.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
|
@ -495,7 +495,7 @@ mod test {
|
|||
map.insert(1, 1);
|
||||
|
||||
let m = map.into_object(py);
|
||||
let py_map = PyDict::downcast_from(m.as_ref(py)).unwrap();
|
||||
let py_map = PyDict::try_from(m.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
|
@ -510,7 +510,7 @@ mod test {
|
|||
map.insert(1, 1);
|
||||
|
||||
let m = map.into_object(py);
|
||||
let py_map = PyDict::downcast_from(m.as_ref(py)).unwrap();
|
||||
let py_map = PyDict::try_from(m.as_ref(py)).unwrap();
|
||||
|
||||
assert!(py_map.len() == 1);
|
||||
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
|
||||
|
|
|
@ -61,8 +61,8 @@ impl <'p> Iterator for PyIterator<'p> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use python::Python;
|
||||
use conversion::{PyTryFrom, ToPyObject};
|
||||
use objects::PyObjectRef;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
|
@ -71,7 +71,7 @@ mod tests {
|
|||
let gil_guard = Python::acquire_gil();
|
||||
let py = gil_guard.python();
|
||||
let obj = vec![10, 20].to_object(py);
|
||||
let inst = PyObjectRef::downcast_from(obj.as_ref(py)).unwrap();
|
||||
let inst = PyObjectRef::try_from(obj.as_ref(py)).unwrap();
|
||||
let mut it = inst.iter().unwrap();
|
||||
assert_eq!(10, it.next().unwrap().unwrap().extract().unwrap());
|
||||
assert_eq!(20, it.next().unwrap().unwrap().extract().unwrap());
|
||||
|
|
|
@ -165,8 +165,8 @@ impl <T> IntoPyObject for Vec<T> where T: IntoPyObject + ToPyObject {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use python::Python;
|
||||
use conversion::{ToPyObject, PyTryFrom};
|
||||
use objects::PyList;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
|
@ -188,7 +188,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![1,2,3,4];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(4, list.len());
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
|
||||
assert_eq!(5, list.get_item(2).extract::<i32>().unwrap());
|
||||
|
@ -211,7 +211,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(2, list.get_parked_item(0).extract::<i32>(py).unwrap());
|
||||
assert_eq!(3, list.get_parked_item(1).extract::<i32>(py).unwrap());
|
||||
assert_eq!(5, list.get_parked_item(2).extract::<i32>(py).unwrap());
|
||||
|
@ -224,7 +224,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
let val = 42i32.to_object(py);
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
list.set_item(0, val).unwrap();
|
||||
|
@ -239,7 +239,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
let none = py.None();
|
||||
cnt = none.get_refcnt();
|
||||
list.set_item(0, none).unwrap();
|
||||
|
@ -257,7 +257,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
let val = 42i32.to_object(py);
|
||||
assert_eq!(4, list.len());
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
|
@ -291,7 +291,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
list.append(3).unwrap();
|
||||
assert_eq!(2, list.get_item(0).extract::<i32>().unwrap());
|
||||
assert_eq!(3, list.get_item(1).extract::<i32>().unwrap());
|
||||
|
@ -321,7 +321,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
let mut idx = 0;
|
||||
for el in list.iter() {
|
||||
assert_eq!(v[idx], el.extract::<i32>().unwrap());
|
||||
|
@ -336,7 +336,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = vec![2, 3, 5, 7];
|
||||
let ob = v.to_object(py);
|
||||
let list = PyList::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let list = PyList::try_from(ob.as_ref(py)).unwrap();
|
||||
let v2 = list.as_ref().extract::<Vec<i32>>().unwrap();
|
||||
assert_eq!(v, v2);
|
||||
}
|
||||
|
|
|
@ -34,31 +34,6 @@ pub use self::num2::{PyInt, PyLong};
|
|||
|
||||
macro_rules! pyobject_downcast(
|
||||
($name: ident, $checkfunction: ident) => (
|
||||
impl $crate::python::PyDowncastFrom for $name
|
||||
{
|
||||
fn try_downcast_from(ob: &$crate::PyObjectRef) -> Option<&$name>
|
||||
{
|
||||
use $crate::ToPyPointer;
|
||||
unsafe {
|
||||
if $crate::ffi::$checkfunction(ob.as_ptr()) > 0 {
|
||||
Some($crate::std::mem::transmute(ob))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unchecked_downcast_from(ob: &$crate::PyObjectRef) -> &Self
|
||||
{
|
||||
$crate::std::mem::transmute(ob)
|
||||
}
|
||||
unsafe fn unchecked_mut_downcast_from(ob: &$crate::PyObjectRef) -> &mut Self
|
||||
{
|
||||
#[allow(mutable_transmutes)]
|
||||
$crate::std::mem::transmute(ob)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::FromPyObject<'a> for &'a $name
|
||||
{
|
||||
/// Extracts `Self` from the source `PyObject`.
|
||||
|
@ -108,24 +83,6 @@ macro_rules! pyobject_nativetype(
|
|||
self.0.as_ptr()
|
||||
}
|
||||
}
|
||||
impl $crate::python::IntoPyPointer for $name {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn into_ptr(self) -> *mut $crate::ffi::PyObject {
|
||||
let ptr = self.0.as_ptr();
|
||||
unsafe { $crate::ffi::Py_INCREF(ptr); }
|
||||
ptr
|
||||
}
|
||||
}
|
||||
impl<'a> $crate::python::IntoPyPointer for &'a $name {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn into_ptr(self) -> *mut $crate::ffi::PyObject {
|
||||
let ptr = self.0.as_ptr();
|
||||
unsafe { $crate::ffi::Py_INCREF(ptr); }
|
||||
ptr
|
||||
}
|
||||
}
|
||||
impl PartialEq for $name {
|
||||
#[inline]
|
||||
fn eq(&self, o: &$name) -> bool {
|
||||
|
@ -149,7 +106,7 @@ macro_rules! pyobject_nativetype(
|
|||
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
||||
&mut $crate::ffi::$typeobject
|
||||
}
|
||||
#[inline]
|
||||
|
||||
fn is_instance(ptr: *mut $crate::ffi::PyObject) -> bool {
|
||||
#[allow(unused_unsafe)]
|
||||
unsafe { $crate::ffi::$checkfunction(ptr) > 0 }
|
||||
|
@ -184,14 +141,6 @@ macro_rules! pyobject_nativetype(
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::IntoPyObject for &'a $name
|
||||
{
|
||||
#[inline]
|
||||
fn into_object(self, py: $crate::Python) -> $crate::PyObject {
|
||||
unsafe { $crate::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::std::fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
|
||||
-> Result<(), $crate::std::fmt::Error>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
|
||||
use buffer;
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use err::{self, PyErr, PyResult};
|
||||
use err::{self, PyErr, PyResult, PyDowncastError};
|
||||
use object::PyObject;
|
||||
use instance::PyObjectWithToken;
|
||||
use python::{ToPyPointer, PyDowncastFrom};
|
||||
use conversion::{FromPyObject, ToBorrowedObject};
|
||||
use python::ToPyPointer;
|
||||
use conversion::{FromPyObject, ToBorrowedObject, PyTryFrom};
|
||||
use objects::{PyObjectRef, PyList, PyTuple};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
|
@ -34,8 +36,9 @@ impl PySequence {
|
|||
#[inline]
|
||||
pub fn concat(&self, other: &PySequence) -> PyResult<&PySequence> {
|
||||
unsafe {
|
||||
self.py().cast_from_ptr_or_err::<PySequence>(
|
||||
ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))
|
||||
let ptr = self.py().cast_from_ptr_or_err::<PyObjectRef>(
|
||||
ffi::PySequence_Concat(self.as_ptr(), other.as_ptr()))?;
|
||||
Ok(std::mem::transmute(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,8 +48,9 @@ impl PySequence {
|
|||
#[inline]
|
||||
pub fn repeat(&self, count: isize) -> PyResult<&PySequence> {
|
||||
unsafe {
|
||||
self.py().cast_from_ptr_or_err::<PySequence>(
|
||||
ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t))
|
||||
let ptr = self.py().cast_from_ptr_or_err::<PyObjectRef>(
|
||||
ffi::PySequence_Repeat(self.as_ptr(), count as Py_ssize_t))?;
|
||||
Ok(std::mem::transmute(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,7 +236,7 @@ impl <'source, T> FromPyObject<'source> for Vec<T>
|
|||
|
||||
fn extract_sequence<'s, T>(obj: &'s PyObjectRef) -> PyResult<Vec<T>> where T: FromPyObject<'s>
|
||||
{
|
||||
let seq = PySequence::downcast_from(obj)?;
|
||||
let seq = PySequence::try_from(obj)?;
|
||||
let mut v = Vec::new();
|
||||
for item in try!(seq.iter()) {
|
||||
let item = try!(item);
|
||||
|
@ -241,12 +245,48 @@ fn extract_sequence<'s, T>(obj: &'s PyObjectRef) -> PyResult<Vec<T>> where T: Fr
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
impl PyTryFrom for PySequence
|
||||
{
|
||||
type Error = PyDowncastError;
|
||||
|
||||
fn try_from(value: &PyObjectRef) -> Result<&PySequence, Self::Error> {
|
||||
unsafe {
|
||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||
let ptr = value as *const _ as *mut u8 as *mut PySequence;
|
||||
Ok(&*ptr)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_exact(value: &PyObjectRef) -> Result<&PySequence, Self::Error> {
|
||||
PySequence::try_from(value)
|
||||
}
|
||||
|
||||
fn try_from_mut(value: &PyObjectRef) -> Result<&mut PySequence, Self::Error> {
|
||||
unsafe {
|
||||
if ffi::PySequence_Check(value.as_ptr()) != 0 {
|
||||
let ptr = value as *const _ as *mut u8 as *mut PySequence;
|
||||
Ok(&mut *ptr)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut PySequence, Self::Error> {
|
||||
PySequence::try_from_mut(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use objects::{PySequence};
|
||||
use python::Python;
|
||||
use conversion::{PyTryFrom, ToPyObject};
|
||||
use objects::PySequence;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
#[test]
|
||||
|
@ -254,7 +294,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = 42i32;
|
||||
assert!(PySequence::downcast_from(v.to_object(py).as_ref(py)).is_err());
|
||||
assert!(PySequence::try_from(v.to_object(py).as_ref(py)).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -262,7 +302,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let v = "London Calling";
|
||||
assert!(PySequence::downcast_from(v.to_object(py).as_ref(py)).is_ok());
|
||||
assert!(PySequence::try_from(v.to_object(py).as_ref(py)).is_ok());
|
||||
}
|
||||
#[test]
|
||||
fn test_seq_empty() {
|
||||
|
@ -499,7 +539,7 @@ mod test {
|
|||
let py = gil.python();
|
||||
let v = "foo";
|
||||
let ob = v.to_object(py);
|
||||
let seq = PySequence::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let seq = PySequence::try_from(ob.as_ref(py)).unwrap();
|
||||
assert!(seq.list().is_ok());
|
||||
}
|
||||
|
||||
|
|
|
@ -144,8 +144,8 @@ impl PyFrozenSet {
|
|||
mod test {
|
||||
use std::collections::{HashSet};
|
||||
use super::{PySet, PyFrozenSet};
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use python::Python;
|
||||
use conversion::{ToPyObject, PyTryFrom};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use instance::AsPyRef;
|
||||
|
||||
|
@ -165,11 +165,11 @@ mod test {
|
|||
|
||||
let mut v = HashSet::new();
|
||||
let ob = v.to_object(py);
|
||||
let set = PySet::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let set = PySet::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(0, set.len());
|
||||
v.insert(7);
|
||||
let ob = v.to_object(py);
|
||||
let set2 = PySet::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let set2 = PySet::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(1, set2.len());
|
||||
}
|
||||
|
||||
|
|
|
@ -66,9 +66,9 @@ impl PyString {
|
|||
/// even if the bytes are not valid UTF-8.
|
||||
/// For unicode strings, returns the underlying representation used by Python.
|
||||
pub fn data(&self) -> PyStringData {
|
||||
if let Some(bytes) = self.cast_as::<PyBytes>() {
|
||||
if let Ok(bytes) = self.cast_as::<PyBytes>() {
|
||||
PyStringData::Utf8(bytes.data())
|
||||
} else if let Some(unicode) = self.cast_as::<PyUnicode>() {
|
||||
} else if let Ok(unicode) = self.cast_as::<PyUnicode>() {
|
||||
unicode.data()
|
||||
} else {
|
||||
panic!("PyString is neither `str` nor `unicode`")
|
||||
|
@ -175,7 +175,7 @@ impl PyUnicode {
|
|||
impl std::convert::From<Py<PyBytes>> for Py<PyString> {
|
||||
#[inline]
|
||||
fn from(ob: Py<PyBytes>) -> Py<PyString> {
|
||||
<Py<PyString> as ::PyDowncastInto>::unchecked_downcast_into(ob)
|
||||
unsafe{std::mem::transmute(ob)}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ impl std::convert::From<Py<PyBytes>> for Py<PyString> {
|
|||
impl std::convert::From<Py<PyUnicode>> for Py<PyString> {
|
||||
#[inline]
|
||||
fn from(ob: Py<PyUnicode>) -> Py<PyString> {
|
||||
<Py<PyString> as ::PyDowncastInto>::unchecked_downcast_into(ob)
|
||||
unsafe{std::mem::transmute(ob)}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use err::PyResult;
|
||||
use python::Python;
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyString};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::{ToPyObject, IntoPyObject, RefFromPyObject};
|
||||
use conversion::{ToPyObject, IntoPyObject, RefFromPyObject, PyTryFrom};
|
||||
|
||||
/// Converts Rust `str` to Python object.
|
||||
/// See `PyString::new` for details on the conversion.
|
||||
|
@ -59,14 +59,14 @@ impl<'source> ::FromPyObject<'source> for Cow<'source, str>
|
|||
{
|
||||
fn extract(ob: &'source PyObjectRef) -> PyResult<Self>
|
||||
{
|
||||
PyString::downcast_from(ob)?.to_string()
|
||||
PyString::try_from(ob)?.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// Allows extracting strings from Python objects.
|
||||
/// Accepts Python `str` and `unicode` objects.
|
||||
pyobject_extract!(py, obj to String => {
|
||||
PyString::downcast_from(obj)?.to_string().map(Cow::into_owned)
|
||||
PyString::try_from(obj)?.to_string().map(Cow::into_owned)
|
||||
});
|
||||
|
||||
impl RefFromPyObject for str {
|
||||
|
|
|
@ -7,8 +7,8 @@ use err::{PyErr, PyResult};
|
|||
use instance::{Py, PyObjectWithToken};
|
||||
use object::PyObject;
|
||||
use objects::PyObjectRef;
|
||||
use python::{Python, ToPyPointer, IntoPyPointer, PyDowncastFrom};
|
||||
use conversion::{FromPyObject, ToPyObject, IntoPyTuple, IntoPyObject};
|
||||
use python::{Python, ToPyPointer, IntoPyPointer};
|
||||
use conversion::{FromPyObject, ToPyObject, IntoPyTuple, IntoPyObject, PyTryFrom};
|
||||
use super::exc;
|
||||
|
||||
/// Represents a Python `tuple` object.
|
||||
|
@ -161,7 +161,7 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
|
|||
impl<'s, $($T: FromPyObject<'s>),+> FromPyObject<'s> for ($($T,)+) {
|
||||
fn extract(obj: &'s PyObjectRef) -> PyResult<Self>
|
||||
{
|
||||
let t = PyTuple::downcast_from(obj)?;
|
||||
let t = PyTuple::try_from(obj)?;
|
||||
let slice = t.as_slice();
|
||||
if t.len() == $length {
|
||||
Ok((
|
||||
|
@ -238,7 +238,7 @@ impl IntoPyTuple for () {
|
|||
/// Returns `Ok(NoArgs)` if the input is an empty Python tuple.
|
||||
/// Otherwise, returns an error.
|
||||
pyobject_extract!(py, obj to NoArgs => {
|
||||
let t = PyTuple::downcast_from(obj)?;
|
||||
let t = PyTuple::try_from(obj)?;
|
||||
if t.len() == 0 {
|
||||
Ok(NoArgs)
|
||||
} else {
|
||||
|
@ -251,8 +251,8 @@ pyobject_extract!(py, obj to NoArgs => {
|
|||
mod test {
|
||||
use PyTuple;
|
||||
use instance::AsPyRef;
|
||||
use python::{Python, PyDowncastFrom};
|
||||
use conversion::ToPyObject;
|
||||
use python::Python;
|
||||
use conversion::{ToPyObject, PyTryFrom};
|
||||
use objects::PyObjectRef;
|
||||
use objectprotocol::ObjectProtocol;
|
||||
|
||||
|
@ -272,7 +272,7 @@ mod test {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let ob = (1, 2, 3).to_object(py);
|
||||
let tuple = PyTuple::downcast_from(ob.as_ref(py)).unwrap();
|
||||
let tuple = PyTuple::try_from(ob.as_ref(py)).unwrap();
|
||||
assert_eq!(3, tuple.len());
|
||||
let ob: &PyObjectRef = tuple.into();
|
||||
assert_eq!((1, 2, 3), ob.extract().unwrap());
|
||||
|
|
161
src/python.rs
161
src/python.rs
|
@ -13,6 +13,7 @@ use instance::{Py, PyToken, AsPyRef};
|
|||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyType, PyDict, PyModule};
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use conversion::PyTryFrom;
|
||||
use pythonrun::{self, GILGuard};
|
||||
|
||||
|
||||
|
@ -29,93 +30,10 @@ use pythonrun::{self, GILGuard};
|
|||
#[derive(Copy, Clone)]
|
||||
pub struct Python<'p>(PhantomData<&'p GILGuard>);
|
||||
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
pub trait PyDowncastFrom : Sized {
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_downcast_from(&PyObjectRef) -> Option<&Self>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_exact_downcast_from(ob: &PyObjectRef) -> Option<&Self> {
|
||||
Self::try_downcast_from(ob)
|
||||
}
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn downcast_from(ob: &PyObjectRef) -> Result<&Self, PyDowncastError> {
|
||||
if let Some(ob) = Self::try_downcast_from(ob) {
|
||||
Ok(ob)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn exact_downcast_from(ob: &PyObjectRef) -> Result<&Self, PyDowncastError> {
|
||||
if let Some(ob) = Self::try_exact_downcast_from(ob) {
|
||||
Ok(ob)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
unsafe fn unchecked_downcast_from(&PyObjectRef) -> &Self;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
unsafe fn unchecked_mut_downcast_from(&PyObjectRef) -> &mut Self;
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
pub trait PyMutDowncastFrom : Sized {
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_mut_downcast_from(&mut PyObjectRef) -> Option<&mut Self>;
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn try_mut_exact_downcast_from(ob: &mut PyObjectRef) -> Option<&mut Self> {
|
||||
Self::try_mut_downcast_from(ob)
|
||||
}
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn mut_downcast_from(ob: &mut PyObjectRef) -> Result<&mut Self, PyDowncastError> {
|
||||
if let Some(o) = Self::try_mut_downcast_from(ob) {
|
||||
return Ok(o)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from PyObject to a concrete Python object type.
|
||||
fn mut_exact_downcast_from(ob: &mut PyObjectRef) -> Result<&mut Self, PyDowncastError> {
|
||||
if let Some(ob) = Self::try_mut_exact_downcast_from(ob) {
|
||||
Ok(ob)
|
||||
} else {
|
||||
Err(PyDowncastError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait implemented by Python object types that allow a checked downcast.
|
||||
pub trait PyDowncastInto : Sized {
|
||||
|
||||
/// Cast Self to a concrete Python object type.
|
||||
fn downcast_into<I>(Python, I) -> Result<Self, PyDowncastError>
|
||||
where I: ToPyPointer + IntoPyPointer;
|
||||
|
||||
/// Cast from ffi::PyObject to a concrete Python object type.
|
||||
fn downcast_into_from_ptr(py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Result<Self, PyDowncastError>;
|
||||
|
||||
/// Cast from ffi::PyObject to a concrete Python object type.
|
||||
fn unchecked_downcast_into<I>(I) -> Self where I: IntoPyPointer;
|
||||
}
|
||||
|
||||
/// This trait allows retrieving the underlying FFI pointer from Python objects.
|
||||
pub trait ToPyPointer {
|
||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject;
|
||||
|
||||
}
|
||||
|
||||
/// This trait allows retrieving the underlying FFI pointer from Python objects.
|
||||
|
@ -147,6 +65,15 @@ impl <T> IntoPyPointer for Option<T> where T: IntoPyPointer {
|
|||
}
|
||||
}
|
||||
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
impl<'a, T> IntoPyPointer for &'a T where T: ToPyPointer {
|
||||
#[inline]
|
||||
default fn into_ptr(self) -> *mut ffi::PyObject {
|
||||
let ptr = self.as_ptr();
|
||||
unsafe { ffi::Py_INCREF(ptr); }
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> Python<'p> {
|
||||
/// Retrieve Python instance under the assumption that the GIL is already acquired at this point,
|
||||
|
@ -217,7 +144,7 @@ impl<'p> Python<'p> {
|
|||
}
|
||||
|
||||
let globals = globals.map(|g| g.as_ptr())
|
||||
.unwrap_or_else(|| ffi::PyModule_GetDict(mptr));
|
||||
.unwrap_or_else(|| ffi::PyModule_GetDict(mptr));
|
||||
let locals = locals.map(|l| l.as_ptr()).unwrap_or(globals);
|
||||
|
||||
let res_ptr = ffi::PyRun_StringFlags(code.as_ptr(),
|
||||
|
@ -280,9 +207,9 @@ impl<'p> Python<'p> {
|
|||
/// Create new instance of `T` and move it under python management.
|
||||
/// Created object get registered in release pool. Returns references to `T`
|
||||
#[inline]
|
||||
pub fn init_ref<T, F>(self, f: F) -> PyResult<&'p T>
|
||||
pub fn init_ref<T, F>(self, f: F) -> PyResult<&'p T>
|
||||
where F: FnOnce(PyToken) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<T> + PyDowncastFrom
|
||||
T: PyTypeInfo + PyObjectAlloc<T>
|
||||
{
|
||||
Py::new_ref(self, f)
|
||||
}
|
||||
|
@ -292,7 +219,7 @@ impl<'p> Python<'p> {
|
|||
#[inline]
|
||||
pub fn init_mut<T, F>(self, f: F) -> PyResult<&'p mut T>
|
||||
where F: FnOnce(PyToken) -> T,
|
||||
T: PyTypeInfo + PyObjectAlloc<T> + PyDowncastFrom
|
||||
T: PyTypeInfo + PyObjectAlloc<T>
|
||||
{
|
||||
Py::new_mut(self, f)
|
||||
}
|
||||
|
@ -300,22 +227,42 @@ impl<'p> Python<'p> {
|
|||
|
||||
impl<'p> Python<'p> {
|
||||
|
||||
unsafe fn unchecked_downcast<T: PyTypeInfo>(self, ob: &PyObjectRef) -> &'p T
|
||||
{
|
||||
if T::OFFSET == 0 {
|
||||
&*(ob as *const _ as *const T)
|
||||
} else {
|
||||
let ptr = (ob.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
&*ptr
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn unchecked_mut_downcast<T: PyTypeInfo>(self, ob: &PyObjectRef) -> &'p mut T
|
||||
{
|
||||
if T::OFFSET == 0 {
|
||||
&mut *(ob as *const _ as *mut T)
|
||||
} else {
|
||||
let ptr = (ob.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
||||
/// 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: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
unsafe {
|
||||
let p = pythonrun::register_owned(self, obj.into_ptr());
|
||||
<T as PyDowncastFrom>::downcast_from(p)
|
||||
T::try_from(p)
|
||||
}
|
||||
}
|
||||
|
||||
/// 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: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
let p = pythonrun::register_owned(self, obj.into_ptr());
|
||||
<T as PyDowncastFrom>::unchecked_downcast_from(p)
|
||||
self.unchecked_downcast(p)
|
||||
}
|
||||
|
||||
/// Register `ffi::PyObject` pointer in release pool
|
||||
|
@ -331,26 +278,26 @@ impl<'p> Python<'p> {
|
|||
/// Register `ffi::PyObject` pointer in release pool,
|
||||
/// and do unchecked downcast to specific type.
|
||||
pub unsafe fn cast_from_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
let p = pythonrun::register_owned(self, ptr);
|
||||
<T as PyDowncastFrom>::unchecked_downcast_from(p)
|
||||
self.unchecked_downcast(p)
|
||||
}
|
||||
}
|
||||
|
||||
/// Register `ffi::PyObject` pointer in release pool,
|
||||
/// Do unchecked downcast to specific type. Returns mutable reference.
|
||||
pub unsafe fn mut_cast_from_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p mut T
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
let p = pythonrun::register_owned(self, ptr);
|
||||
<T as PyDowncastFrom>::unchecked_mut_downcast_from(p)
|
||||
self.unchecked_mut_downcast(p)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,13 +305,13 @@ impl<'p> Python<'p> {
|
|||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
pub unsafe fn cast_from_ptr_or_err<T>(self, ptr: *mut ffi::PyObject) -> PyResult<&'p T>
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(self))
|
||||
} else {
|
||||
let p = pythonrun::register_owned(self, ptr);
|
||||
Ok(<T as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
Ok(self.unchecked_downcast(p))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,13 +319,13 @@ impl<'p> Python<'p> {
|
|||
/// Returns `None` if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
pub unsafe fn cast_from_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject) -> Option<&'p T>
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
let p = pythonrun::register_owned(self, ptr);
|
||||
Some(<T as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
Some(self.unchecked_downcast(p))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,10 +333,10 @@ impl<'p> Python<'p> {
|
|||
/// Panics if the pointer is `null`.
|
||||
/// do unchecked downcast to specific type.
|
||||
pub unsafe fn cast_from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p T
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
let p = pythonrun::register_borrowed(self, ptr);
|
||||
<T as PyDowncastFrom>::unchecked_downcast_from(p)
|
||||
self.unchecked_downcast(p)
|
||||
}
|
||||
|
||||
/// Register borrowed `ffi::PyObject` pointer in release pool.
|
||||
|
@ -397,13 +344,13 @@ impl<'p> Python<'p> {
|
|||
/// do unchecked downcast to specific type.
|
||||
pub unsafe fn cast_from_borrowed_ptr_or_err<T>(self, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<&'p T>
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(self))
|
||||
} else {
|
||||
let p = pythonrun::register_borrowed(self, ptr);
|
||||
Ok(<T as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
Ok(self.unchecked_downcast(p))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,13 +359,13 @@ impl<'p> Python<'p> {
|
|||
/// do unchecked downcast to specific `T`.
|
||||
pub unsafe fn cast_from_borrowed_ptr_or_opt<T>(self, ptr: *mut ffi::PyObject)
|
||||
-> Option<&'p T>
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
let p = pythonrun::register_borrowed(self, ptr);
|
||||
Some(<T as PyDowncastFrom>::unchecked_downcast_from(p))
|
||||
Some(self.unchecked_downcast(p))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,10 +373,10 @@ impl<'p> Python<'p> {
|
|||
/// Panics if the pointer is `null`.
|
||||
/// do unchecked downcast to specific `T`, returns mutable reference.
|
||||
pub unsafe fn mut_cast_from_borrowed_ptr<T>(self, ptr: *mut ffi::PyObject) -> &'p mut T
|
||||
where T: PyDowncastFrom
|
||||
where T: PyTypeInfo
|
||||
{
|
||||
let p = pythonrun::register_borrowed(self, ptr);
|
||||
<T as PyDowncastFrom>::unchecked_mut_downcast_from(p)
|
||||
self.unchecked_mut_downcast(p)
|
||||
}
|
||||
|
||||
/// Release PyObject reference.
|
||||
|
|
|
@ -41,11 +41,21 @@ pub trait PyTypeInfo {
|
|||
/// PyTypeObject instance for this type
|
||||
unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
|
||||
|
||||
/// Check `*mut ffi::PyObject` if it is the same type
|
||||
fn is_instance(ptr: *mut ffi::PyObject) -> bool;
|
||||
/// Check if `*mut ffi::PyObject` is instance of this type
|
||||
fn is_instance(ptr: *mut ffi::PyObject) -> bool {
|
||||
unsafe {ffi::PyObject_TypeCheck(ptr, Self::type_object()) != 0}
|
||||
}
|
||||
|
||||
/// Check if `*mut ffi::PyObject` is exact instance of this type
|
||||
fn is_exact_instance(ptr: *mut ffi::PyObject) -> bool {
|
||||
unsafe {
|
||||
(*ptr).ob_type == Self::type_object()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// type object supports python GC
|
||||
pub const PY_TYPE_FLAG_GC: usize = 1<<0;
|
||||
|
||||
|
@ -78,6 +88,11 @@ impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
|||
<T as PyTypeInfo>::is_instance(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn is_exact_instance(ptr: *mut ffi::PyObject) -> bool {
|
||||
<T as PyTypeInfo>::is_exact_instance(ptr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// A Python object allocator that is usable as a base type for #[class]
|
||||
|
@ -100,6 +115,7 @@ impl<T> PyObjectAlloc<T> for T where T : PyTypeInfo {
|
|||
T::init_type();
|
||||
|
||||
let obj = ffi::PyType_GenericAlloc(T::type_object(), 0);
|
||||
println!("ALLOC {:?} {:?}", obj, ffi::Py_REFCNT(obj));
|
||||
|
||||
let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
std::ptr::write(ptr, value);
|
||||
|
|
|
@ -110,7 +110,7 @@ fn empty_class_with_new() {
|
|||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let typeobj = py.get_type::<EmptyClassWithNew>();
|
||||
assert!(typeobj.call(NoArgs, None).unwrap().cast_as::<EmptyClassWithNew>().is_some());
|
||||
assert!(typeobj.call(NoArgs, None).unwrap().cast_as::<EmptyClassWithNew>().is_ok());
|
||||
}
|
||||
|
||||
#[py::class]
|
||||
|
|
|
@ -29,7 +29,7 @@ struct Test {
|
|||
impl<'p> PyMappingProtocol<'p> for Test
|
||||
{
|
||||
fn __getitem__(&self, idx: &PyObjectRef) -> PyResult<PyObject> {
|
||||
if let Some(slice) = idx.cast_as::<PySlice>() {
|
||||
if let Ok(slice) = idx.cast_as::<PySlice>() {
|
||||
let indices = slice.indices(1000)?;
|
||||
if indices.start == 100 && indices.stop == 200 && indices.step == 1 {
|
||||
return Ok("slice".into_object(self.py()))
|
||||
|
|
Loading…
Reference in New Issue