This commit is contained in:
Nikolay Kim 2017-06-02 09:23:48 -07:00
parent cbfdfa2d07
commit 27bd365f5c
10 changed files with 100 additions and 34 deletions

View file

@ -51,7 +51,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let ptr = <#cls as _pyo3::python::ToPyPointer>::as_ptr(self);
let repr = unsafe {
PyString::downcast_from_owned_ptr(
_pyo3::PyString::downcast_from_owned_ptr(
self.token(), _pyo3::ffi::PyObject_Repr(ptr))
.map_err(|_| std::fmt::Error)?
};
@ -63,7 +63,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let ptr = <#cls as _pyo3::python::ToPyPointer>::as_ptr(self);
let str_obj = unsafe {
PyString::downcast_from_owned_ptr(
_pyo3::PyString::downcast_from_owned_ptr(
self.token(), _pyo3::ffi::PyObject_Str(ptr))
.map_err(|_| std::fmt::Error)?
};

View file

@ -48,7 +48,7 @@ pub fn impl_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) -> Tokens
{
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
_pyo3::callback::cb_meth(LOCATION, |py| {
let mut slf: Py<#cls> = Py::from_borrowed_ptr(py, slf);
let mut slf = _pyo3::Py::<#cls>::from_borrowed_ptr(py, slf);
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);
@ -75,7 +75,7 @@ pub fn impl_proto_wrap(cls: &Box<syn::Ty>, name: &syn::Ident, spec: &FnSpec) ->
{
const LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
_pyo3::callback::cb_meth(LOCATION, |py| {
let mut slf: Py<#cls> = Py::from_borrowed_ptr(py, slf);
let mut slf = _pyo3::Py::<#cls>::from_borrowed_ptr(py, slf);
let args = _pyo3::PyTuple::from_borrowed_ptr(py, args);
let kwargs = _pyo3::argparse::get_kwargs(py, kwargs);

View file

@ -30,12 +30,26 @@ pub fn build_ptr(cls: syn::Ident, ast: &mut syn::DeriveInput) -> Tokens {
}
}
impl #ptr {
pub fn clone_ref(&self, _py: Python) -> #ptr {
#ptr(unsafe{_pyo3::PyPtr::from_borrowed_ptr(self.as_ptr())})
}
}
impl<'p> _pyo3::python::Unpark<'p> for #ptr {
type Target = Py<'p, #cls>;
type RefTarget = #cls;
fn unpark(self, _py: Python<'p>) -> Py<'p, #cls> {
unsafe {std::mem::transmute(self)}
}
fn unpark_ref(&self, _py: Python<'p>) -> &#cls {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
unsafe {
let ptr = (self.as_ptr() as *mut u8).offset(offset) as *mut #cls;
ptr.as_ref().unwrap()
}
}
}
impl std::ops::Deref for #ptr {
@ -46,6 +60,17 @@ pub fn build_ptr(cls: syn::Ident, ast: &mut syn::DeriveInput) -> Tokens {
}
}
impl _pyo3::PyClone for #ptr {
fn clone_ref<'p>(&self, py: _pyo3::Python<'p>) -> _pyo3::PyObject<'p> {
_pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr())
}
}
impl _pyo3::PyClonePtr for #ptr {
fn clone_ptr(&self, _py: _pyo3::Python) -> #ptr {
#ptr(unsafe{ _pyo3::PyPtr::from_borrowed_ptr(self.as_ptr()) })
}
}
impl _pyo3::IntoPyObject for #ptr {
fn into_object(self, _py: Python) -> _pyo3::PyObjectPtr {

View file

@ -4,7 +4,7 @@ use std::os::raw::c_char;
use libc;
use ffi;
use python::{ToPyPointer, IntoPyPointer, Python, Park, PyDowncastInto, PyClone};
use python::{ToPyPointer, IntoPyPointer, Python, Park, PyDowncastInto, PyClone, PyClonePtr};
use objects::{PyObject, PyObjectPtr, PyType, PyTypePtr, exc};
use typeob::{PyTypeObject};
use conversion::{ToPyObject, ToPyTuple, IntoPyObject};
@ -330,6 +330,14 @@ impl PyErr {
category.as_ptr(), message.as_ptr(), stacklevel as ffi::Py_ssize_t))
}
}
pub fn clone_ref(&self, py: Python) -> PyErr {
PyErr {
ptype: self.ptype.clone_ptr(py),
pvalue: self.pvalue.clone_ptr(py),
ptraceback: self.ptraceback.clone_ptr(py),
}
}
}
/// Converts `PyDowncastError` to Python `TypeError`.

