Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kngwyu committed Feb 4, 2019
1 parent 76e30b5 commit 90c169c
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 81 deletions.
7 changes: 4 additions & 3 deletions src/class/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::callback::{CallbackConverter, PyObjectCallbackConverter};
use crate::conversion::IntoPyObject;
use crate::err::PyResult;
use crate::ffi;
use crate::instance::PyRefMut;
use crate::python::{IntoPyPointer, Python};
use crate::typeob::PyTypeInfo;

Expand All @@ -16,15 +17,15 @@ use crate::typeob::PyTypeInfo;
/// more information
/// `https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_iter`
#[allow(unused_variables)]
pub trait PyIterProtocol<'p>: PyTypeInfo {
fn __iter__(&'p mut self) -> Self::Result
pub trait PyIterProtocol<'p>: PyTypeInfo + Sized {
fn __iter__(self_: PyRefMut<'p, Self>) -> Self::Result
where
Self: PyIterIterProtocol<'p>,
{
unimplemented!()
}

fn __next__(&'p mut self) -> Self::Result
fn __next__(self_: PyRefMut<'p, Self>) -> Self::Result
where
Self: PyIterNextProtocol<'p>,
{
Expand Down
2 changes: 1 addition & 1 deletion src/class/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ macro_rules! py_unary_func {
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let res = slf.$f().into();
let res = $class::$f(PyRefMut::new(slf)).into();
$crate::callback::cb_convert($conv, py, res)
}
Some(wrap::<$class>)
Expand Down
48 changes: 23 additions & 25 deletions src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use crate::err::{PyDowncastError, PyResult};
use crate::ffi;
use crate::instance::Py;
use crate::instance::{Py, PyRef, PyRefMut};
use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeInfo;
Expand Down Expand Up @@ -207,41 +207,41 @@ pub trait PyTryInto<T>: Sized {
type Error;

/// Cast from PyObject to a concrete Python object type.
fn try_into(&self) -> Result<&T, Self::Error>;
fn try_into(&self) -> Result<PyRef<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>;
fn try_into_exact(&self) -> Result<PyRef<T>, Self::Error>;

/// Cast from PyObject to a concrete Python object type.
fn try_into_mut(&self) -> Result<&mut T, Self::Error>;
fn try_into_mut(&self) -> Result<PyRefMut<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>;
fn try_into_mut_exact(&self) -> Result<PyRefMut<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 {
/// Cast from a concrete Python object type to PyObject.
fn try_from(value: &PyObjectRef) -> Result<&Self, PyDowncastError>;
fn try_from(value: &PyObjectRef) -> Result<PyRef<Self>, PyDowncastError>;

/// Cast from a concrete Python object type to PyObject. With exact type check.
fn try_from_exact(value: &PyObjectRef) -> Result<&Self, PyDowncastError>;
fn try_from_exact(value: &PyObjectRef) -> Result<PyRef<Self>, PyDowncastError>;

/// Cast from a concrete Python object type to PyObject.
fn try_from_mut(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>;
fn try_from_mut(value: &PyObjectRef) -> Result<PyRefMut<Self>, PyDowncastError>;

/// Cast from a concrete Python object type to PyObject. With exact type check.
fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut Self, PyDowncastError>;
fn try_from_mut_exact(value: &PyObjectRef) -> Result<PyRefMut<Self>, PyDowncastError>;

/// Cast a PyObjectRef to a specific type of PyObject. The caller must
/// have already verified the reference is for this type.
unsafe fn try_from_unchecked(value: &PyObjectRef) -> &Self;
unsafe fn try_from_unchecked(value: &PyObjectRef) -> PyRef<Self>;

/// Cast a PyObjectRef 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(value: &PyObjectRef) -> &mut Self;
unsafe fn try_from_mut_unchecked(value: &PyObjectRef) -> PyRefMut<Self>;
}

// TryFrom implies TryInto
Expand All @@ -251,16 +251,16 @@ where
{
type Error = PyDowncastError;

fn try_into(&self) -> Result<&U, PyDowncastError> {
fn try_into(&self) -> Result<PyRef<U>, PyDowncastError> {
U::try_from(self)
}
fn try_into_exact(&self) -> Result<&U, PyDowncastError> {
fn try_into_exact(&self) -> Result<PyRef<U>, PyDowncastError> {
U::try_from_exact(self)
}
fn try_into_mut(&self) -> Result<&mut U, PyDowncastError> {
fn try_into_mut(&self) -> Result<PyRefMut<U>, PyDowncastError> {
U::try_from_mut(self)
}
fn try_into_mut_exact(&self) -> Result<&mut U, PyDowncastError> {
fn try_into_mut_exact(&self) -> Result<PyRefMut<U>, PyDowncastError> {
U::try_from_mut_exact(self)
}
}
Expand All @@ -269,7 +269,7 @@ impl<T> PyTryFrom for T
where
T: PyTypeInfo,
{
fn try_from(value: &PyObjectRef) -> Result<&T, PyDowncastError> {
fn try_from(value: &PyObjectRef) -> Result<PyRef<T>, PyDowncastError> {
unsafe {
if T::is_instance(value) {
Ok(PyTryFrom::try_from_unchecked(value))
Expand All @@ -279,7 +279,7 @@ where
}
}

fn try_from_exact(value: &PyObjectRef) -> Result<&T, PyDowncastError> {
fn try_from_exact(value: &PyObjectRef) -> Result<PyRef<T>, PyDowncastError> {
unsafe {
if T::is_exact_instance(value) {
Ok(PyTryFrom::try_from_unchecked(value))
Expand All @@ -289,7 +289,7 @@ where
}
}

fn try_from_mut(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> {
fn try_from_mut(value: &PyObjectRef) -> Result<PyRefMut<T>, PyDowncastError> {
unsafe {
if T::is_instance(value) {
Ok(PyTryFrom::try_from_mut_unchecked(value))
Expand All @@ -299,7 +299,7 @@ where
}
}

fn try_from_mut_exact(value: &PyObjectRef) -> Result<&mut T, PyDowncastError> {
fn try_from_mut_exact(value: &PyObjectRef) -> Result<PyRefMut<T>, PyDowncastError> {
unsafe {
if T::is_exact_instance(value) {
Ok(PyTryFrom::try_from_mut_unchecked(value))
Expand All @@ -310,23 +310,23 @@ where
}

#[inline]
unsafe fn try_from_unchecked(value: &PyObjectRef) -> &T {
unsafe fn try_from_unchecked(value: &PyObjectRef) -> PyRef<T> {
let ptr = if T::OFFSET == 0 {
value as *const _ as *const u8 as *const T
} else {
(value.as_ptr() as *const u8).offset(T::OFFSET) as *const T
};
&*ptr
PyRef::new(&*ptr)
}

#[inline]
unsafe fn try_from_mut_unchecked(value: &PyObjectRef) -> &mut T {
unsafe fn try_from_mut_unchecked(value: &PyObjectRef) -> PyRefMut<T> {
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
};
&mut *ptr
PyRefMut::new(&mut *ptr)
}
}

Expand Down Expand Up @@ -357,8 +357,6 @@ impl<T: IntoPyObject> ReturnTypeIntoPyResult for PyResult<T> {
}
}



#[cfg(test)]
mod test {
use super::PyTryFrom;
Expand Down
54 changes: 27 additions & 27 deletions src/objectprotocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::conversion::{FromPyObject, IntoPyTuple, PyTryFrom, ToBorrowedObject,
use crate::err::{self, PyDowncastError, PyErr, PyResult};
use crate::exceptions::TypeError;
use crate::ffi;
use crate::instance::PyObjectWithGIL;
use crate::instance::{PyObjectWithGIL, PyRef, PyRefMut};
use crate::object::PyObject;
use crate::python::{IntoPyPointer, Python, ToPyPointer};
use crate::typeob::PyTypeInfo;
Expand All @@ -22,7 +22,7 @@ pub trait ObjectProtocol {

/// Retrieves an attribute value.
/// This is equivalent to the Python expression `self.attr_name`.
fn getattr<N>(&self, attr_name: N) -> PyResult<&PyObjectRef>
fn getattr<N>(&self, attr_name: N) -> PyResult<PyRef<PyObjectRef>>
where
N: ToPyObject;

Expand Down Expand Up @@ -73,28 +73,28 @@ pub trait ObjectProtocol {

/// Compute the string representation of self.
/// This is equivalent to the Python expression `repr(self)`.
fn repr(&self) -> PyResult<&PyString>;
fn repr(&self) -> PyResult<PyRef<PyString>>;

/// Compute the string representation of self.
/// This is equivalent to the Python expression `str(self)`.
fn str(&self) -> PyResult<&PyString>;
fn str(&self) -> PyResult<PyRef<PyString>>;

/// Determines whether this object is callable.
fn is_callable(&self) -> bool;

/// Calls the object.
/// This is equivalent to the Python expression: `self(*args, **kwargs)`
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyObjectRef>
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyRef<PyObjectRef>>
where
A: IntoPyTuple;

/// Calls the object.
/// This is equivalent to the Python expression: `self()`
fn call0(&self) -> PyResult<&PyObjectRef>;
fn call0(&self) -> PyResult<PyRef<PyObjectRef>>;

/// Calls the object.
/// This is equivalent to the Python expression: `self(*args)`
fn call1<A>(&self, args: A) -> PyResult<&PyObjectRef>
fn call1<A>(&self, args: A) -> PyResult<PyRef<PyObjectRef>>
where
A: IntoPyTuple;

Expand All @@ -118,15 +118,15 @@ pub trait ObjectProtocol {
name: &str,
args: impl IntoPyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<&PyObjectRef>;
) -> PyResult<PyRef<PyObjectRef>>;

/// Calls a method on the object.
/// This is equivalent to the Python expression: `self.name()`
fn call_method0(&self, name: &str) -> PyResult<&PyObjectRef>;
fn call_method0(&self, name: &str) -> PyResult<PyRef<PyObjectRef>>;

/// Calls a method on the object with positional arguments only .
/// This is equivalent to the Python expression: `self.name(*args)`
fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<&PyObjectRef>;
fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<PyRef<PyObjectRef>>;

/// Retrieves the hash code of the object.
/// This is equivalent to the Python expression: `hash(self)`
Expand All @@ -145,7 +145,7 @@ pub trait ObjectProtocol {
fn len(&self) -> PyResult<usize>;

/// This is equivalent to the Python expression: `self[key]`
fn get_item<K>(&self, key: K) -> PyResult<&PyObjectRef>
fn get_item<K>(&self, key: K) -> PyResult<PyRef<PyObjectRef>>
where
K: ToBorrowedObject;

Expand Down Expand Up @@ -174,18 +174,18 @@ 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(&self) -> PyRef<<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
fn get_mut_base(&mut self) -> PyRefMut<<Self as PyTypeInfo>::BaseType>
where
Self: PyTypeInfo;

/// Casts the PyObject to a concrete Python object type.
fn cast_as<'a, D>(&'a self) -> Result<&'a D, PyDowncastError>
fn cast_as<'a, D>(&'a self) -> Result<PyRef<'a, D>, PyDowncastError>
where
D: PyTryFrom,
&'a PyObjectRef: std::convert::From<&'a Self>;
Expand Down Expand Up @@ -218,7 +218,7 @@ where
})
}

fn getattr<N>(&self, attr_name: N) -> PyResult<&PyObjectRef>
fn getattr<N>(&self, attr_name: N) -> PyResult<PyRef<PyObjectRef>>
where
N: ToPyObject,
{
Expand Down Expand Up @@ -303,14 +303,14 @@ where
}
}

fn repr(&self) -> PyResult<&PyString> {
fn repr(&self) -> PyResult<PyRef<PyString>> {
unsafe {
self.py()
.from_owned_ptr_or_err(ffi::PyObject_Repr(self.as_ptr()))
}
}

fn str(&self) -> PyResult<&PyString> {
fn str(&self) -> PyResult<PyRef<PyString>> {
unsafe {
self.py()
.from_owned_ptr_or_err(ffi::PyObject_Str(self.as_ptr()))
Expand All @@ -321,7 +321,7 @@ where
unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 }
}

fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<&PyObjectRef>
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyRef<PyObjectRef>>
where
A: IntoPyTuple,
{
Expand All @@ -338,11 +338,11 @@ where
result
}

fn call0(&self) -> PyResult<&PyObjectRef> {
fn call0(&self) -> PyResult<PyRef<PyObjectRef>> {
self.call(PyTuple::empty(self.py()), None)
}

fn call1<A>(&self, args: A) -> PyResult<&PyObjectRef>
fn call1<A>(&self, args: A) -> PyResult<PyRef<PyObjectRef>>
where
A: IntoPyTuple,
{
Expand All @@ -354,7 +354,7 @@ where
name: &str,
args: impl IntoPyTuple,
kwargs: Option<&PyDict>,
) -> PyResult<&PyObjectRef> {
) -> PyResult<PyRef<PyObjectRef>> {
name.with_borrowed_ptr(self.py(), |name| unsafe {
let py = self.py();
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
Expand All @@ -372,11 +372,11 @@ where
})
}

fn call_method0(&self, name: &str) -> PyResult<&PyObjectRef> {
fn call_method0(&self, name: &str) -> PyResult<PyRef<PyObjectRef>> {
self.call_method(name, PyTuple::empty(self.py()), None)
}

fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<&PyObjectRef> {
fn call_method1(&self, name: &str, args: impl IntoPyTuple) -> PyResult<PyRef<PyObjectRef>> {
self.call_method(name, args, None)
}

Expand Down Expand Up @@ -411,7 +411,7 @@ where
}
}

fn get_item<K>(&self, key: K) -> PyResult<&PyObjectRef>
fn get_item<K>(&self, key: K) -> PyResult<PyRef<PyObjectRef>>
where
K: ToBorrowedObject,
{
Expand Down Expand Up @@ -455,21 +455,21 @@ where
unsafe { (*self.as_ptr()).ob_type }
}

fn get_base(&self) -> &<Self as PyTypeInfo>::BaseType
fn get_base(&self) -> PyRef<<Self as PyTypeInfo>::BaseType>
where
Self: PyTypeInfo,
{
unsafe { self.py().from_borrowed_ptr(self.as_ptr()) }
}

fn get_mut_base(&mut self) -> &mut <Self as PyTypeInfo>::BaseType
fn get_mut_base(&mut self) -> PyRefMut<<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>
fn cast_as<'a, D>(&'a self) -> Result<PyRef<'a, D>, PyDowncastError>
where
D: PyTryFrom,
&'a PyObjectRef: std::convert::From<&'a Self>,
Expand Down
Loading

0 comments on commit 90c169c

Please sign in to comment.