better gil token scope

This commit is contained in:
Nikolay Kim 2017-05-29 13:30:38 -07:00
parent ea8ccf190a
commit 51ac8c9c78
28 changed files with 357 additions and 311 deletions

View file

@ -52,8 +52,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
let extra = if let Some(token) = token {
Some(quote! {
impl _pyo3::PythonObjectWithToken for #cls {
fn token<'p>(&'p self) -> _pyo3::python::Python<'p> {
self.#token.token()
fn token<'p>(&'p self) -> _pyo3::python::Python<'p> {
self.#token.token()
}
}
@ -127,12 +127,16 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident, token: Option<syn::Ident>) ->
let ptr = (py.as_ptr() as *mut u8).offset(offset) as *mut #cls;
Ok(ptr.as_ref().unwrap())
} else {
Err(_pyo3::PyDowncastError(py.token(), None))
Err(_pyo3::PyDowncastError(py.gil(), None))
}
}
}
}
impl _pyo3::class::PyCustomObject for #cls {
}
#extra
}
}

View file

@ -331,7 +331,7 @@ macro_rules! py_argparse_impl {
// We'll have to generate a bunch of nested `match` statements
// (at least until we can use ? + catch, assuming that will be hygienic wrt. macros),
// so use a recursive helper macro for that:
py_argparse_extract!( py, _iter, $body,
py_argparse_extract!(py, _iter, $body,
[ $( { $pname : $ptype = $detail } )* ])
},
Err(e) => Err(e)
@ -344,11 +344,9 @@ macro_rules! py_argparse_impl {
#[doc(hidden)]
macro_rules! py_argparse_raw {
($py:ident, $fname:expr, $args:expr, $kwargs:expr, $plist:tt $body:block) => {{
let args: $crate::PyTuple = $crate::PyObject::from_borrowed_ptr($py, $args).unchecked_cast_into();
let args: $crate::PyTuple = $crate::PyTuple::from_borrowed_ptr($py, $args);
let kwargs: Option<$crate::PyDict> = $crate::argparse::get_kwargs($py, $kwargs);
let ret = py_argparse_impl!($py, $fname, &args, kwargs.as_ref(), $body, $plist);
$crate::PyDrop::release_ref(args, $py);
$crate::PyDrop::release_ref(kwargs, $py);
ret
}};
}
@ -363,7 +361,7 @@ pub unsafe fn get_kwargs<'p>(py: Python<'p>, ptr: *mut ffi::PyObject) -> Option<
}
}
/*
#[macro_export]
#[doc(hidden)]
macro_rules! py_argparse_param_description {
@ -394,7 +392,8 @@ macro_rules! py_argparse_extract {
) => {
// First unwrap() asserts the iterated sequence is long enough (which should be guaranteed);
// second unwrap() asserts the parameter was not missing (which fn parse_args already checked for).
match <$ptype as $crate::FromPyObject>::extract($py, $iter.next().unwrap().as_ref().unwrap()) {
match <$ptype as $crate::FromPyObject>::extract(
$iter.next().unwrap().as_ref().unwrap()) {
Ok($pname) => py_argparse_extract!($py, $iter, $body, [$($tail)*]),
Err(e) => Err(e)
}
@ -405,8 +404,8 @@ macro_rules! py_argparse_extract {
) => {
// First unwrap() asserts the iterated sequence is long enough (which should be guaranteed);
// second unwrap() asserts the parameter was not missing (which fn parse_args already checked for).
match <$rtype as $crate::RefFromPyObject>::with_extracted($py,
$iter.next().unwrap().as_ref().unwrap(),
match <$rtype as $crate::RefFromPyObject>::with_extracted(
$iter.next().unwrap().as_ref().unwrap(),
|$pname: $ptype| py_argparse_extract!($py, $iter, $body, [$($tail)*])
) {
Ok(v) => v,
@ -417,7 +416,7 @@ macro_rules! py_argparse_extract {
( $py:expr, $iter:expr, $body:block,
[ { $pname:ident : $ptype:ty = [ {} {$default:expr} {} ] } $($tail:tt)* ]
) => {
match $iter.next().unwrap().as_ref().map(|obj| obj.extract::<_>($py)).unwrap_or(Ok($default)) {
match $iter.next().unwrap().as_ref().map(|obj| obj.extract::<_>()).unwrap_or(Ok($default)) {
Ok($pname) => py_argparse_extract!($py, $iter, $body, [$($tail)*]),
Err(e) => Err(e)
}
@ -427,8 +426,7 @@ macro_rules! py_argparse_extract {
[ { $pname:ident : $ptype:ty = [ {} {$default:expr} {$rtype:ty} ] } $($tail:tt)* ]
) => {
//unwrap() asserts the iterated sequence is long enough (which should be guaranteed);
$crate::argparse::with_extracted_or_default($py,
$iter.next().unwrap().as_ref(),
$crate::argparse::with_extracted_or_default($iter.next().unwrap().as_ref(),
|$pname: $ptype| py_argparse_extract!($py, $iter, $body, [$($tail)*]),
$default)
};
@ -436,24 +434,22 @@ macro_rules! py_argparse_extract {
#[doc(hidden)] // used in py_argparse_extract!() macro
pub fn with_extracted_or_default<'p, P: ?Sized, R, F>(
py: Python<'p>,
obj: Option<&'p Py<'p,PyObject>>,
f: F, default: &'static P) -> PyResult<R>
obj: Option<&'p PyObject>, f: F, default: &'static P) -> PyResult<R>
where F: FnOnce(&P) -> PyResult<R>,
P: RefFromPyObject<'p>
{
match obj {
Some(obj) => match P::with_extracted(py, obj, f) {
Some(obj) => match P::with_extracted(obj, f) {
Ok(result) => result,
Err(e) => Err(e)
},
None => f(default)
}
}
*/
#[cfg(test)]
mod test {
mod test {
use python::{Python};
use objects::PyTuple;
use conversion::{ToPyTuple};
@ -480,7 +476,7 @@ mod test {
let mut called = false;
let tuple = ("abc",).to_py_tuple(py);
py_argparse!(py, None, &tuple, None, (x) {
assert_eq!(*x, tuple.get_item(py, 0));
assert_eq!(*x, tuple.get_item(0));
called = true;
Ok(())
}).unwrap();

View file

@ -139,7 +139,7 @@ fn validate(b: &ffi::Py_buffer) {
impl PyBuffer {
/// Get the underlying buffer from the specified python object.
pub fn get<'p>(obj: Py<'p, PyObject>) -> PyResult<PyBuffer> {
pub fn get<'p>(obj: &PyObject<'p>) -> PyResult<PyBuffer> {
unsafe {
let mut buf = Box::new(mem::zeroed::<ffi::Py_buffer>());
err::error_on_minusone(
@ -565,12 +565,13 @@ impl_element!(isize, SignedInteger);
impl_element!(f32, Float);
impl_element!(f64, Float);
#[cfg(test)]
//#[cfg(test)]
mod test {
use std;
use python::{Python, PythonObject, PyDrop};
use python::{Python};
use conversion::ToPyObject;
use objects::{PySequence, PyList, PyTuple, PyIterator};
use objects::{PyList, PyTuple};//, PySequence, PyIterator};
use objectprotocol::ObjectProtocol;
use super::PyBuffer;
@ -585,7 +586,7 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let bytes = py.eval("b'abcde'", None, None).unwrap();
let buffer = PyBuffer::get(py, &bytes).unwrap();
let buffer = PyBuffer::get(&bytes).unwrap();
assert_eq!(buffer.dimensions(), 1);
assert_eq!(buffer.item_count(), 5);
assert_eq!(buffer.format().to_str().unwrap(), "B");
@ -620,8 +621,9 @@ mod test {
fn test_array_buffer() {
let gil = Python::acquire_gil();
let py = gil.python();
let array = py.import("array").unwrap().as_object().call_method(py, "array", ("f", (1.0, 1.5, 2.0, 2.5)), None).unwrap();
let buffer = PyBuffer::get(py, &array).unwrap();
let array = py.import("array").unwrap().call_method(
"array", ("f", (1.0, 1.5, 2.0, 2.5)), None).unwrap();
let buffer = PyBuffer::get(&array).unwrap();
assert_eq!(buffer.dimensions(), 1);
assert_eq!(buffer.item_count(), 4);
assert_eq!(buffer.format().to_str().unwrap(), "f");

View file

@ -32,6 +32,8 @@ pub static NO_METHODS: &'static [&'static str] = &[];
pub static NO_PY_METHODS: &'static [PyMethodDefType] = &[];
use ffi;
use typeob::PyTypeInfo;
use python::ToPythonPointer;
#[derive(Debug)]
pub enum CompareOp {
@ -43,4 +45,14 @@ pub enum CompareOp {
Ge = ffi::Py_GE as isize
}
pub trait PyCustomObject : Sized {}
pub trait PyCustomObject : PyTypeInfo + Sized {}
impl<'p, T> ToPythonPointer for T where T: PyCustomObject {
#[inline]
fn as_ptr(&self) -> *mut ffi::PyObject {
let offset = <T as PyTypeInfo>::offset();
unsafe {
{self as *const _ as *mut u8}.offset(-offset) as *mut ffi::PyObject
}
}
}

View file

@ -1,6 +1,6 @@
use ffi;
use err::PyResult;
use pyptr::{Py, PyPtr};
use pyptr::PyPtr;
use python::{Python, ToPythonPointer};
use objects::{PyObject, PyTuple};
use token::PyObjectMarker;
@ -21,7 +21,7 @@ pub trait ToPyObject {
fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
where F: FnOnce(*mut ffi::PyObject) -> R
{
let obj = self.to_object(py).into_object();
let obj = self.to_object(py).park();
f(obj.as_ptr())
}
}
@ -79,7 +79,7 @@ pub trait FromPyObject<'source> : Sized {
}
pub trait RefFromPyObject<'p> {
fn with_extracted<F, R>(obj: &'p Py<'p, PyObject>, f: F) -> PyResult<R>
fn with_extracted<F, R>(obj: &'p PyObject, f: F) -> PyResult<R>
where F: FnOnce(&Self) -> R;
}
@ -87,7 +87,7 @@ impl <'p, T: ?Sized> RefFromPyObject<'p> for T
where for<'a> &'a T: FromPyObject<'p> + Sized
{
#[inline]
fn with_extracted<F, R>(obj: &'p Py<'p, PyObject>, f: F) -> PyResult<R>
fn with_extracted<F, R>(obj: &'p PyObject, f: F) -> PyResult<R>
where F: FnOnce(&Self) -> R
{
match FromPyObject::extract(obj) {

View file

@ -179,7 +179,7 @@ impl PyErr {
ptype: if ptype.is_null() {
py.get_type::<exc::SystemError>().into_object()
} else {
PyPtr::<PyObjectMarker>::from_owned_ptr(ptype).into_object()
PyPtr::<PyObjectMarker>::from_owned_ptr(ptype).park()
},
pvalue: PyPtr::from_owned_ptr_or_opt(py, pvalue),
ptraceback: PyPtr::from_owned_ptr_or_opt(py, ptraceback)
@ -386,12 +386,12 @@ pub fn error_on_minusone(py: Python, result: libc::c_int) -> PyResult<()> {
#[cfg(test)]
mod tests {
use {Python, PyErr};
use ::{Python, PyErr};
use objects::exc;
#[test]
fn set_typeerror() {
let gil = Python::acqduire_gil();
let gil = Python::acquire_gil();
let py = gil.python();
PyErr::new_lazy_init(py.get_type::<exc::TypeError>(), None).restore(py);
assert!(PyErr::occurred(py));

View file

@ -115,7 +115,7 @@ macro_rules! py_fn_impl {
kwargs: *mut $crate::ffi::PyObject)
-> *mut $crate::ffi::PyObject
{
$crate::callback::handle_callback(
$crate::callback::handle(
stringify!($f), $crate::callback::PyObjectCallbackConverter,
|py| {
py_argparse_raw!(py, Some(stringify!($f)), args, kwargs,

View file

@ -71,7 +71,7 @@ mod ppptr;
pub use ppptr::pptr;
mod token;
pub use token::{PyObjectMarker, PythonToken, PythonObjectWithToken};
pub use token::{PyObjectMarker, PythonToken, PythonObjectWithToken, PythonObjectWithGilToken};
pub use err::{PyErr, PyResult, PyDowncastError};
pub use objects::*;
@ -82,6 +82,7 @@ pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject, IntoPyObject, To
pub use class::{CompareOp};
pub mod class;
pub use class::*;
pub use native::PyNativeObject;
pub use self::typeob::PyTypeObject;
#[allow(non_camel_case_types)]
@ -112,7 +113,7 @@ macro_rules! py_replace_expr {
}
pub mod python;
pub mod native;
mod native;
mod err;
mod conversion;
mod objects;
@ -122,7 +123,7 @@ pub mod callback;
pub mod typeob;
pub mod argparse;
pub mod function;
pub mod buffer;
// pub mod buffer;
// re-export for simplicity
pub use std::os::raw::*;

View file

@ -1,16 +1,23 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use ffi;
use ppptr::pptr;
use pyptr::PyPtr;
use token::PyObjectMarker;
use typeob::PyTypeInfo;
use objects::PyObject;
use python::ToPythonPointer;
pub trait PyBaseObject : PyTypeInfo + Sized {}
pub trait PyNativeObject : PyTypeInfo {
pub trait PyNativeObject<'p> : PyBaseObject {
fn as_object(self) -> PyObject<'p>;
fn into_object(self) -> PyPtr<PyObjectMarker>;
}
/*impl<'a, T: Sized> FromPyObject<'a> for T
where T: PyNativeObject + PythonObjectWithCheckedDowncast
{

View file

@ -7,15 +7,15 @@ use std::cmp::Ordering;
use ffi;
use libc;
use pyptr::{Py, PyPtr};
use python::{Python, ToPythonPointer};
use python::{Python, PyDowncastInto, ToPythonPointer};
use objects::{PyObject, PyDict, PyString};
use token::PythonObjectWithToken;
use token::PythonObjectWithGilToken;
use conversion::{ToPyObject, ToPyTuple};
use typeob::PyTypeInfo;
use err::{PyErr, PyResult, self};
pub trait ObjectProtocol {
pub trait ObjectProtocol<'p> {
/// Determines whether this object has the given attribute.
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
@ -23,7 +23,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<Py<PyObject>> where N: ToPyObject;
fn getattr<N>(&self, attr_name: N) -> PyResult<PyObject<'p>> where N: ToPyObject;
/// Sets an attribute value.
/// This is equivalent to the Python expression 'self.attr_name = value'.
@ -61,29 +61,29 @@ pub trait ObjectProtocol {
/// * CompareOp::Gt: `self > other`
/// * CompareOp::Ge: `self >= other`
fn rich_compare<O>(&self, other: O, compare_op: ::CompareOp)
-> PyResult<Py<PyObject>> where O: ToPyObject;
-> PyResult<PyObject<'p>> where O: ToPyObject;
/// Compute the string representation of self.
/// This is equivalent to the Python expression 'repr(self)'.
fn repr(&self) -> PyResult<Py<PyString>>;
fn repr(&self) -> PyResult<PyString<'p>>;
/// Compute the string representation of self.
/// This is equivalent to the Python expression 'str(self)'.
fn str(&self) -> PyResult<Py<PyString>>;
fn str(&self) -> PyResult<PyString<'p>>;
/// 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<Py<PyObject>>
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
where A: ToPyTuple;
/// Calls a method on the object.
/// This is equivalent to the Python expression: 'self.name(*args, **kwargs)'
fn call_method<A>(&self,
name: &str, args: A,
kwargs: Option<&PyDict>) -> PyResult<Py<PyObject>>
kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
where A: ToPyTuple;
/// Retrieves the hash code of the object.
@ -104,7 +104,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<Py<PyObject>> where K: ToPyObject;
fn get_item<K>(&self, key: K) -> PyResult<PyObject<'p>> where K: ToPyObject;
/// Sets an item value.
/// This is equivalent to the Python expression 'self[key] = value'.
@ -122,13 +122,13 @@ pub trait ObjectProtocol {
}
impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
impl<'p, T> ObjectProtocol<'p> for T where T: PythonObjectWithGilToken<'p> + ToPythonPointer {
/// Determines whether this object has the given attribute.
/// This is equivalent to the Python expression 'hasattr(self, attr_name)'.
#[inline]
fn hasattr<N>(&self, attr_name: N) -> PyResult<bool> where N: ToPyObject {
attr_name.with_borrowed_ptr(self.token(), |attr_name| unsafe {
attr_name.with_borrowed_ptr(self.gil(), |attr_name| unsafe {
Ok(ffi::PyObject_HasAttr(self.as_ptr(), attr_name) != 0)
})
}
@ -136,11 +136,11 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
/// Retrieves an attribute value.
/// This is equivalent to the Python expression 'self.attr_name'.
#[inline]
fn getattr<N>(&self, attr_name: N) -> PyResult<Py<PyObject>> where N: ToPyObject
fn getattr<N>(&self, attr_name: N) -> PyResult<PyObject<'p>> where N: ToPyObject
{
attr_name.with_borrowed_ptr(self.token(), |attr_name| unsafe {
Py::from_owned_ptr_or_err(
self.token(), ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
attr_name.with_borrowed_ptr(self.gil(), |attr_name| unsafe {
PyObject::from_owned_ptr_or_err(
self.gil(), ffi::PyObject_GetAttr(self.as_ptr(), attr_name))
})
}
@ -151,10 +151,10 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
where N: ToPyObject, V: ToPyObject
{
attr_name.with_borrowed_ptr(
self.token(), move |attr_name|
value.with_borrowed_ptr(self.token(), |value| unsafe {
self.gil(), move |attr_name|
value.with_borrowed_ptr(self.gil(), |value| unsafe {
err::error_on_minusone(
self.token(), ffi::PyObject_SetAttr(self.as_ptr(), attr_name, value))
self.gil(), ffi::PyObject_SetAttr(self.as_ptr(), attr_name, value))
}))
}
@ -162,8 +162,8 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
/// This is equivalent to the Python expression 'del self.attr_name'.
#[inline]
fn delattr<N>(&self, attr_name: N) -> PyResult<()> where N: ToPyObject {
attr_name.with_borrowed_ptr(self.token(), |attr_name| unsafe {
err::error_on_minusone(self.token(),
attr_name.with_borrowed_ptr(self.gil(), |attr_name| unsafe {
err::error_on_minusone(self.gil(),
ffi::PyObject_DelAttr(self.as_ptr(), attr_name))
})
}
@ -208,8 +208,8 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
return Err(PyErr::new::<::exc::TypeError, _>(py, "ObjectProtocol::compare(): All comparisons returned false"));
}
other.with_borrowed_ptr(self.token(), |other| unsafe {
do_compare(self.token(), self.as_ptr(), other)
other.with_borrowed_ptr(self.gil(), |other| unsafe {
do_compare(self.gil(), self.as_ptr(), other)
})
}
@ -223,11 +223,11 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
/// * CompareOp::Gt: `self > other`
/// * CompareOp::Ge: `self >= other`
fn rich_compare<O>(&self, other: O, compare_op: ::CompareOp)
-> PyResult<Py<PyObject>> where O: ToPyObject {
-> PyResult<PyObject<'p>> where O: ToPyObject {
unsafe {
other.with_borrowed_ptr(self.token(), |other| {
Py::cast_from_owned_or_err(
self.token(), ffi::PyObject_RichCompare(
other.with_borrowed_ptr(self.gil(), |other| {
PyObject::from_owned_ptr_or_err(
self.gil(), ffi::PyObject_RichCompare(
self.as_ptr(), other, compare_op as libc::c_int))
})
}
@ -236,15 +236,17 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
/// Compute the string representation of self.
/// This is equivalent to the Python expression 'repr(self)'.
#[inline]
fn repr(&self) -> PyResult<Py<PyString>> {
unsafe { Py::cast_from_owned_or_err(self.token(), ffi::PyObject_Repr(self.as_ptr())) }
fn repr(&self) -> PyResult<PyString<'p>> {
Ok(PyString::downcast_from_owned_ptr(
self.gil(), unsafe{ffi::PyObject_Repr(self.as_ptr())})?)
}
/// Compute the string representation of self.
/// This is equivalent to the Python expression 'str(self)'.
#[inline]
fn str(&self) -> PyResult<Py<PyString>> {
unsafe { Py::cast_from_owned_or_err(self.token(), ffi::PyObject_Str(self.as_ptr())) }
fn str(&self) -> PyResult<PyString<'p>> {
Ok(PyString::downcast_from_owned_ptr(
self.gil(), unsafe{ffi::PyObject_Str(self.as_ptr())})?)
}
/// Determines whether this object is callable.
@ -258,13 +260,13 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
/// Calls the object.
/// This is equivalent to the Python expression: 'self(*args, **kwargs)'
#[inline]
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<Py<PyObject>>
fn call<A>(&self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
where A: ToPyTuple
{
let t = args.to_py_tuple(self.token());
let t = args.to_py_tuple(self.gil());
unsafe {
Py::from_owned_ptr_or_err(
self.token(),
PyObject::from_owned_ptr_or_err(
self.gil(),
ffi::PyObject_Call(self.as_ptr(), t.as_ptr(), kwargs.as_ptr()))
}
}
@ -274,14 +276,14 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
#[inline]
fn call_method<A>(&self,
name: &str, args: A,
kwargs: Option<&PyDict>) -> PyResult<Py<PyObject>>
kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
where A: ToPyTuple
{
name.with_borrowed_ptr(self.token(), |name| unsafe {
let t = args.to_py_tuple(self.token());
name.with_borrowed_ptr(self.gil(), |name| unsafe {
let t = args.to_py_tuple(self.gil());
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
Py::from_owned_ptr_or_err(
self.token(),
PyObject::from_owned_ptr_or_err(
self.gil(),
ffi::PyObject_Call(ptr, t.as_ptr(), kwargs.as_ptr()))
})
}
@ -292,7 +294,7 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
fn hash(&self) -> PyResult<::Py_hash_t> {
let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.token()))
Err(PyErr::fetch(self.gil()))
} else {
Ok(v)
}
@ -304,7 +306,7 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
fn is_true(&self) -> PyResult<bool> {
let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.token()))
Err(PyErr::fetch(self.gil()))
} else {
Ok(v != 0)
}
@ -323,7 +325,7 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
fn len(&self) -> PyResult<usize> {
let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };
if v == -1 {
Err(PyErr::fetch(self.token()))
Err(PyErr::fetch(self.gil()))
} else {
Ok(v as usize)
}
@ -331,10 +333,10 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
/// This is equivalent to the Python expression: 'self[key]'
#[inline]
fn get_item<K>(&self, key: K) -> PyResult<Py<PyObject>> where K: ToPyObject {
key.with_borrowed_ptr(self.token(), |key| unsafe {
Py::from_owned_ptr_or_err(
self.token(), ffi::PyObject_GetItem(self.as_ptr(), key))
fn get_item<K>(&self, key: K) -> PyResult<PyObject<'p>> where K: ToPyObject {
key.with_borrowed_ptr(self.gil(), |key| unsafe {
PyObject::from_owned_ptr_or_err(
self.gil(), ffi::PyObject_GetItem(self.as_ptr(), key))
})
}
@ -345,9 +347,9 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
where K: ToPyObject, V: ToPyObject
{
key.with_borrowed_ptr(
self.token(), move |key|
value.with_borrowed_ptr(self.token(), |value| unsafe {
err::error_on_minusone(self.token(),
self.gil(), move |key|
value.with_borrowed_ptr(self.gil(), |value| unsafe {
err::error_on_minusone(self.gil(),
ffi::PyObject_SetItem(self.as_ptr(), key, value))
}))
}
@ -356,8 +358,8 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
/// This is equivalent to the Python expression 'del self[key]'.
#[inline]
fn del_item<K>(&self, key: K) -> PyResult<()> where K: ToPyObject {
key.with_borrowed_ptr(self.token(), |key| unsafe {
err::error_on_minusone(self.token(),
key.with_borrowed_ptr(self.gil(), |key| unsafe {
err::error_on_minusone(self.gil(),
ffi::PyObject_DelItem(self.as_ptr(), key))
})
}
@ -372,7 +374,7 @@ impl<T> ObjectProtocol for T where T: PythonObjectWithToken + ToPythonPointer {
}
impl<'p, T> fmt::Debug for Py<'p, T> where T: ObjectProtocol + PyTypeInfo {
impl<'p, T> fmt::Debug for Py<'p, T> where T: ObjectProtocol<'p> + PyTypeInfo {
fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
// TODO: we shouldn't use fmt::Error when repr() fails
let repr_obj = try!(self.repr().map_err(|_| fmt::Error));
@ -380,7 +382,7 @@ impl<'p, T> fmt::Debug for Py<'p, T> where T: ObjectProtocol + PyTypeInfo {
}
}
impl<'p, T> fmt::Display for Py<'p, T> where T: ObjectProtocol + PyTypeInfo {
impl<'p, T> fmt::Display for Py<'p, T> where T: ObjectProtocol<'p> + PyTypeInfo {
fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
// TODO: we shouldn't use fmt::Error when str() fails
let str_obj = try!(self.str().map_err(|_| fmt::Error));
@ -388,7 +390,7 @@ impl<'p, T> fmt::Display for Py<'p, T> where T: ObjectProtocol + PyTypeInfo {
}
}
impl<'p, T> fmt::Debug for PyPtr<T> where T: ObjectProtocol + PyTypeInfo {
impl<'p, T> fmt::Debug for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
let gil = Python::acquire_gil();
let py = gil.python();
@ -400,7 +402,7 @@ impl<'p, T> fmt::Debug for PyPtr<T> where T: ObjectProtocol + PyTypeInfo {
}
}
impl<'p, T> fmt::Display for PyPtr<T> where T: ObjectProtocol + PyTypeInfo {
impl<'p, T> fmt::Display for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
let gil = Python::acquire_gil();
let py = gil.python();
@ -414,17 +416,16 @@ impl<'p, T> fmt::Display for PyPtr<T> where T: ObjectProtocol + PyTypeInfo {
#[cfg(test)]
mod test {
use std;
use python::{Python, PythonObject};
use python::{Python};
use conversion::ToPyObject;
use objects::{PyList, PyTuple};
//use objects::{PyTuple}; //PyList,
use super::ObjectProtocol;
#[test]
fn test_debug_string() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = "Hello\n".to_py_object(py).into_object();
let v = "Hello\n".to_object(py);
assert_eq!(format!("{:?}", v), "'Hello\\n'");
}
@ -432,7 +433,7 @@ mod test {
fn test_display_string() {
let gil = Python::acquire_gil();
let py = gil.python();
let v = "Hello\n".to_py_object(py).into_object();
let v = "Hello\n".to_object(py);
assert_eq!(format!("{}", v), "Hello\n");
}
@ -441,10 +442,9 @@ mod test {
use std::cmp::Ordering;
let gil = Python::acquire_gil();
let py = gil.python();
let one = 1i32.to_py_object(py).into_object();
assert_eq!(one.compare(py, 1).unwrap(), Ordering::Equal);
assert_eq!(one.compare(py, 2).unwrap(), Ordering::Less);
assert_eq!(one.compare(py, 0).unwrap(), Ordering::Greater);
let one = 1i32.to_object(py).into_object(py);
assert_eq!(one.compare(1).unwrap(), Ordering::Equal);
assert_eq!(one.compare(2).unwrap(), Ordering::Less);
assert_eq!(one.compare(0).unwrap(), Ordering::Greater);
}
}

View file

@ -52,16 +52,17 @@ pyobject_extract!(obj to bool => {
#[cfg(test)]
mod test {
use python::{Python, PythonObject};
use python::{Python};
use conversion::ToPyObject;
use ::PyNativeObject;
#[test]
fn test_true() {
let gil = Python::acquire_gil();
let py = gil.python();
assert!(py.True().is_true());
assert_eq!(true, py.True().as_object().extract(py).unwrap());
assert!(true.to_py_object(py).as_object() == py.True().as_object());
assert_eq!(true, py.True().as_object().extract().unwrap());
assert!(true.to_object(py).into_object(py) == py.True().as_object());
}
#[test]
@ -69,7 +70,7 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
assert!(!py.False().is_true());
assert_eq!(false, py.False().as_object().extract(py).unwrap());
assert!(false.to_py_object(py).as_object() == py.False().as_object());
assert_eq!(false, py.False().as_object().extract().unwrap());
assert!(false.to_object(py).into_object(py) == py.False().as_object());
}
}

View file

@ -7,8 +7,8 @@ use ffi;
use python::{Python, ToPythonPointer};
use objects::PyObject;
use err::{PyResult, PyErr};
use pyptr::Py;
use ppptr::pptr;
use token::PythonObjectWithGilToken;
/// Represents a Python bytearray.
@ -31,13 +31,13 @@ impl<'p> PyByteArray<'p> {
/// Creates a new Python bytearray object
/// from other PyObject, that implements the buffer protocol.
pub fn from(src: Py<'p, PyObject>) -> PyResult<PyByteArray<'p>> {
pub fn from(src: &'p PyObject<'p>) -> PyResult<PyByteArray<'p>> {
let res = unsafe {ffi::PyByteArray_FromObject(src.as_ptr())};
if res != ptr::null_mut() {
Ok(unsafe{ PyByteArray(
pptr::cast_from_owned_ptr_or_panic::<PyByteArray>(src.token(), res))})
pptr::cast_from_owned_ptr_or_panic::<PyByteArray>(src.gil(), res))})
} else {
Err(PyErr::fetch(src.token()))
Err(PyErr::fetch(src.gil()))
}
}
@ -75,9 +75,10 @@ impl<'p> PyByteArray<'p> {
#[cfg(test)]
mod test {
use ::ToPyObject;
use exc;
use class::PyTypeObject;
use python::Python;
use typeob::PyTypeObject;
use objects::PyByteArray;
#[test]
@ -90,17 +91,20 @@ mod test {
assert_eq!(src.len(), bytearray.len());
assert_eq!(src, bytearray.data());
//let bytearray = PyByteArray::from(py, bytearray.into_object()).unwrap();
//assert_eq!(src.len(), bytearray.len(py));
//assert_eq!(src, bytearray.data(py));
let ba = bytearray.to_object(py);
let bytearray = PyByteArray::from(ba.as_object(py)).unwrap();
assert_eq!(src.len(), bytearray.len());
assert_eq!(src, bytearray.data());
bytearray.resize(20).unwrap();
assert_eq!(20, bytearray.len());
//if let Err(mut err) = PyByteArray::from(py, py.None()) {
// assert!(exc::TypeError::type_object(py).is_instance(py, &err.instance(py)))
//} else {
// panic!("error");
//}
let none = py.None();
if let Err(mut err) = PyByteArray::from(none.as_object(py)) {
assert!(exc::TypeError::type_object(py).is_instance(&err.instance(py)))
} else {
panic!("error");
}
drop(none);
}
}

View file

@ -8,7 +8,7 @@ use pyptr::PyPtr;
use python::{Python, ToPythonPointer};
use conversion::{ToPyObject, IntoPyObject};
use objects::PyObject;
use token::{PyObjectMarker, PythonObjectWithToken}; //, PyList};
use token::{PyObjectMarker, PythonObjectWithGilToken}; //, PyList};
use err::{self, PyResult, PyErr};
use std::{mem, collections, hash, cmp};
@ -36,7 +36,7 @@ impl<'p> PyDict<'p> {
pub fn copy(&'p self) -> PyResult<PyDict<'p>> {
unsafe {
Ok(PyDict(
pptr::from_owned_ptr_or_err(self.token(), ffi::PyDict_Copy(self.0.as_ptr()))?
pptr::from_owned_ptr_or_err(self.gil(), ffi::PyDict_Copy(self.0.as_ptr()))?
))
}
}
@ -57,11 +57,11 @@ impl<'p> PyDict<'p> {
/// Determine if the dictionary contains the specified key.
/// This is equivalent to the Python expression `key in self`.
pub fn contains<K>(&self, key: K) -> PyResult<bool> where K: ToPyObject {
key.with_borrowed_ptr(self.token(), |key| unsafe {
key.with_borrowed_ptr(self.gil(), |key| unsafe {
match ffi::PyDict_Contains(self.as_ptr(), key) {
1 => Ok(true),
0 => Ok(false),
_ => Err(PyErr::fetch(self.token()))
_ => Err(PyErr::fetch(self.gil()))
}
})
}
@ -69,9 +69,9 @@ impl<'p> PyDict<'p> {
/// Gets an item from the dictionary.
/// Returns None if the item is not present, or if an error occurs.
pub fn get_item<K>(&self, key: K) -> Option<PyObject> where K: ToPyObject {
key.with_borrowed_ptr(self.token(), |key| unsafe {
key.with_borrowed_ptr(self.gil(), |key| unsafe {
PyObject::from_borrowed_ptr_or_opt(
self.token(), ffi::PyDict_GetItem(self.as_ptr(), key))
self.gil(), ffi::PyDict_GetItem(self.as_ptr(), key))
})
}
@ -80,19 +80,19 @@ impl<'p> PyDict<'p> {
pub fn set_item<K, V>(&self, key: K, value: V)
-> PyResult<()> where K: ToPyObject, V: ToPyObject {
key.with_borrowed_ptr(
self.token(), move |key|
value.with_borrowed_ptr(self.token(), |value| unsafe {
self.gil(), move |key|
value.with_borrowed_ptr(self.gil(), |value| unsafe {
err::error_on_minusone(
self.token(), ffi::PyDict_SetItem(self.as_ptr(), key, value))
self.gil(), ffi::PyDict_SetItem(self.as_ptr(), key, value))
}))
}
/// Deletes an item.
/// This is equivalent to the Python expression `del self[key]`.
pub fn del_item<K>(&self, key: K) -> PyResult<()> where K: ToPyObject {
key.with_borrowed_ptr(self.token(), |key| unsafe {
key.with_borrowed_ptr(self.gil(), |key| unsafe {
err::error_on_minusone(
self.token(), ffi::PyDict_DelItem(self.as_ptr(), key))
self.gil(), ffi::PyDict_DelItem(self.as_ptr(), key))
})
}
@ -109,7 +109,7 @@ impl<'p> PyDict<'p> {
// Note that we don't provide an iterator because
// PyDict_Next() is unsafe to use when the dictionary might be changed
// by other python code.
let token = self.token();
let token = self.gil();
let mut vec = Vec::with_capacity(self.len());
unsafe {
let mut pos = 0;
@ -151,21 +151,25 @@ impl <K, V> ToPyObject for collections::BTreeMap<K, V>
#[cfg(test)]
mod test {
use python::{Python, PythonObjectWithCheckedDowncast};
use conversion::ToPyObject;
use objects::{PyDict, PyTuple};
use std::collections::{BTreeMap, HashMap};
use python::{Python};
use conversion::ToPyObject;
use objects::{PyDict}; //, PyTuple};
use ::PyDowncastFrom;
#[test]
fn test_len() {
let gil = Python::acquire_gil();
let py = gil.python();
let mut v = HashMap::new();
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert_eq!(0, dict.len(py));
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(py)).unwrap();
assert_eq!(0, dict.len());
v.insert(7, 32);
let dict2 = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert_eq!(1, dict2.len(py));
let ob = v.to_object(py);
let dict2 = PyDict::downcast_from(ob.as_object(py)).unwrap();
assert_eq!(1, dict2.len());
}
#[test]
@ -174,9 +178,10 @@ mod test {
let py = gil.python();
let mut v = HashMap::new();
v.insert(7, 32);
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert_eq!(true, dict.contains(py, 7i32).unwrap());
assert_eq!(false, dict.contains(py, 8i32).unwrap());
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(py)).unwrap();
assert_eq!(true, dict.contains(7i32).unwrap());
assert_eq!(false, dict.contains(8i32).unwrap());
}
#[test]
@ -185,9 +190,10 @@ mod test {
let py = gil.python();
let mut v = HashMap::new();
v.insert(7, 32);
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert_eq!(32, dict.get_item(py, 7i32).unwrap().extract::<i32>(py).unwrap());
assert_eq!(None, dict.get_item(py, 8i32));
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(py)).unwrap();
assert_eq!(32, dict.get_item(7i32).unwrap().extract::<i32>().unwrap());
assert_eq!(None, dict.get_item(8i32));
}
#[test]
@ -196,11 +202,12 @@ mod test {
let py = gil.python();
let mut v = HashMap::new();
v.insert(7, 32);
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert!(dict.set_item(py, 7i32, 42i32).is_ok()); // change
assert!(dict.set_item(py, 8i32, 123i32).is_ok()); // insert
assert_eq!(42i32, dict.get_item(py, 7i32).unwrap().extract::<i32>(py).unwrap());
assert_eq!(123i32, dict.get_item(py, 8i32).unwrap().extract::<i32>(py).unwrap());
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(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());
assert_eq!(123i32, dict.get_item(8i32).unwrap().extract::<i32>().unwrap());
}
#[test]
@ -209,9 +216,10 @@ mod test {
let py = gil.python();
let mut v = HashMap::new();
v.insert(7, 32);
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert!(dict.set_item(py, 7i32, 42i32).is_ok()); // change
assert!(dict.set_item(py, 8i32, 123i32).is_ok()); // insert
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(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!
assert_eq!(None, v.get(&8i32));
}
@ -223,10 +231,11 @@ mod test {
let py = gil.python();
let mut v = HashMap::new();
v.insert(7, 32);
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert!(dict.del_item(py, 7i32).is_ok());
assert_eq!(0, dict.len(py));
assert_eq!(None, dict.get_item(py, 7i32));
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(py)).unwrap();
assert!(dict.del_item(7i32).is_ok());
assert_eq!(0, dict.len());
assert_eq!(None, dict.get_item(7i32));
}
#[test]
@ -235,12 +244,13 @@ mod test {
let py = gil.python();
let mut v = HashMap::new();
v.insert(7, 32);
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
assert!(dict.del_item(py, 7i32).is_ok()); // change
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(py)).unwrap();
assert!(dict.del_item(7i32).is_ok()); // change
assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!
}
#[test]
/*#[test]
fn test_items_list() {
let gil = Python::acquire_gil();
let py = gil.python();
@ -259,7 +269,7 @@ mod test {
}
assert_eq!(7 + 8 + 9, key_sum);
assert_eq!(32 + 42 + 123, value_sum);
}
}*/
#[test]
fn test_items() {
@ -269,13 +279,14 @@ mod test {
v.insert(7, 32);
v.insert(8, 42);
v.insert(9, 123);
let dict = PyDict::downcast_from(py, v.to_py_object(py)).unwrap();
let ob = v.to_object(py);
let dict = PyDict::downcast_from(ob.as_object(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;
for (key, value) in dict.items(py) {
key_sum += key.extract::<i32>(py).unwrap();
value_sum += value.extract::<i32>(py).unwrap();
for (key, value) in dict.items() {
key_sum += key.extract::<i32>().unwrap();
value_sum += value.extract::<i32>().unwrap();
}
assert_eq!(7 + 8 + 9, key_sum);
assert_eq!(32 + 42 + 123, value_sum);
@ -289,12 +300,14 @@ mod test {
let mut map = HashMap::<i32, i32>::new();
map.insert(1, 1);
let py_map = PyDict::downcast_from(py, map.to_py_object(py)).unwrap();
let m = map.to_object(py);
let py_map = PyDict::downcast_from(m.as_object(py)).unwrap();
assert!(py_map.len(py) == 1);
assert!( py_map.get_item(py, 1).unwrap().extract::<i32>(py).unwrap() == 1);
assert!(py_map.len() == 1);
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
}
#[test]
fn test_btreemap_to_python() {
let gil = Python::acquire_gil();
let py = gil.python();
@ -302,9 +315,10 @@ mod test {
let mut map = BTreeMap::<i32, i32>::new();
map.insert(1, 1);
let py_map = PyDict::downcast_from(py, map.to_py_object(py)).unwrap();
let m = map.to_object(py);
let py_map = PyDict::downcast_from(m.as_object(py)).unwrap();
assert!(py_map.len(py) == 1);
assert!( py_map.get_item(py, 1).unwrap().extract::<i32>(py).unwrap() == 1);
assert!(py_map.len() == 1);
assert!( py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
}
}

View file

@ -20,12 +20,6 @@ pub use self::slice::PySlice;
macro_rules! pyobject_nativetype(
($name: ident, $checkfunction: ident, $typeobject: ident) => (
impl<'p> $crate::native::PyNativeObject for $name<'p> {
fn into_object(self) -> $crate::PyPtr<$crate::PyObjectMarker> {
unsafe { $crate::std::mem::transmute(self) }
}
}
impl<'p> $crate::typeob::PyTypeInfo for $name<'p> {
type Type = ();
@ -49,8 +43,19 @@ macro_rules! pyobject_nativetype(
}
}
impl<'p> $crate::token::PythonObjectWithToken for $name<'p> {
fn token<'a>(&'a self) -> $crate::python::Python<'a> {
impl<'p> $crate::native::PyBaseObject for $name<'p> {}
impl<'p> $crate::native::PyNativeObject<'p> for $name<'p> {
fn as_object(self) -> $crate::PyObject<'p> {
unsafe { $crate::std::mem::transmute(self) }
}
fn into_object(self) -> $crate::PyPtr<$crate::PyObjectMarker> {
unsafe { $crate::std::mem::transmute(self) }
}
}
impl<'p> $crate::token::PythonObjectWithGilToken<'p> for $name<'p> {
fn gil(&self) -> $crate::python::Python<'p> {
self.0.token()
}
}
@ -60,14 +65,14 @@ macro_rules! pyobject_nativetype(
fn downcast_from(py: &'p $crate::PyObject<'p>)
-> Result<&'p $name<'p>, $crate::PyDowncastError<'p>>
{
use $crate::{ToPythonPointer, PythonObjectWithToken};
use $crate::{ToPythonPointer, PythonObjectWithGilToken};
unsafe {
if $crate::ffi::$checkfunction(py.as_ptr()) > 0 {
let ptr = py as *const _ as *mut u8 as *mut $name;
Ok(ptr.as_ref().unwrap())
} else {
Err($crate::PyDowncastError(py.token(), None))
Err($crate::PyDowncastError(py.gil(), None))
}
}
}
@ -116,12 +121,11 @@ macro_rules! pyobject_nativetype(
{
/// Extracts `Self` from the source `Py<PyObject>`.
fn extract(py: &'a $crate::PyObject<'a>) -> $crate::PyResult<Self>
//where S: $crate::typeob::PyTypeInfo
{
use $crate::token::PythonObjectWithToken;
use $crate::token::PythonObjectWithGilToken;
Ok($name(
$crate::pptr::cast_from_borrowed_ptr::<$name>(py.token(), py.as_ptr())?))
$crate::pptr::cast_from_borrowed_ptr::<$name>(py.gil(), py.as_ptr())?))
}
}
@ -129,14 +133,13 @@ macro_rules! pyobject_nativetype(
{
/// Extracts `Self` from the source `PyObject`.
fn extract(py: &'a $crate::PyObject<'a>) -> $crate::PyResult<Self>
//where S: $crate::typeob::PyTypeInfo
{
unsafe {
if ffi::$checkfunction(py.as_ptr()) != 0 {
Ok($crate::std::mem::transmute(py))
} else {
Err($crate::PyDowncastError(
$crate::token::PythonObjectWithToken::token(py), None).into())
$crate::token::PythonObjectWithGilToken::gil(py), None).into())
}
}
}
@ -145,8 +148,8 @@ macro_rules! pyobject_nativetype(
impl<'a> $crate::ToPyObject for $name<'a>
{
#[inline]
default fn to_object<'p>(&self, _py: $crate::Python<'p>)
-> $crate::PyPtr<$crate::PyObjectMarker> {
fn to_object<'p>(&self, _py: $crate::Python<'p>)
-> $crate::PyPtr<$crate::PyObjectMarker> {
unsafe { $crate::PyPtr::from_borrowed_ptr(self.0.as_ptr()) }
}
@ -168,12 +171,12 @@ macro_rules! pyobject_nativetype(
}
impl<'p> $crate::std::fmt::Debug for $name<'p> {
default fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
-> Result<(), $crate::std::fmt::Error>
fn fmt(&self, f: &mut $crate::std::fmt::Formatter)
-> Result<(), $crate::std::fmt::Error>
{
use $crate::python::PyDowncastInto;
let py = <$name as $crate::token::PythonObjectWithToken>::token(self);
let py = <$name as $crate::token::PythonObjectWithGilToken>::gil(self);
let s = unsafe { $crate::PyString::downcast_from_owned_ptr(
py, $crate::ffi::PyObject_Repr(
$crate::python::ToPythonPointer::as_ptr(self))) };
@ -188,7 +191,7 @@ macro_rules! pyobject_nativetype(
{
use $crate::python::PyDowncastInto;
let py = <$name as $crate::token::PythonObjectWithToken>::token(self);
let py = <$name as $crate::token::PythonObjectWithGilToken>::gil(self);
let s = unsafe { $crate::PyString::downcast_from_owned_ptr(
py, $crate::ffi::PyObject_Str(
$crate::python::ToPythonPointer::as_ptr(self))) };

View file

@ -10,7 +10,7 @@ use std::ffi::{CStr, CString};
use ::pptr;
use pyptr::PyPtr;
use python::{ToPythonPointer, Python};
use token::PythonObjectWithToken;
use token::PythonObjectWithGilToken;
use objects::{PyDict, PyType, exc};
use objectprotocol::ObjectProtocol;
use err::{PyResult, PyErr};
@ -53,14 +53,14 @@ impl<'p> PyModule<'p> {
unsafe fn str_from_ptr<'a>(&'a self, ptr: *const c_char) -> PyResult<&'a str> {
if ptr.is_null() {
Err(PyErr::fetch(self.token()))
Err(PyErr::fetch(self.gil()))
} else {
let slice = CStr::from_ptr(ptr).to_bytes();
match std::str::from_utf8(slice) {
Ok(s) => Ok(s),
Err(e) => Err(PyErr::from_instance(
self.token(),
try!(exc::UnicodeDecodeError::new_utf8(self.token(), slice, e))))
self.gil(),
try!(exc::UnicodeDecodeError::new_utf8(self.gil(), slice, e))))
}
}
}
@ -91,15 +91,15 @@ impl<'p> PyModule<'p> {
let type_name = <T as ::typeob::PyTypeInfo>::type_name();
let ty = if (ty.tp_flags & ffi::Py_TPFLAGS_READY) != 0 {
unsafe { PyType::from_type_ptr(self.token(), ty) }
unsafe { PyType::from_type_ptr(self.gil(), ty) }
} else {
// automatically initialize the class
let name = self.name()?;
::typeob::initialize_type::<T>(self.token(), Some(name), type_name, ty)
::typeob::initialize_type::<T>(self.gil(), Some(name), type_name, ty)
.expect(
format!("An error occurred while initializing class {}",
<T as ::typeob::PyTypeInfo>::type_name()).as_ref());
unsafe { PyType::from_type_ptr(self.token(), ty) }
unsafe { PyType::from_type_ptr(self.gil(), ty) }
};
self.setattr(type_name, ty)

View file

@ -11,7 +11,7 @@ use ::{PyPtr, pptr};
use ffi;
use super::exc;
use objects::PyObject;
use token::{PyObjectMarker, PythonObjectWithToken};
use token::{PyObjectMarker, PythonObjectWithGilToken};
use python::{ToPythonPointer, Python};
use err::{PyResult, PyErr};
use conversion::{ToPyObject, FromPyObject, IntoPyObject};
@ -62,12 +62,12 @@ macro_rules! int_fits_c_long(
pyobject_extract!(obj to $rust_type => {
let val = unsafe { ffi::PyLong_AsLong(obj.as_ptr()) };
if val == -1 && PyErr::occurred(obj.token()) {
return Err(PyErr::fetch(obj.token()));
if val == -1 && PyErr::occurred(obj.gil()) {
return Err(PyErr::fetch(obj.gil()));
}
match cast::<c_long, $rust_type>(val) {
Some(v) => Ok(v),
None => Err(overflow_error(obj.token()))
None => Err(overflow_error(obj.gil()))
}
});
)
@ -84,7 +84,7 @@ macro_rules! int_fits_larger_int(
}
pyobject_extract!(obj to $rust_type => {
let py = obj.token();
let py = obj.gil();
let val = try!(obj.extract::<$larger_type>());
match cast::<$larger_type, $rust_type>(val) {
Some(v) => Ok(v),
@ -123,13 +123,13 @@ macro_rules! int_convert_u64_or_i64 (
let ptr = py.as_ptr();
unsafe {
if ffi::PyLong_Check(ptr) != 0 {
err_if_invalid_value(py.token(), !0, $pylong_as_ull_or_ull(ptr))
err_if_invalid_value(py.gil(), !0, $pylong_as_ull_or_ull(ptr))
} else {
let num = ffi::PyNumber_Long(ptr);
if num.is_null() {
Err(PyErr::fetch(py.token()))
Err(PyErr::fetch(py.gil()))
} else {
err_if_invalid_value(py.token(), !0, $pylong_as_ull_or_ull(num))
err_if_invalid_value(py.gil(), !0, $pylong_as_ull_or_ull(num))
}
}
}
@ -176,8 +176,8 @@ impl ToPyObject for f64 {
pyobject_extract!(obj to f64 => {
let v = unsafe { ffi::PyFloat_AsDouble(obj.as_ptr()) };
if v == -1.0 && PyErr::occurred(obj.token()) {
Err(PyErr::fetch(obj.token()))
if v == -1.0 && PyErr::occurred(obj.gil()) {
Err(PyErr::fetch(obj.gil()))
} else {
Ok(v)
}
@ -210,8 +210,8 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let val = 123 as $t1;
let obj = val.to_object(py).into_object();
assert_eq!(obj.extract::<$t2>(py).unwrap(), val as $t2);
let obj = val.to_object(py).into_object(py);
assert_eq!(obj.extract::<$t2>().unwrap(), val as $t2);
}
)
);
@ -239,10 +239,10 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let v = std::u32::MAX;
let obj = v.to_py_object(py).into_object();
assert_eq!(v, obj.extract::<u32>(py).unwrap());
assert_eq!(v as u64, obj.extract::<u64>(py).unwrap());
assert!(obj.extract::<i32>(py).is_err());
let obj = v.to_object(py).into_object(py);
assert_eq!(v, obj.extract::<u32>().unwrap());
assert_eq!(v as u64, obj.extract::<u64>().unwrap());
assert!(obj.extract::<i32>().is_err());
}
#[test]
@ -250,10 +250,10 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let v = std::i64::MAX;
let obj = v.to_py_object(py).into_object();
assert_eq!(v, obj.extract::<i64>(py).unwrap());
assert_eq!(v as u64, obj.extract::<u64>(py).unwrap());
assert!(obj.extract::<u32>(py).is_err());
let obj = v.to_object(py).into_object(py);
assert_eq!(v, obj.extract::<i64>().unwrap());
assert_eq!(v as u64, obj.extract::<u64>().unwrap());
assert!(obj.extract::<u32>().is_err());
}
#[test]
@ -261,10 +261,10 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let v = std::i64::MIN;
let obj = v.to_py_object(py).into_object();
assert_eq!(v, obj.extract::<i64>(py).unwrap());
assert!(obj.extract::<i32>(py).is_err());
assert!(obj.extract::<u64>(py).is_err());
let obj = v.to_object(py).into_object(py);
assert_eq!(v, obj.extract::<i64>().unwrap());
assert!(obj.extract::<i32>().is_err());
assert!(obj.extract::<u64>().is_err());
}
#[test]
@ -272,9 +272,8 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let v = std::u64::MAX;
let obj = v.to_py_object(py).into_object();
println!("{:?}", obj);
assert_eq!(v, obj.extract::<u64>(py).unwrap());
assert!(obj.extract::<i64>(py).is_err());
let obj = v.to_object(py).into_object(py);
assert_eq!(v, obj.extract::<u64>().unwrap());
assert!(obj.extract::<i64>().is_err());
}
}

View file

@ -6,8 +6,6 @@ use ::pptr;
use ffi;
use err::{PyResult, PyDowncastError};
use python::{Python, ToPythonPointer};
use token::PythonObjectWithToken;
use typeob::PyTypeInfo;
pub struct PyObject<'p>(pptr<'p>);
@ -69,8 +67,6 @@ impl<'p> PyObject<'p> {
/// Fails with `PyDowncastError` if the object is not of the expected type.
#[inline]
pub fn cast_as<D>(&'p self) -> Result<&'p D, PyDowncastError<'p>>
//where D: PyTypeInfo
//{
where D: ::PyDowncastFrom<'p>
{
<D as ::PyDowncastFrom>::downcast_from(&self)

View file

@ -8,7 +8,7 @@ use python::{ToPythonPointer, Python};
use err::{PyErr, PyResult};
use ffi::{self, Py_ssize_t};
use conversion::{ToPyObject, IntoPyObject};
use token::{PyObjectMarker, PythonObjectWithToken};
use token::{PyObjectMarker, PythonObjectWithGilToken};
/// Represents a Python `slice` indices
pub struct PySliceIndices {
@ -71,7 +71,7 @@ impl<'p> PySlice<'p> {
slicelength: slicelen,
})
} else {
Err(PyErr::fetch(self.token()))
Err(PyErr::fetch(self.gil()))
}
}
}

View file

@ -8,11 +8,11 @@ use std::ascii::AsciiExt;
use std::borrow::Cow;
use std::os::raw::c_char;
use ::{Py, PyPtr, pptr};
use ::{PyPtr, pptr};
use ffi;
use python::{ToPythonPointer, Python};
use super::{exc, PyObject};
use token::{PyObjectMarker, PythonObjectWithToken};
use token::{PyObjectMarker, PythonObjectWithGilToken};
use err::{PyResult, PyErr};
use conversion::{ToPyObject, IntoPyObject, RefFromPyObject};
@ -153,7 +153,7 @@ impl<'p> PyString<'p> {
unsafe {
Ok(PyString(
pptr::from_owned_ptr_or_err(
src.token(), ffi::PyUnicode_FromEncodedObject(
src.gil(), ffi::PyUnicode_FromEncodedObject(
src.as_ptr(),
encoding.as_ptr() as *const i8,
errors.as_ptr() as *const i8))?))
@ -168,7 +168,7 @@ impl<'p> PyString<'p> {
let mut size : ffi::Py_ssize_t = mem::uninitialized();
let data = ffi::PyUnicode_AsUTF8AndSize(self.0.as_ptr(), &mut size) as *const u8;
if data.is_null() {
PyErr::fetch(self.token()).print(self.token());
PyErr::fetch(self.gil()).print(self.gil());
panic!("PyUnicode_AsUTF8AndSize failed");
}
PyStringData::Utf8(std::slice::from_raw_parts(data, size as usize))
@ -180,7 +180,7 @@ impl<'p> PyString<'p> {
/// Returns a `UnicodeDecodeError` if the input is not valid unicode
/// (containing unpaired surrogates).
pub fn to_string(&self) -> PyResult<Cow<str>> {
self.data().to_string(self.token())
self.data().to_string(self.gil())
}
/// Convert the `PyString` into a Rust string.
@ -259,10 +259,10 @@ pyobject_extract!(obj to String => {
impl<'p> RefFromPyObject<'p> for str {
fn with_extracted<F, R>(obj: &'p Py<'p, PyObject>, f: F) -> PyResult<R>
fn with_extracted<F, R>(obj: &'p PyObject, f: F) -> PyResult<R>
where F: FnOnce(&str) -> R
{
let p = PyObject::from_borrowed_ptr(obj.token(), obj.as_ptr());
let p = PyObject::from_borrowed_ptr(obj.gil(), obj.as_ptr());
let s = try!(p.extract::<Cow<str>>());
Ok(f(&s))
}
@ -278,8 +278,8 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let s = "\u{1F30F}";
let py_string = s.to_py_object(py).into_object();
assert_eq!(s, py_string.extract::<String>(py).unwrap());
let py_string = s.to_object(py);
assert_eq!(s, py_string.as_object(py).extract::<String>().unwrap());
}
#[test]
@ -287,9 +287,9 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let s = "Hello Python";
let py_string = s.to_py_object(py).into_object();
let py_string = s.to_object(py);
let mut called = false;
RefFromPyObject::with_extracted(py, &py_string,
RefFromPyObject::with_extracted(&py_string.as_object(py),
|s2: &str| {
assert_eq!(s, s2);
called = true;

View file

@ -10,7 +10,7 @@ use err::{PyErr, PyResult};
use python::{Python, ToPythonPointer, IntoPythonPointer};
use conversion::{FromPyObject, ToPyObject, ToPyTuple, IntoPyObject};
use objects::PyObject;
use token::{PyObjectMarker, PythonObjectWithToken};
use token::{PyObjectMarker, PythonObjectWithGilToken};
use super::exc;
/// Represents a Python tuple object.
@ -63,7 +63,7 @@ impl<'p> PyTuple<'p> {
assert!(index < self.len());
unsafe {
PyObject::from_owned_ptr(
self.token(), ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
self.gil(), ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t))
}
}
@ -134,7 +134,7 @@ macro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+
$( try!(slice[$n].extract::<$T>()), )+
))
} else {
Err(wrong_tuple_length(obj.token(), t, $length))
Err(wrong_tuple_length(obj.gil(), t, $length))
}
}
}
@ -202,7 +202,7 @@ pyobject_extract!(obj to NoArgs => {
if t.len() == 0 {
Ok(NoArgs)
} else {
Err(wrong_tuple_length(obj.token(), t, 0))
Err(wrong_tuple_length(obj.gil(), t, 0))
}
});
@ -210,16 +210,17 @@ pyobject_extract!(obj to NoArgs => {
#[cfg(test)]
mod test {
use PyTuple;
use python::{Python, PythonObjectWithCheckedDowncast};
use python::{Python, PyDowncastInto};
use conversion::IntoPyObject;
use conversion::ToPyObject;
#[test]
fn test_len() {
let gil = Python::acquire_gil();
let py = gil.python();
let tuple = PyTuple::downcast_from(py, (1, 2, 3).to_py_object(py)).unwrap();
assert_eq!(3, tuple.len(py));
assert_eq!((1, 2, 3), tuple.into_object().extract(py).unwrap());
let tuple = PyTuple::downcast_into(py, (1, 2, 3).to_object(py).into_object(py)).unwrap();
assert_eq!(3, tuple.len());
assert_eq!((1, 2, 3), tuple.into_object(py).as_object(py).extract().unwrap());
}
}

View file

@ -7,7 +7,7 @@ use std::borrow::Cow;
use ::pptr;
use ffi;
use token::PythonObjectWithToken;
use token::PythonObjectWithGilToken;
use python::{Python, ToPythonPointer};
use conversion::ToPyTuple;
use objects::{PyObject, PyDict};
@ -59,10 +59,10 @@ impl<'p> PyType<'p> {
pub fn call<A>(&'p self, args: A, kwargs: Option<&PyDict>) -> PyResult<PyObject<'p>>
where A: ToPyTuple
{
let args = args.to_py_tuple(self.token());
let args = args.to_py_tuple(self.gil());
unsafe {
PyObject::from_owned_ptr_or_err(
self.token(), ffi::PyObject_Call(self.as_ptr(), args.as_ptr(), kwargs.as_ptr()))
self.gil(), ffi::PyObject_Call(self.as_ptr(), args.as_ptr(), kwargs.as_ptr()))
}
}
}

View file

@ -5,7 +5,7 @@ use err::{PyErr, PyResult};
use python::{Python, ToPythonPointer};
use typeob::{PyTypeInfo, PyObjectAlloc};
#[allow(non_camel_case_types)]
pub struct pptr<'p>(Python<'p>, *mut ffi::PyObject);

View file

@ -10,7 +10,7 @@ use err::{PyErr, PyResult, PyDowncastError};
use conversion::{ToPyObject, IntoPyObject};
use objects::PyObject;
use python::{Python, ToPythonPointer, IntoPythonPointer};
use token::{PyObjectMarker, PythonObjectWithToken};
use token::{PyObjectMarker, PythonObjectWithGilToken};
use typeob::{PyTypeInfo, PyObjectAlloc};
@ -104,12 +104,25 @@ impl<T> PyPtr<T> {
/// Converts PyPtr<T> -> PyPtr<PyObject>
/// Consumes `self` without calling `Py_INCREF()`
#[inline]
pub fn into_object(self) -> PyPtr<PyObjectMarker> {
pub fn park(self) -> PyPtr<PyObjectMarker> {
let p = PyPtr {inner: self.inner, _t: PhantomData};
std::mem::forget(self);
p
}
/// Converts PyPtr<T> -> &PyObject<'p>.
#[inline]
pub fn as_object<'p>(&self, _py: Python<'p>) -> &PyObject<'p> {
unsafe { std::mem::transmute(self) }
}
/// Converts PyPtr<T> -> PyObject<'p>
/// Consumes `self` without calling `Py_DECREF()`
#[inline]
pub fn into_object<'p>(self, _py: Python<'p>) -> PyObject<'p> {
unsafe { std::mem::transmute(self) }
}
/// Gets the reference count of this PyPtr object.
#[inline]
pub fn get_refcnt(&self) -> usize {
@ -171,7 +184,7 @@ impl<T> IntoPyObject for PyPtr<T> {
#[inline]
fn into_object<'a>(self, _py: Python) -> PyPtr<PyObjectMarker> {
self.into_object()
self.park()
}
}
@ -326,12 +339,14 @@ impl<'p, T> Py<'p, T>
res
}
#[inline]
pub fn clone_ref(&self) -> Py<'p, T> {
unsafe { ffi::Py_INCREF(self.inner) };
Py {inner: self.inner, _t: self._t, py: self.py}
}
pub fn token<'a>(&'a self) -> Python<'p> {
#[inline]
pub fn gil(&self) -> Python<'p> {
self.py
}
}
@ -375,6 +390,7 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
}
}
#[inline]
pub fn cast_from_owned_or_err(py: Python<'p>, ptr: *mut ffi::PyObject)
-> PyResult<Py<'p, T>>
{
@ -460,7 +476,7 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
let ptr = (self.inner as *mut u8).offset(offset) as *mut D;
ptr.as_ref().unwrap() })
} else {
Err(PyDowncastError(self.token(), None))
Err(PyDowncastError(self.py, None))
}
}
@ -483,8 +499,8 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
}
}
//impl<'p, T> PythonObjectWithToken for Py<'p, T> {
// fn token(&self) -> Token {
//impl<'p, T> PythonObjectWithGilToken<'p> for Py<'p, T> {
// fn gil(&self) -> Python<'p> {
// self.py
// }
//}
@ -575,14 +591,13 @@ impl<'source, T> ::FromPyObject<'source> for Py<'source, T> where T: PyTypeInfo
{
#[inline]
default fn extract(py: &'source PyObject<'source>) -> PyResult<Py<'source, T>>
// where S: PyTypeInfo
{
let ptr = py.as_ptr();
let checked = unsafe { ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 };
if checked {
Ok( unsafe { Py::<T>::from_borrowed_ptr(py.token(), ptr) })
Ok( unsafe { Py::<T>::from_borrowed_ptr(py.gil(), ptr) })
} else {
Err(PyDowncastError(py.token(), None).into())
Err(PyDowncastError(py.gil(), None).into())
}
}
}

View file

@ -9,7 +9,7 @@ use std::os::raw::c_int;
use ffi;
use typeob::{PyTypeInfo, PyTypeObject, PyObjectAlloc};
use token::{PyObjectMarker, PythonToken, PythonObjectWithToken};
use token::{PyObjectMarker, PythonToken, PythonObjectWithGilToken};
use objects::{PyObject, PyType, PyBool, PyDict, PyModule};
use err::{PyErr, PyResult, PyDowncastError};
use pyptr::{Py, PyPtr};
@ -73,16 +73,6 @@ pub trait ToPythonPointer {
}
impl<'p, T> ToPythonPointer for T where T: PyTypeInfo + PythonObjectWithToken {
#[inline]
default fn as_ptr(&self) -> *mut ffi::PyObject {
let offset = <T as PyTypeInfo>::offset();
unsafe {
{self as *const _ as *mut u8}.offset(-offset) as *mut ffi::PyObject
}
}
}
/// This trait allows retrieving the underlying FFI pointer from Python objects.
pub trait IntoPythonPointer {
/// Retrieves the underlying FFI pointer. Whether pointer owned or borrowed
@ -94,7 +84,7 @@ pub trait IntoPythonPointer {
/// Convert None into a null pointer.
/*impl <T> ToPythonPointer for Option<T> where T: ToPythonPointer {
#[inline]
fn as_ptr(&self) -> *mut ffi::PyObject {
default fn as_ptr(&self) -> *mut ffi::PyObject {
match *self {
Some(ref t) => t.as_ptr(),
None => std::ptr::null_mut()
@ -105,7 +95,7 @@ pub trait IntoPythonPointer {
/// Convert None into a null pointer.
impl<'p, T> ToPythonPointer for Option<&'p T> where T: ToPythonPointer {
#[inline]
fn as_ptr(&self) -> *mut ffi::PyObject {
default fn as_ptr(&self) -> *mut ffi::PyObject {
match *self {
Some(ref t) => t.as_ptr(),
None => std::ptr::null_mut()
@ -303,18 +293,18 @@ mod test {
let py = gil.python();
// Make sure builtin names are accessible
let v: i32 = py.eval("min(1, 2)", None, None).unwrap().extract(py).unwrap();
let v: i32 = py.eval("min(1, 2)", None, None).unwrap().extract().unwrap();
assert_eq!(v, 1);
let d = PyDict::new(py);
d.set_item(py, "foo", 13).unwrap();
d.set_item("foo", 13).unwrap();
// Inject our own local namespace
let v: i32 = py.eval("foo + 29", None, Some(&d)).unwrap().extract(py).unwrap();
let v: i32 = py.eval("foo + 29", None, Some(&d)).unwrap().extract().unwrap();
assert_eq!(v, 42);
// Make sure builtin names are still accessible when using a local namespace
let v: i32 = py.eval("min(foo, 2)", None, Some(&d)).unwrap().extract(py).unwrap();
let v: i32 = py.eval("min(foo, 2)", None, Some(&d)).unwrap().extract().unwrap();
assert_eq!(v, 2);
}
}

View file

@ -33,15 +33,16 @@ pub fn with_token<'p, T, F>(py: Python<'p>, f: F) -> Py<'p, T>
}
pub trait PythonObjectWithGilToken<'p> : Sized {
fn gil(&self) -> Python<'p>;
}
pub trait PythonObjectWithToken : Sized {
fn token<'p>(&'p self) -> Python<'p>;
}
pub struct PyObjectMarker;
//pyobject_newtype!(PyObject, PyObject_Check, PyBaseObject_Type);
impl PyObjectMarker {

View file

@ -1,7 +1,7 @@
#![allow(dead_code, unused_variables)]
#![feature(proc_macro, specialization)]
#[macro_use] extern crate pyo3;
extern crate pyo3;
use std::ptr;
use std::os::raw::{c_int, c_void};

View file

@ -804,8 +804,8 @@ impl PyObjectProtocol for RichComparisons2 {
fn __richcmp__(&self, py: Python,
other: &'p PyObject<'p>, op: CompareOp) -> PyResult<PyPtr<PyObjectMarker>> {
match op {
CompareOp::Eq => Ok(true.to_object(py).into_object()),
CompareOp::Ne => Ok(false.to_object(py).into_object()),
CompareOp::Eq => Ok(true.to_object(py).park()),
CompareOp::Ne => Ok(false.to_object(py).park()),
_ => Ok(py.NotImplemented())
}
}

View file

@ -17,16 +17,16 @@ fn no_args() {
let obj = py_fn!(py, f());
assert_eq!(CALL_COUNT.load(Relaxed), 0);
assert_eq!(obj.call(py, NoArgs, None).unwrap().extract::<i32>(py).unwrap(), 0);
assert_eq!(obj.call(py, NoArgs, None).unwrap().extract::<i32>(py).unwrap(), 1);
assert_eq!(obj.call(NoArgs, None).unwrap().extract::<i32>().unwrap(), 0);
assert_eq!(obj.call(NoArgs, None).unwrap().extract::<i32>().unwrap(), 1);
assert_eq!(CALL_COUNT.load(Relaxed), 2);
assert!(obj.call(py, (1,), None).is_err());
assert!(obj.call((1,), None).is_err());
assert_eq!(CALL_COUNT.load(Relaxed), 2);
assert_eq!(obj.call(py, NoArgs, Some(&PyDict::new(py))).unwrap().extract::<i32>(py).unwrap(), 2);
assert_eq!(obj.call(NoArgs, Some(&PyDict::new(py))).unwrap().extract::<i32>().unwrap(), 2);
assert_eq!(CALL_COUNT.load(Relaxed), 3);
let dict = PyDict::new(py);
dict.set_item(py, "param", 42).unwrap();
assert!(obj.call(py, NoArgs, Some(&dict)).is_err());
dict.set_item("param", 42).unwrap();
assert!(obj.call(NoArgs, Some(&dict)).is_err());
assert_eq!(CALL_COUNT.load(Relaxed), 3);
}
@ -40,16 +40,16 @@ fn one_arg() {
let py = gil.python();
let obj = py_fn!(py, f(i: usize));
assert!(obj.call(py, NoArgs, None).is_err());
assert_eq!(obj.call(py, (1,), None).unwrap().extract::<i32>(py).unwrap(), 2);
assert!(obj.call(py, (1, 2), None).is_err());
assert!(obj.call(NoArgs, None).is_err());
assert_eq!(obj.call((1,), None).unwrap().extract::<i32>().unwrap(), 2);
assert!(obj.call((1, 2), None).is_err());
let dict = PyDict::new(py);
dict.set_item(py, "i", 42).unwrap();
assert_eq!(obj.call(py, NoArgs, Some(&dict)).unwrap().extract::<i32>(py).unwrap(), 84);
assert!(obj.call(py, (1,), Some(&dict)).is_err());
dict.set_item(py, "j", 10).unwrap();
assert!(obj.call(py, NoArgs, Some(&dict)).is_err());
dict.set_item("i", 42).unwrap();
assert_eq!(obj.call(NoArgs, Some(&dict)).unwrap().extract::<i32>().unwrap(), 84);
assert!(obj.call((1,), Some(&dict)).is_err());
dict.set_item("j", 10).unwrap();
assert!(obj.call(NoArgs, Some(&dict)).is_err());
}
#[test]
@ -61,8 +61,8 @@ fn inline_two_args() {
Ok(a * b)
});
assert!(obj.call(py, NoArgs, None).is_err());
assert_eq!(obj.call(py, (6, 7), None).unwrap().extract::<i32>(py).unwrap(), 42);
assert!(obj.call(NoArgs, None).is_err());
assert_eq!(obj.call((6, 7), None).unwrap().extract::<i32>().unwrap(), 42);
}
/* TODO: reimplement flexible sig support