View file

@ -1,4 +1,4 @@
#![feature(specialization, const_fn)]
#![feature(specialization, const_fn, proc_macro)]
//! Rust bindings to the Python interpreter.
//!
@ -59,8 +59,6 @@ extern crate libc;
#[macro_use]
pub extern crate pyo3cls;
pub use pyo3cls::*;
pub mod ffi;
pub use ffi::{Py_ssize_t, Py_hash_t};
@ -74,8 +72,8 @@ pub use err::{PyErr, PyResult, PyDowncastError};
pub use objects::*;
pub use objectprotocol::ObjectProtocol;
pub use python::{Python, ToPyPointer, IntoPyPointer,
Park, ParkRef,
PyClone, PyDowncastFrom, PyDowncastInto};
Park, ParkRef, Unpark,
PyClone, PyClonePtr, PyDowncastFrom, PyDowncastInto};
pub use pythonrun::{GILGuard, GILProtected, prepare_freethreaded_python};
pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject, IntoPyObject, ToPyTuple};
pub use class::{CompareOp};

View file

@ -61,10 +61,14 @@ macro_rules! pyobject_nativetype(
impl<'p> $crate::python::Unpark<'p> for $ptr {
type Target = $name<'p>;
type RefTarget = $name<'p>;
fn unpark(self, _py: $crate::Python<'p>) -> $name<'p> {
unsafe {$crate::std::mem::transmute(self)}
}
fn unpark_ref(&self, _py: $crate::Python<'p>) -> &$name<'p> {
unsafe {$crate::std::mem::transmute(self)}
}
}
impl $crate::std::ops::Deref for $ptr {
@ -83,6 +87,17 @@ macro_rules! pyobject_nativetype(
}
}
impl $crate::PyClone for $ptr {
fn clone_ref<'p>(&self, py: $crate::Python<'p>) -> $crate::PyObject<'p> {
$crate::PyObject::from_borrowed_ptr(py, self.as_ptr())
}
}
impl $crate::PyClonePtr for $ptr {
fn clone_ptr(&self, _py: $crate::Python) -> $ptr {
$ptr(unsafe{ $crate::PyPtr::from_borrowed_ptr(self.as_ptr()) })
}
}
impl $crate::python::IntoPyPointer for $ptr {
/// Gets the underlying FFI pointer, returns a owned pointer.
#[inline]

View file

@ -9,7 +9,7 @@ use std::ffi::{CStr, CString};
use conversion::{ToPyObject, ToPyTuple};
use pointers::{Ptr, PyPtr};
use python::{ToPyPointer, Python};
use python::{Python, ToPyPointer};
use token::PyObjectWithGilToken;
use objects::{PyObject, PyDict, PyType, exc};
use objectprotocol::ObjectProtocol;
@ -77,8 +77,7 @@ impl<'p> PyModule<'p> {
/// Calls a function in the module.
/// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
pub fn call<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>)
-> PyResult<PyObject<'p>>
pub fn call<A>(&self, name: &str, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject>
where A: ToPyTuple
{
self.getattr(name)?.call(args, kwargs)
@ -86,7 +85,8 @@ impl<'p> PyModule<'p> {
/// Gets a member from the module.
/// This is equivalent to the Python expression: `getattr(module, name)`
pub fn get(&self, name: &str) -> PyResult<PyObject> {
pub fn get(&self, name: &str) -> PyResult<PyObject<'p>>
{
self.getattr(name)
}

View file

@ -64,7 +64,7 @@ impl PyPtr {
/// Converts `PyPtr` instance -> PyObjectPtr
/// Consumes `self` without calling `Py_DECREF()`
#[inline]
pub fn into_object_ptr(self) -> PyObjectPtr {
pub fn park(self) -> PyObjectPtr {
unsafe { std::mem::transmute(self) }
}

View file

@ -65,8 +65,22 @@ pub trait ParkRef : Sized {
pub trait Unpark<'p> : Sized {
type Target;
type RefTarget;
fn unpark(self, py: Python<'p>) -> Self::Target;
fn unpark_ref(&self, py: Python<'p>) -> &Self::RefTarget;
}
impl<T> Park for PyResult<T> where T: Park {
type Target = PyResult<T::Target>;
fn park(self) -> Self::Target {
match self {
Ok(val) => Ok(val.park()),
Err(e) => Err(e),
}
}
}
/// This trait allows retrieving the underlying FFI pointer from Python objects.
@ -109,6 +123,22 @@ impl <T> IntoPyPointer for Option<T> where T: IntoPyPointer {
pub trait PyClone {
fn clone_ref<'p>(&self, py: Python<'p>) -> PyObject<'p>;
}
pub trait PyClonePtr {
fn clone_ptr(&self, py: Python) -> Self;
}
impl<T> PyClonePtr for Option<T> where T: PyClonePtr {
fn clone_ptr(&self, py: Python) -> Option<T> {
match *self {
Some(ref p) => Some(p.clone_ptr(py)),
None => None,
}
}
}
@ -201,13 +231,6 @@ impl<'p> Python<'p> {
PyModule::import(self, name)
}
pub fn with_token<T, F>(self, f: F) -> Py<'p, T>
where F: FnOnce(PyToken) -> T,
T: PyTypeInfo + PyObjectAlloc<Type=T>
{
::token::with_token(self, f)
}
/// Gets the Python builtin value `None`.
#[allow(non_snake_case)] // the Python keyword starts with uppercase
#[inline]
@ -236,12 +259,12 @@ impl<'p> Python<'p> {
unsafe { PyObjectPtr::from_borrowed_ptr(ffi::Py_NotImplemented()) }
}
/// Execute closure `F` with Python instance.
/// Retrieve Python instance under the assumption that the GIL is already acquired
/// at this point, and stays acquired during closure call.
pub fn with<F, R>(self, f: F) -> R where F: FnOnce(Python<'p>) -> R
/// Execute closure `F` with Python Token instance.
pub fn with<T, F>(self, f: F) -> PyResult<Py<'p, T>>
where F: FnOnce(PyToken) -> T,
T: PyTypeInfo + PyObjectAlloc<Type=T>
{
f(Python(PhantomData))
::token::with(self, f)
}
}

View file

@ -3,6 +3,7 @@
use std::rc::Rc;
use std::marker::PhantomData;
use err::PyResult;
use pointers::Py;
use python::Python;
use typeob::{PyTypeInfo, PyObjectAlloc};
@ -16,17 +17,13 @@ impl PyToken {
}
}
#[inline]
pub fn with_token<'p, T, F>(py: Python<'p>, f: F) -> Py<'p, T>
pub fn with<'p, T, F>(py: Python<'p>, f: F) -> PyResult<Py<'p, T>>
where F: FnOnce(PyToken) -> T,
T: PyTypeInfo + PyObjectAlloc<Type=T>
{
let value = f(PyToken(PhantomData));
if let Ok(ob) = Py::new(py, value) {
ob
} else {
::err::panic_after_error()
}
Py::new(py, f(PyToken(PhantomData)))
}