Remove many specialization uses

From over a hundret "default fn" uses down to 17
This commit is contained in:
konstin 2018-08-25 20:47:30 +02:00
parent 33e72a2b03
commit 7c0379b13a
34 changed files with 526 additions and 1037 deletions

View File

@ -8,8 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Changed ### Changed
* Slowly removing specialization uses
* All exceptions are consturcted with `py_err` instead of `new`, as they return `PyErr` and not `Self`. * All exceptions are consturcted with `py_err` instead of `new`, as they return `PyErr` and not `Self`.
* `as_mut` and friends take and `&mut self` instead of `&self` * `as_mut` and friends take and `&mut self` instead of `&self`
* `ObjectProtocol::call` now takes an `Option<PyDict>` for the kwargs instead of an `IntoPyDictPointer`.
* `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`.
### Fixed ### Fixed

View File

@ -76,11 +76,8 @@ fn main() {
} }
``` ```
`kwargs` argument is generate over `kwargs` can by `None` or `Some(PyDict)`. You can use the
[`IntoPyDictPointer`][IntoPyDictPointer] trait. `HashMap` or `BTreeMap` could be used as [`IntoPyDict`][IntoPyDict] trait to convert other dict-like containers, e.g. `HashMap`, `BTreeMap` as well as tuples with up to 10 elements and `Vec`s where each element is a two element tuple.
keyword arguments. rust tuple with up to 10 elements where each element is tuple with size 2
could be used as kwargs as well. Or `NoArgs` object can be used to indicate that
no keywords arguments are provided.
```rust ```rust
extern crate pyo3; extern crate pyo3;
@ -130,4 +127,4 @@ TODO
[IntoPyTuple]: https://docs.rs/pyo3/0.2.7/trait.IntoPyTuple.html [IntoPyTuple]: https://docs.rs/pyo3/0.2.7/trait.IntoPyTuple.html
[PyTuple]: https://docs.rs/pyo3/0.2.7/struct.PyTuple.html [PyTuple]: https://docs.rs/pyo3/0.2.7/struct.PyTuple.html
[ObjectProtocol]: https://docs.rs/pyo3/0.2.7/trait.ObjectProtocol.html [ObjectProtocol]: https://docs.rs/pyo3/0.2.7/trait.ObjectProtocol.html
[IntoPyDictPointer]: https://docs.rs/pyo3/0.2.7/trait.IntoPyDictPointer.html [IntoPyDict]: https://docs.rs/pyo3/0.2.7/trait.IntoPyDict.html

View File

@ -720,7 +720,7 @@ mod test {
let array = py let array = py
.import("array") .import("array")
.unwrap() .unwrap()
.call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), ::NoArgs) .call_method("array", ("f", (1.0, 1.5, 2.0, 2.5)), None)
.unwrap(); .unwrap();
let buffer = PyBuffer::get(py, array.into()).unwrap(); let buffer = PyBuffer::get(py, array.into()).unwrap();
assert_eq!(buffer.dimensions(), 1); assert_eq!(buffer.dimensions(), 1);

View File

@ -91,24 +91,18 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
#[cfg(Py_3)] #[cfg(Py_3)]
#[doc(hidden)] #[doc(hidden)]
pub trait PyAsyncProtocolImpl { pub trait PyAsyncProtocolImpl {
fn tp_as_async() -> Option<ffi::PyAsyncMethods>; fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
fn methods() -> Vec<PyMethodDef>;
}
#[cfg(Py_3)]
impl<T> PyAsyncProtocolImpl for T {
#[inline]
default fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
None None
} }
#[inline] fn methods() -> Vec<PyMethodDef> {
default fn methods() -> Vec<PyMethodDef> {
Vec::new() Vec::new()
} }
} }
#[cfg(Py_3)]
impl<T> PyAsyncProtocolImpl for T {}
#[cfg(Py_3)] #[cfg(Py_3)]
impl<'p, T> PyAsyncProtocolImpl for T impl<'p, T> PyAsyncProtocolImpl for T
where where
@ -139,19 +133,13 @@ where
} }
trait PyAsyncAwaitProtocolImpl { trait PyAsyncAwaitProtocolImpl {
fn am_await() -> Option<ffi::unaryfunc>; fn am_await() -> Option<ffi::unaryfunc> {
}
impl<'p, T> PyAsyncAwaitProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn am_await() -> Option<ffi::unaryfunc> {
None None
} }
} }
impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
impl<T> PyAsyncAwaitProtocolImpl for T impl<T> PyAsyncAwaitProtocolImpl for T
where where
T: for<'p> PyAsyncAwaitProtocol<'p>, T: for<'p> PyAsyncAwaitProtocol<'p>,
@ -168,19 +156,13 @@ where
} }
trait PyAsyncAiterProtocolImpl { trait PyAsyncAiterProtocolImpl {
fn am_aiter() -> Option<ffi::unaryfunc>; fn am_aiter() -> Option<ffi::unaryfunc> {
}
impl<'p, T> PyAsyncAiterProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn am_aiter() -> Option<ffi::unaryfunc> {
None None
} }
} }
impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
impl<T> PyAsyncAiterProtocolImpl for T impl<T> PyAsyncAiterProtocolImpl for T
where where
T: for<'p> PyAsyncAiterProtocol<'p>, T: for<'p> PyAsyncAiterProtocol<'p>,
@ -197,19 +179,13 @@ where
} }
trait PyAsyncAnextProtocolImpl { trait PyAsyncAnextProtocolImpl {
fn am_anext() -> Option<ffi::unaryfunc>; fn am_anext() -> Option<ffi::unaryfunc> {
}
impl<'p, T> PyAsyncAnextProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn am_anext() -> Option<ffi::unaryfunc> {
None None
} }
} }
impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {}
#[cfg(Py_3)] #[cfg(Py_3)]
mod anext { mod anext {
use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl}; use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
@ -260,29 +236,17 @@ mod anext {
} }
trait PyAsyncAenterProtocolImpl { trait PyAsyncAenterProtocolImpl {
fn __aenter__() -> Option<PyMethodDef>; fn __aenter__() -> Option<PyMethodDef> {
}
impl<'p, T> PyAsyncAenterProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn __aenter__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
trait PyAsyncAexitProtocolImpl { trait PyAsyncAexitProtocolImpl {
fn __aexit__() -> Option<PyMethodDef>; fn __aexit__() -> Option<PyMethodDef> {
}
impl<'p, T> PyAsyncAexitProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn __aexit__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyAsyncAexitProtocolImpl for T where T: PyAsyncProtocol<'p> {}

View File

@ -150,26 +150,21 @@ pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
#[doc(hidden)] #[doc(hidden)]
pub trait PyObjectProtocolImpl { pub trait PyObjectProtocolImpl {
fn methods() -> Vec<PyMethodDef>; fn methods() -> Vec<PyMethodDef> {
fn tp_as_object(type_object: &mut ffi::PyTypeObject);
fn nb_bool_fn() -> Option<ffi::inquiry>;
}
impl<T> PyObjectProtocolImpl for T {
default fn methods() -> Vec<PyMethodDef> {
Vec::new() Vec::new()
} }
default fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {} fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
default fn nb_bool_fn() -> Option<ffi::inquiry> { fn nb_bool_fn() -> Option<ffi::inquiry> {
None None
} }
} }
impl<T> PyObjectProtocolImpl for T {}
impl<'p, T> PyObjectProtocolImpl for T impl<'p, T> PyObjectProtocolImpl for T
where where
T: PyObjectProtocol<'p>, T: PyObjectProtocol<'p>,
{ {
#[inline]
fn methods() -> Vec<PyMethodDef> { fn methods() -> Vec<PyMethodDef> {
let mut methods = Vec::new(); let mut methods = Vec::new();
@ -203,22 +198,15 @@ where
} }
trait PyObjectGetAttrProtocolImpl { trait PyObjectGetAttrProtocolImpl {
fn tp_getattro() -> Option<ffi::binaryfunc>; fn tp_getattro() -> Option<ffi::binaryfunc> {
}
impl<'p, T> PyObjectGetAttrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_getattro() -> Option<ffi::binaryfunc> {
None None
} }
} }
impl<'p, T> PyObjectGetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectGetAttrProtocolImpl for T impl<T> PyObjectGetAttrProtocolImpl for T
where where
T: for<'p> PyObjectGetAttrProtocol<'p>, T: for<'p> PyObjectGetAttrProtocol<'p>,
{ {
#[inline]
fn tp_getattro() -> Option<ffi::binaryfunc> { fn tp_getattro() -> Option<ffi::binaryfunc> {
py_binary_func!( py_binary_func!(
PyObjectGetAttrProtocol, PyObjectGetAttrProtocol,
@ -230,45 +218,31 @@ where
} }
trait PyObjectSetAttrProtocolImpl { trait PyObjectSetAttrProtocolImpl {
fn tp_setattro() -> Option<ffi::setattrofunc>; fn tp_setattro() -> Option<ffi::setattrofunc> {
}
impl<'p, T> PyObjectSetAttrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_setattro() -> Option<ffi::setattrofunc> {
None None
} }
} }
impl<'p, T> PyObjectSetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectSetAttrProtocolImpl for T impl<T> PyObjectSetAttrProtocolImpl for T
where where
T: for<'p> PyObjectSetAttrProtocol<'p>, T: for<'p> PyObjectSetAttrProtocol<'p>,
{ {
#[inline]
fn tp_setattro() -> Option<ffi::setattrofunc> { fn tp_setattro() -> Option<ffi::setattrofunc> {
py_func_set!(PyObjectSetAttrProtocol, T::__setattr__) py_func_set!(PyObjectSetAttrProtocol, T::__setattr__)
} }
} }
trait PyObjectDelAttrProtocolImpl { trait PyObjectDelAttrProtocolImpl {
fn tp_delattro() -> Option<ffi::setattrofunc>; fn tp_delattro() -> Option<ffi::setattrofunc> {
}
impl<'p, T> PyObjectDelAttrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_delattro() -> Option<ffi::setattrofunc> {
None None
} }
} }
impl<'p, T> PyObjectDelAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectDelAttrProtocolImpl for T impl<T> PyObjectDelAttrProtocolImpl for T
where where
T: for<'p> PyObjectDelAttrProtocol<'p>, T: for<'p> PyObjectDelAttrProtocol<'p>,
{ {
#[inline]
default fn tp_delattro() -> Option<ffi::setattrofunc> { default fn tp_delattro() -> Option<ffi::setattrofunc> {
py_func_del!(PyObjectDelAttrProtocol, T::__delattr__) py_func_del!(PyObjectDelAttrProtocol, T::__delattr__)
} }
@ -277,33 +251,27 @@ impl<T> PyObjectDelAttrProtocolImpl for T
where where
T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>, T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
{ {
#[inline]
fn tp_delattro() -> Option<ffi::setattrofunc> { fn tp_delattro() -> Option<ffi::setattrofunc> {
py_func_set_del!( py_func_set_del!(
PyObjectSetAttrProtocol, PyObjectSetAttrProtocol,
PyObjectDelAttrProtocol, PyObjectDelAttrProtocol,
T::__setattr__ / __delattr__ T,
__setattr__,
__delattr__
) )
} }
} }
trait PyObjectStrProtocolImpl { trait PyObjectStrProtocolImpl {
fn tp_str() -> Option<ffi::unaryfunc>; fn tp_str() -> Option<ffi::unaryfunc> {
}
impl<'p, T> PyObjectStrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_str() -> Option<ffi::unaryfunc> {
None None
} }
} }
impl<'p, T> PyObjectStrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectStrProtocolImpl for T impl<T> PyObjectStrProtocolImpl for T
where where
T: for<'p> PyObjectStrProtocol<'p>, T: for<'p> PyObjectStrProtocol<'p>,
{ {
#[inline]
fn tp_str() -> Option<ffi::unaryfunc> { fn tp_str() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(
PyObjectStrProtocol, PyObjectStrProtocol,
@ -315,22 +283,15 @@ where
} }
trait PyObjectReprProtocolImpl { trait PyObjectReprProtocolImpl {
fn tp_repr() -> Option<ffi::unaryfunc>; fn tp_repr() -> Option<ffi::unaryfunc> {
}
impl<'p, T> PyObjectReprProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_repr() -> Option<ffi::unaryfunc> {
None None
} }
} }
impl<'p, T> PyObjectReprProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectReprProtocolImpl for T impl<T> PyObjectReprProtocolImpl for T
where where
T: for<'p> PyObjectReprProtocol<'p>, T: for<'p> PyObjectReprProtocol<'p>,
{ {
#[inline]
fn tp_repr() -> Option<ffi::unaryfunc> { fn tp_repr() -> Option<ffi::unaryfunc> {
py_unary_func!( py_unary_func!(
PyObjectReprProtocol, PyObjectReprProtocol,
@ -343,63 +304,38 @@ where
#[doc(hidden)] #[doc(hidden)]
pub trait PyObjectFormatProtocolImpl { pub trait PyObjectFormatProtocolImpl {
fn __format__() -> Option<PyMethodDef>; fn __format__() -> Option<PyMethodDef> {
}
impl<'p, T> PyObjectFormatProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn __format__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyObjectFormatProtocolImpl for T where T: PyObjectProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyObjectBytesProtocolImpl { pub trait PyObjectBytesProtocolImpl {
fn __bytes__() -> Option<PyMethodDef>; fn __bytes__() -> Option<PyMethodDef> {
}
impl<'p, T> PyObjectBytesProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn __bytes__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyObjectBytesProtocolImpl for T where T: PyObjectProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyObjectUnicodeProtocolImpl { pub trait PyObjectUnicodeProtocolImpl {
fn __unicode__() -> Option<PyMethodDef>; fn __unicode__() -> Option<PyMethodDef> {
}
impl<'p, T> PyObjectUnicodeProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn __unicode__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyObjectUnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
trait PyObjectHashProtocolImpl { trait PyObjectHashProtocolImpl {
fn tp_hash() -> Option<ffi::hashfunc>; fn tp_hash() -> Option<ffi::hashfunc> {
}
impl<'p, T> PyObjectHashProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_hash() -> Option<ffi::hashfunc> {
None None
} }
} }
impl<'p, T> PyObjectHashProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectHashProtocolImpl for T impl<T> PyObjectHashProtocolImpl for T
where where
T: for<'p> PyObjectHashProtocol<'p>, T: for<'p> PyObjectHashProtocol<'p>,
{ {
#[inline]
fn tp_hash() -> Option<ffi::hashfunc> { fn tp_hash() -> Option<ffi::hashfunc> {
py_unary_func!( py_unary_func!(
PyObjectHashProtocol, PyObjectHashProtocol,
@ -412,22 +348,15 @@ where
} }
trait PyObjectBoolProtocolImpl { trait PyObjectBoolProtocolImpl {
fn nb_bool() -> Option<ffi::inquiry>; fn nb_bool() -> Option<ffi::inquiry> {
}
impl<'p, T> PyObjectBoolProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn nb_bool() -> Option<ffi::inquiry> {
None None
} }
} }
impl<'p, T> PyObjectBoolProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectBoolProtocolImpl for T impl<T> PyObjectBoolProtocolImpl for T
where where
T: for<'p> PyObjectBoolProtocol<'p>, T: for<'p> PyObjectBoolProtocol<'p>,
{ {
#[inline]
fn nb_bool() -> Option<ffi::inquiry> { fn nb_bool() -> Option<ffi::inquiry> {
py_unary_func!( py_unary_func!(
PyObjectBoolProtocol, PyObjectBoolProtocol,
@ -440,22 +369,15 @@ where
} }
trait PyObjectRichcmpProtocolImpl { trait PyObjectRichcmpProtocolImpl {
fn tp_richcompare() -> Option<ffi::richcmpfunc>; fn tp_richcompare() -> Option<ffi::richcmpfunc> {
}
impl<'p, T> PyObjectRichcmpProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_richcompare() -> Option<ffi::richcmpfunc> {
None None
} }
} }
impl<'p, T> PyObjectRichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectRichcmpProtocolImpl for T impl<T> PyObjectRichcmpProtocolImpl for T
where where
T: for<'p> PyObjectRichcmpProtocol<'p>, T: for<'p> PyObjectRichcmpProtocol<'p>,
{ {
#[inline]
fn tp_richcompare() -> Option<ffi::richcmpfunc> { fn tp_richcompare() -> Option<ffi::richcmpfunc> {
unsafe extern "C" fn wrap<T>( unsafe extern "C" fn wrap<T>(
slf: *mut ffi::PyObject, slf: *mut ffi::PyObject,

View File

@ -42,15 +42,13 @@ pub trait PyBufferReleaseBufferProtocol<'p>: PyBufferProtocol<'p> {
#[doc(hidden)] #[doc(hidden)]
pub trait PyBufferProtocolImpl { pub trait PyBufferProtocolImpl {
fn tp_as_buffer() -> Option<ffi::PyBufferProcs>; fn tp_as_buffer() -> Option<ffi::PyBufferProcs> {
}
impl<T> PyBufferProtocolImpl for T {
default fn tp_as_buffer() -> Option<ffi::PyBufferProcs> {
None None
} }
} }
impl<T> PyBufferProtocolImpl for T {}
impl<'p, T> PyBufferProtocolImpl for T impl<'p, T> PyBufferProtocolImpl for T
where where
T: PyBufferProtocol<'p>, T: PyBufferProtocol<'p>,
@ -67,19 +65,13 @@ where
} }
trait PyBufferGetBufferProtocolImpl { trait PyBufferGetBufferProtocolImpl {
fn cb_bf_getbuffer() -> Option<ffi::getbufferproc>; fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
}
impl<'p, T> PyBufferGetBufferProtocolImpl for T
where
T: PyBufferProtocol<'p>,
{
#[inline]
default fn cb_bf_getbuffer() -> Option<ffi::getbufferproc> {
None None
} }
} }
impl<'p, T> PyBufferGetBufferProtocolImpl for T where T: PyBufferProtocol<'p> {}
impl<T> PyBufferGetBufferProtocolImpl for T impl<T> PyBufferGetBufferProtocolImpl for T
where where
T: for<'p> PyBufferGetBufferProtocol<'p>, T: for<'p> PyBufferGetBufferProtocol<'p>,

View File

@ -46,16 +46,13 @@ pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> {
#[doc(hidden)] #[doc(hidden)]
pub trait PyContextProtocolImpl { pub trait PyContextProtocolImpl {
fn methods() -> Vec<PyMethodDef>; fn methods() -> Vec<PyMethodDef> {
}
impl<T> PyContextProtocolImpl for T {
#[inline]
default fn methods() -> Vec<PyMethodDef> {
Vec::new() Vec::new()
} }
} }
impl<T> PyContextProtocolImpl for T {}
impl<'p, T> PyContextProtocolImpl for T impl<'p, T> PyContextProtocolImpl for T
where where
T: PyContextProtocol<'p>, T: PyContextProtocol<'p>,
@ -77,30 +74,18 @@ where
#[doc(hidden)] #[doc(hidden)]
pub trait PyContextEnterProtocolImpl { pub trait PyContextEnterProtocolImpl {
fn __enter__() -> Option<PyMethodDef>; fn __enter__() -> Option<PyMethodDef> {
}
impl<'p, T> PyContextEnterProtocolImpl for T
where
T: PyContextProtocol<'p>,
{
#[inline]
default fn __enter__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyContextExitProtocolImpl { pub trait PyContextExitProtocolImpl {
fn __exit__() -> Option<PyMethodDef>; fn __exit__() -> Option<PyMethodDef> {
}
impl<'p, T> PyContextExitProtocolImpl for T
where
T: PyContextProtocol<'p>,
{
#[inline]
default fn __exit__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyContextExitProtocolImpl for T where T: PyContextProtocol<'p> {}

View File

@ -71,16 +71,12 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
} }
trait PyDescrGetProtocolImpl { trait PyDescrGetProtocolImpl {
fn tp_descr_get() -> Option<ffi::descrgetfunc>; fn tp_descr_get() -> Option<ffi::descrgetfunc> {
}
impl<'p, T> PyDescrGetProtocolImpl for T
where
T: PyDescrProtocol<'p>,
{
default fn tp_descr_get() -> Option<ffi::descrgetfunc> {
None None
} }
} }
impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {}
impl<T> PyDescrGetProtocolImpl for T impl<T> PyDescrGetProtocolImpl for T
where where
T: for<'p> PyDescrGetProtocol<'p>, T: for<'p> PyDescrGetProtocol<'p>,
@ -94,17 +90,13 @@ where
) )
} }
} }
trait PyDescrSetProtocolImpl { trait PyDescrSetProtocolImpl {
fn tp_descr_set() -> Option<ffi::descrsetfunc>; fn tp_descr_set() -> Option<ffi::descrsetfunc> {
}
impl<'p, T> PyDescrSetProtocolImpl for T
where
T: PyDescrProtocol<'p>,
{
default fn tp_descr_set() -> Option<ffi::descrsetfunc> {
None None
} }
} }
impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {}
impl<T> PyDescrSetProtocolImpl for T impl<T> PyDescrSetProtocolImpl for T
where where
T: for<'p> PyDescrSetProtocol<'p>, T: for<'p> PyDescrSetProtocol<'p>,
@ -121,42 +113,29 @@ where
} }
trait PyDescrDelProtocolImpl { trait PyDescrDelProtocolImpl {
fn __del__() -> Option<PyMethodDef>; fn __del__() -> Option<PyMethodDef> {
}
impl<'p, T> PyDescrDelProtocolImpl for T
where
T: PyDescrProtocol<'p>,
{
default fn __del__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyDescrDelProtocolImpl for T where T: PyDescrProtocol<'p> {}
trait PyDescrSetNameProtocolImpl { trait PyDescrSetNameProtocolImpl {
fn __set_name__() -> Option<PyMethodDef>; fn __set_name__() -> Option<PyMethodDef> {
}
impl<'p, T> PyDescrSetNameProtocolImpl for T
where
T: PyDescrProtocol<'p>,
{
default fn __set_name__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyDescrSetNameProtocolImpl for T where T: PyDescrProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyDescrProtocolImpl { pub trait PyDescrProtocolImpl {
fn methods() -> Vec<PyMethodDef>; fn methods() -> Vec<PyMethodDef> {
fn tp_as_descr(type_object: &mut ffi::PyTypeObject);
}
impl<T> PyDescrProtocolImpl for T {
default fn methods() -> Vec<PyMethodDef> {
Vec::new() Vec::new()
} }
default fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {} fn tp_as_descr(_type_object: &mut ffi::PyTypeObject) {}
} }
impl<T> PyDescrProtocolImpl for T {}
impl<'p, T> PyDescrProtocolImpl for T impl<'p, T> PyDescrProtocolImpl for T
where where
T: PyDescrProtocol<'p>, T: PyDescrProtocol<'p>,

View File

@ -29,12 +29,10 @@ pub trait PyGCClearProtocol<'p>: PyGCProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyGCProtocolImpl { pub trait PyGCProtocolImpl {
fn update_type_object(type_object: &mut ffi::PyTypeObject); fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
} }
impl<'p, T> PyGCProtocolImpl for T { impl<'p, T> PyGCProtocolImpl for T {}
default fn update_type_object(_type_object: &mut ffi::PyTypeObject) {}
}
impl<'p, T> PyGCProtocolImpl for T impl<'p, T> PyGCProtocolImpl for T
where where
@ -71,19 +69,13 @@ impl<'p> PyVisit<'p> {
} }
trait PyGCTraverseProtocolImpl { trait PyGCTraverseProtocolImpl {
fn tp_traverse() -> Option<ffi::traverseproc>; fn tp_traverse() -> Option<ffi::traverseproc> {
}
impl<'p, T> PyGCTraverseProtocolImpl for T
where
T: PyGCProtocol<'p>,
{
#[inline]
default fn tp_traverse() -> Option<ffi::traverseproc> {
None None
} }
} }
impl<'p, T> PyGCTraverseProtocolImpl for T where T: PyGCProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
impl<T> PyGCTraverseProtocolImpl for T impl<T> PyGCTraverseProtocolImpl for T
where where
@ -119,19 +111,13 @@ where
} }
trait PyGCClearProtocolImpl { trait PyGCClearProtocolImpl {
fn tp_clear() -> Option<ffi::inquiry>; fn tp_clear() -> Option<ffi::inquiry> {
}
impl<'p, T> PyGCClearProtocolImpl for T
where
T: PyGCProtocol<'p>,
{
#[inline]
default fn tp_clear() -> Option<ffi::inquiry> {
None None
} }
} }
impl<'p, T> PyGCClearProtocolImpl for T where T: PyGCProtocol<'p> {}
impl<T> PyGCClearProtocolImpl for T impl<T> PyGCClearProtocolImpl for T
where where
T: for<'p> PyGCClearProtocol<'p>, T: for<'p> PyGCClearProtocol<'p>,

View File

@ -44,13 +44,10 @@ pub trait PyIterNextProtocol<'p>: PyIterProtocol<'p> {
#[doc(hidden)] #[doc(hidden)]
pub trait PyIterProtocolImpl { pub trait PyIterProtocolImpl {
fn tp_as_iter(typeob: &mut ffi::PyTypeObject); fn tp_as_iter(_typeob: &mut ffi::PyTypeObject) {}
} }
impl<T> PyIterProtocolImpl for T { impl<T> PyIterProtocolImpl for T {}
#[inline]
default fn tp_as_iter(_: &mut ffi::PyTypeObject) {}
}
impl<'p, T> PyIterProtocolImpl for T impl<'p, T> PyIterProtocolImpl for T
where where
@ -64,19 +61,13 @@ where
} }
trait PyIterIterProtocolImpl { trait PyIterIterProtocolImpl {
fn tp_iter() -> Option<ffi::getiterfunc>; fn tp_iter() -> Option<ffi::getiterfunc> {
}
impl<'p, T> PyIterIterProtocolImpl for T
where
T: PyIterProtocol<'p>,
{
#[inline]
default fn tp_iter() -> Option<ffi::getiterfunc> {
None None
} }
} }
impl<'p, T> PyIterIterProtocolImpl for T where T: PyIterProtocol<'p> {}
impl<T> PyIterIterProtocolImpl for T impl<T> PyIterIterProtocolImpl for T
where where
T: for<'p> PyIterIterProtocol<'p>, T: for<'p> PyIterIterProtocol<'p>,
@ -93,19 +84,13 @@ where
} }
trait PyIterNextProtocolImpl { trait PyIterNextProtocolImpl {
fn tp_iternext() -> Option<ffi::iternextfunc>; fn tp_iternext() -> Option<ffi::iternextfunc> {
}
impl<'p, T> PyIterNextProtocolImpl for T
where
T: PyIterProtocol<'p>,
{
#[inline]
default fn tp_iternext() -> Option<ffi::iternextfunc> {
None None
} }
} }
impl<'p, T> PyIterNextProtocolImpl for T where T: PyIterProtocol<'p> {}
impl<T> PyIterNextProtocolImpl for T impl<T> PyIterNextProtocolImpl for T
where where
T: for<'p> PyIterNextProtocol<'p>, T: for<'p> PyIterNextProtocol<'p>,

View File

@ -406,17 +406,16 @@ macro_rules! py_func_del {
}}; }};
} }
#[macro_export]
#[doc(hidden)] #[doc(hidden)]
macro_rules! py_func_set_del { macro_rules! py_func_set_del {
($trait:ident, $trait2:ident, $class:ident :: $f:ident/$f2:ident) => {{ ($trait1:ident, $trait2:ident, $generic:ident, $fn_set:ident, $fn_del:ident) => {{
unsafe extern "C" fn wrap<T>( unsafe extern "C" fn wrap<$generic>(
slf: *mut $crate::ffi::PyObject, slf: *mut $crate::ffi::PyObject,
name: *mut $crate::ffi::PyObject, name: *mut $crate::ffi::PyObject,
value: *mut $crate::ffi::PyObject, value: *mut $crate::ffi::PyObject,
) -> $crate::libc::c_int ) -> $crate::libc::c_int
where where
T: for<'p> $trait<'p> + for<'p> $trait2<'p>, T: for<'p> $trait1<'p> + for<'p> $trait2<'p>,
{ {
use $crate::ObjectProtocol; use $crate::ObjectProtocol;
@ -425,27 +424,22 @@ macro_rules! py_func_set_del {
let slf = py.mut_from_borrowed_ptr::<T>(slf); let slf = py.mut_from_borrowed_ptr::<T>(slf);
let name = py.from_borrowed_ptr::<$crate::PyObjectRef>(name); let name = py.from_borrowed_ptr::<$crate::PyObjectRef>(name);
let result;
if value.is_null() { if value.is_null() {
let result = match name.extract() { result = match name.extract() {
Ok(name) => slf.$f2(name).into(), Ok(name) => slf.$fn_del(name).into(),
Err(e) => Err(e.into()), Err(e) => Err(e.into()),
}; };
match result {
Ok(_) => 0,
Err(e) => {
e.restore(py);
-1
}
}
} else { } else {
let value = py.from_borrowed_ptr::<$crate::PyObjectRef>(value); let value = py.from_borrowed_ptr::<$crate::PyObjectRef>(value);
let result = match name.extract() { result = match name.extract() {
Ok(name) => match value.extract() { Ok(name) => match value.extract() {
Ok(value) => slf.$f(name, value).into(), Ok(value) => slf.$fn_set(name, value).into(),
Err(e) => Err(e.into()), Err(e) => Err(e.into()),
}, },
Err(e) => Err(e.into()), Err(e) => Err(e.into()),
}; };
}
match result { match result {
Ok(_) => 0, Ok(_) => 0,
Err(e) => { Err(e) => {
@ -454,7 +448,6 @@ macro_rules! py_func_set_del {
} }
} }
} }
}
Some(wrap::<T>) Some(wrap::<T>)
}}; }};
} }

View File

@ -106,21 +106,16 @@ pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> {
#[doc(hidden)] #[doc(hidden)]
pub trait PyMappingProtocolImpl { pub trait PyMappingProtocolImpl {
fn tp_as_mapping() -> Option<ffi::PyMappingMethods>; fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
fn methods() -> Vec<PyMethodDef>;
}
impl<T> PyMappingProtocolImpl for T {
#[inline]
default fn tp_as_mapping() -> Option<ffi::PyMappingMethods> {
None None
} }
#[inline] fn methods() -> Vec<PyMethodDef> {
default fn methods() -> Vec<PyMethodDef> {
Vec::new() Vec::new()
} }
} }
impl<T> PyMappingProtocolImpl for T {}
impl<'p, T> PyMappingProtocolImpl for T impl<'p, T> PyMappingProtocolImpl for T
where where
T: PyMappingProtocol<'p>, T: PyMappingProtocol<'p>,
@ -159,19 +154,13 @@ where
} }
trait PyMappingLenProtocolImpl { trait PyMappingLenProtocolImpl {
fn mp_length() -> Option<ffi::lenfunc>; fn mp_length() -> Option<ffi::lenfunc> {
}
impl<'p, T> PyMappingLenProtocolImpl for T
where
T: PyMappingProtocol<'p>,
{
#[inline]
default fn mp_length() -> Option<ffi::lenfunc> {
None None
} }
} }
impl<'p, T> PyMappingLenProtocolImpl for T where T: PyMappingProtocol<'p> {}
impl<T> PyMappingLenProtocolImpl for T impl<T> PyMappingLenProtocolImpl for T
where where
T: for<'p> PyMappingLenProtocol<'p>, T: for<'p> PyMappingLenProtocol<'p>,
@ -183,19 +172,13 @@ where
} }
trait PyMappingGetItemProtocolImpl { trait PyMappingGetItemProtocolImpl {
fn mp_subscript() -> Option<ffi::binaryfunc>; fn mp_subscript() -> Option<ffi::binaryfunc> {
}
impl<'p, T> PyMappingGetItemProtocolImpl for T
where
T: PyMappingProtocol<'p>,
{
#[inline]
default fn mp_subscript() -> Option<ffi::binaryfunc> {
None None
} }
} }
impl<'p, T> PyMappingGetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
impl<T> PyMappingGetItemProtocolImpl for T impl<T> PyMappingGetItemProtocolImpl for T
where where
T: for<'p> PyMappingGetItemProtocol<'p>, T: for<'p> PyMappingGetItemProtocol<'p>,
@ -212,19 +195,13 @@ where
} }
trait PyMappingSetItemProtocolImpl { trait PyMappingSetItemProtocolImpl {
fn mp_ass_subscript() -> Option<ffi::objobjargproc>; fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
}
impl<'p, T> PyMappingSetItemProtocolImpl for T
where
T: PyMappingProtocol<'p>,
{
#[inline]
default fn mp_ass_subscript() -> Option<ffi::objobjargproc> {
None None
} }
} }
impl<'p, T> PyMappingSetItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
impl<T> PyMappingSetItemProtocolImpl for T impl<T> PyMappingSetItemProtocolImpl for T
where where
T: for<'p> PyMappingSetItemProtocol<'p>, T: for<'p> PyMappingSetItemProtocol<'p>,
@ -236,19 +213,13 @@ where
} }
trait PyMappingDelItemProtocolImpl { trait PyMappingDelItemProtocolImpl {
fn mp_del_subscript() -> Option<ffi::objobjargproc>; fn mp_del_subscript() -> Option<ffi::objobjargproc> {
}
impl<'p, T> PyMappingDelItemProtocolImpl for T
where
T: PyMappingProtocol<'p>,
{
#[inline]
default fn mp_del_subscript() -> Option<ffi::objobjargproc> {
None None
} }
} }
impl<'p, T> PyMappingDelItemProtocolImpl for T where T: PyMappingProtocol<'p> {}
impl<T> PyMappingDelItemProtocolImpl for T impl<T> PyMappingDelItemProtocolImpl for T
where where
T: for<'p> PyMappingDelItemProtocol<'p>, T: for<'p> PyMappingDelItemProtocol<'p>,
@ -268,52 +239,36 @@ where
py_func_set_del!( py_func_set_del!(
PyMappingSetItemProtocol, PyMappingSetItemProtocol,
PyMappingDelItemProtocol, PyMappingDelItemProtocol,
T::__setitem__ / __delitem__ T,
__setitem__,
__delitem__
) )
} }
} }
#[doc(hidden)] #[doc(hidden)]
pub trait PyMappingContainsProtocolImpl { pub trait PyMappingContainsProtocolImpl {
fn __contains__() -> Option<PyMethodDef>; fn __contains__() -> Option<PyMethodDef> {
}
impl<'p, T> PyMappingContainsProtocolImpl for T
where
T: PyMappingProtocol<'p>,
{
#[inline]
default fn __contains__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyMappingContainsProtocolImpl for T where T: PyMappingProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyMappingReversedProtocolImpl { pub trait PyMappingReversedProtocolImpl {
fn __reversed__() -> Option<PyMethodDef>; fn __reversed__() -> Option<PyMethodDef> {
}
impl<'p, T> PyMappingReversedProtocolImpl for T
where
T: PyMappingProtocol<'p>,
{
#[inline]
default fn __reversed__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyMappingReversedProtocolImpl for T where T: PyMappingProtocol<'p> {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyMappingIterProtocolImpl { pub trait PyMappingIterProtocolImpl {
fn __iter__() -> Option<PyMethodDef>; fn __iter__() -> Option<PyMethodDef> {
}
impl<'p, T> PyMappingIterProtocolImpl for T
where
T: PyMappingProtocol<'p>,
{
#[inline]
default fn __iter__() -> Option<PyMethodDef> {
None None
} }
} }
impl<'p, T> PyMappingIterProtocolImpl for T where T: PyMappingProtocol<'p> {}

View File

@ -124,22 +124,18 @@ impl PySetterDef {
#[doc(hidden)] #[doc(hidden)]
pub trait PyMethodsProtocolImpl { pub trait PyMethodsProtocolImpl {
fn py_methods() -> &'static [PyMethodDefType]; fn py_methods() -> &'static [PyMethodDefType] {
}
impl<T> PyMethodsProtocolImpl for T {
default fn py_methods() -> &'static [PyMethodDefType] {
NO_PY_METHODS NO_PY_METHODS
} }
} }
impl<T> PyMethodsProtocolImpl for T {}
#[doc(hidden)] #[doc(hidden)]
pub trait PyPropMethodsProtocolImpl { pub trait PyPropMethodsProtocolImpl {
fn py_methods() -> &'static [PyMethodDefType]; fn py_methods() -> &'static [PyMethodDefType] {
}
impl<T> PyPropMethodsProtocolImpl for T {
default fn py_methods() -> &'static [PyMethodDefType] {
NO_PY_METHODS NO_PY_METHODS
} }
} }
impl<T> PyPropMethodsProtocolImpl for T {}

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,6 @@
//! Python Sequence Interface //! Python Sequence Interface
//! Trait and support implementation for implementing sequence //! Trait and support implementation for implementing sequence
use std::os::raw::c_int;
use callback::{BoolCallbackConverter, LenResultConverter, PyObjectCallbackConverter}; use callback::{BoolCallbackConverter, LenResultConverter, PyObjectCallbackConverter};
use conversion::{FromPyObject, IntoPyObject}; use conversion::{FromPyObject, IntoPyObject};
use err::{PyErr, PyResult}; use err::{PyErr, PyResult};
@ -12,6 +10,7 @@ use ffi;
use objectprotocol::ObjectProtocol; use objectprotocol::ObjectProtocol;
use objects::{exc, PyObjectRef}; use objects::{exc, PyObjectRef};
use python::Python; use python::Python;
use std::os::raw::c_int;
use typeob::PyTypeInfo; use typeob::PyTypeInfo;
/// Sequece interface /// Sequece interface
@ -129,22 +128,17 @@ pub trait PySequenceInplaceRepeatProtocol<'p>: PySequenceProtocol<'p> + IntoPyOb
#[doc(hidden)] #[doc(hidden)]
pub trait PySequenceProtocolImpl { pub trait PySequenceProtocolImpl {
fn tp_as_sequence() -> Option<ffi::PySequenceMethods>; fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
}
impl<T> PySequenceProtocolImpl for T {
#[inline]
default fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
None None
} }
} }
impl<T> PySequenceProtocolImpl for T {}
impl<'p, T> PySequenceProtocolImpl for T impl<'p, T> PySequenceProtocolImpl for T
where where
T: PySequenceProtocol<'p>, T: PySequenceProtocol<'p>,
{ {
#[cfg(Py_3)]
#[inline]
fn tp_as_sequence() -> Option<ffi::PySequenceMethods> { fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
let f = if let Some(df) = Self::sq_del_item() { let f = if let Some(df) = Self::sq_del_item() {
Some(df) Some(df)
@ -152,7 +146,8 @@ where
Self::sq_ass_item() Self::sq_ass_item()
}; };
Some(ffi::PySequenceMethods { #[cfg(Py_3)]
return Some(ffi::PySequenceMethods {
sq_length: Self::sq_length(), sq_length: Self::sq_length(),
sq_concat: Self::sq_concat(), sq_concat: Self::sq_concat(),
sq_repeat: Self::sq_repeat(), sq_repeat: Self::sq_repeat(),
@ -163,18 +158,10 @@ where
sq_contains: Self::sq_contains(), sq_contains: Self::sq_contains(),
sq_inplace_concat: Self::sq_inplace_concat(), sq_inplace_concat: Self::sq_inplace_concat(),
sq_inplace_repeat: Self::sq_inplace_repeat(), sq_inplace_repeat: Self::sq_inplace_repeat(),
}) });
}
#[cfg(not(Py_3))]
#[inline]
fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
let f = if let Some(df) = Self::sq_del_item() {
Some(df)
} else {
Self::sq_ass_item()
};
Some(ffi::PySequenceMethods { #[cfg(not(Py_3))]
return Some(ffi::PySequenceMethods {
sq_length: Self::sq_length(), sq_length: Self::sq_length(),
sq_concat: Self::sq_concat(), sq_concat: Self::sq_concat(),
sq_repeat: Self::sq_repeat(), sq_repeat: Self::sq_repeat(),
@ -185,53 +172,39 @@ where
sq_contains: Self::sq_contains(), sq_contains: Self::sq_contains(),
sq_inplace_concat: Self::sq_inplace_concat(), sq_inplace_concat: Self::sq_inplace_concat(),
sq_inplace_repeat: Self::sq_inplace_repeat(), sq_inplace_repeat: Self::sq_inplace_repeat(),
}) });
} }
} }
trait PySequenceLenProtocolImpl { trait PySequenceLenProtocolImpl {
fn sq_length() -> Option<ffi::lenfunc>; fn sq_length() -> Option<ffi::lenfunc> {
}
impl<'p, T> PySequenceLenProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_length() -> Option<ffi::lenfunc> {
None None
} }
} }
impl<'p, T> PySequenceLenProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceLenProtocolImpl for T impl<T> PySequenceLenProtocolImpl for T
where where
T: for<'p> PySequenceLenProtocol<'p>, T: for<'p> PySequenceLenProtocol<'p>,
{ {
#[inline]
fn sq_length() -> Option<ffi::lenfunc> { fn sq_length() -> Option<ffi::lenfunc> {
py_len_func!(PySequenceLenProtocol, T::__len__, LenResultConverter) py_len_func!(PySequenceLenProtocol, T::__len__, LenResultConverter)
} }
} }
trait PySequenceGetItemProtocolImpl { trait PySequenceGetItemProtocolImpl {
fn sq_item() -> Option<ffi::ssizeargfunc>; fn sq_item() -> Option<ffi::ssizeargfunc> {
}
impl<'p, T> PySequenceGetItemProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_item() -> Option<ffi::ssizeargfunc> {
None None
} }
} }
impl<'p, T> PySequenceGetItemProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceGetItemProtocolImpl for T impl<T> PySequenceGetItemProtocolImpl for T
where where
T: for<'p> PySequenceGetItemProtocol<'p>, T: for<'p> PySequenceGetItemProtocol<'p>,
{ {
#[inline]
fn sq_item() -> Option<ffi::ssizeargfunc> { fn sq_item() -> Option<ffi::ssizeargfunc> {
py_ssizearg_func!( py_ssizearg_func!(
PySequenceGetItemProtocol, PySequenceGetItemProtocol,
@ -243,24 +216,17 @@ where
} }
trait PySequenceSetItemProtocolImpl { trait PySequenceSetItemProtocolImpl {
fn sq_ass_item() -> Option<ffi::ssizeobjargproc>; fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
}
impl<'p, T> PySequenceSetItemProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
None None
} }
} }
impl<'p, T> PySequenceSetItemProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceSetItemProtocolImpl for T impl<T> PySequenceSetItemProtocolImpl for T
where where
T: for<'p> PySequenceSetItemProtocol<'p>, T: for<'p> PySequenceSetItemProtocol<'p>,
{ {
#[inline]
fn sq_ass_item() -> Option<ffi::ssizeobjargproc> { fn sq_ass_item() -> Option<ffi::ssizeobjargproc> {
unsafe extern "C" fn wrap<T>( unsafe extern "C" fn wrap<T>(
slf: *mut ffi::PyObject, slf: *mut ffi::PyObject,
@ -301,23 +267,17 @@ where
} }
trait PySequenceDelItemProtocolImpl { trait PySequenceDelItemProtocolImpl {
fn sq_del_item() -> Option<ffi::ssizeobjargproc>; fn sq_del_item() -> Option<ffi::ssizeobjargproc> {
}
impl<'p, T> PySequenceDelItemProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_del_item() -> Option<ffi::ssizeobjargproc> {
None None
} }
} }
impl<'p, T> PySequenceDelItemProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceDelItemProtocolImpl for T impl<T> PySequenceDelItemProtocolImpl for T
where where
T: for<'p> PySequenceDelItemProtocol<'p>, T: for<'p> PySequenceDelItemProtocol<'p>,
{ {
#[inline]
default fn sq_del_item() -> Option<ffi::ssizeobjargproc> { default fn sq_del_item() -> Option<ffi::ssizeobjargproc> {
unsafe extern "C" fn wrap<T>( unsafe extern "C" fn wrap<T>(
slf: *mut ffi::PyObject, slf: *mut ffi::PyObject,
@ -357,7 +317,6 @@ impl<T> PySequenceDelItemProtocolImpl for T
where where
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>, T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
{ {
#[inline]
fn sq_del_item() -> Option<ffi::ssizeobjargproc> { fn sq_del_item() -> Option<ffi::ssizeobjargproc> {
unsafe extern "C" fn wrap<T>( unsafe extern "C" fn wrap<T>(
slf: *mut ffi::PyObject, slf: *mut ffi::PyObject,
@ -400,24 +359,17 @@ where
} }
trait PySequenceContainsProtocolImpl { trait PySequenceContainsProtocolImpl {
fn sq_contains() -> Option<ffi::objobjproc>; fn sq_contains() -> Option<ffi::objobjproc> {
}
impl<'p, T> PySequenceContainsProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_contains() -> Option<ffi::objobjproc> {
None None
} }
} }
impl<'p, T> PySequenceContainsProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceContainsProtocolImpl for T impl<T> PySequenceContainsProtocolImpl for T
where where
T: for<'p> PySequenceContainsProtocol<'p>, T: for<'p> PySequenceContainsProtocol<'p>,
{ {
#[inline]
fn sq_contains() -> Option<ffi::objobjproc> { fn sq_contains() -> Option<ffi::objobjproc> {
py_binary_func!( py_binary_func!(
PySequenceContainsProtocol, PySequenceContainsProtocol,
@ -430,24 +382,17 @@ where
} }
trait PySequenceConcatProtocolImpl { trait PySequenceConcatProtocolImpl {
fn sq_concat() -> Option<ffi::binaryfunc>; fn sq_concat() -> Option<ffi::binaryfunc> {
}
impl<'p, T> PySequenceConcatProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_concat() -> Option<ffi::binaryfunc> {
None None
} }
} }
impl<'p, T> PySequenceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceConcatProtocolImpl for T impl<T> PySequenceConcatProtocolImpl for T
where where
T: for<'p> PySequenceConcatProtocol<'p>, T: for<'p> PySequenceConcatProtocol<'p>,
{ {
#[inline]
fn sq_concat() -> Option<ffi::binaryfunc> { fn sq_concat() -> Option<ffi::binaryfunc> {
py_binary_func!( py_binary_func!(
PySequenceConcatProtocol, PySequenceConcatProtocol,
@ -459,24 +404,17 @@ where
} }
trait PySequenceRepeatProtocolImpl { trait PySequenceRepeatProtocolImpl {
fn sq_repeat() -> Option<ffi::ssizeargfunc>; fn sq_repeat() -> Option<ffi::ssizeargfunc> {
}
impl<'p, T> PySequenceRepeatProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_repeat() -> Option<ffi::ssizeargfunc> {
None None
} }
} }
impl<'p, T> PySequenceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceRepeatProtocolImpl for T impl<T> PySequenceRepeatProtocolImpl for T
where where
T: for<'p> PySequenceRepeatProtocol<'p>, T: for<'p> PySequenceRepeatProtocol<'p>,
{ {
#[inline]
fn sq_repeat() -> Option<ffi::ssizeargfunc> { fn sq_repeat() -> Option<ffi::ssizeargfunc> {
py_ssizearg_func!( py_ssizearg_func!(
PySequenceRepeatProtocol, PySequenceRepeatProtocol,
@ -488,24 +426,17 @@ where
} }
trait PySequenceInplaceConcatProtocolImpl { trait PySequenceInplaceConcatProtocolImpl {
fn sq_inplace_concat() -> Option<ffi::binaryfunc>; fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
}
impl<'p, T> PySequenceInplaceConcatProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
None None
} }
} }
impl<'p, T> PySequenceInplaceConcatProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceInplaceConcatProtocolImpl for T impl<T> PySequenceInplaceConcatProtocolImpl for T
where where
T: for<'p> PySequenceInplaceConcatProtocol<'p>, T: for<'p> PySequenceInplaceConcatProtocol<'p>,
{ {
#[inline]
fn sq_inplace_concat() -> Option<ffi::binaryfunc> { fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
py_binary_func!( py_binary_func!(
PySequenceInplaceConcatProtocol, PySequenceInplaceConcatProtocol,
@ -517,24 +448,17 @@ where
} }
trait PySequenceInplaceRepeatProtocolImpl { trait PySequenceInplaceRepeatProtocolImpl {
fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc>; fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
}
impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T
where
T: PySequenceProtocol<'p>,
{
#[inline]
default fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
None None
} }
} }
impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T where T: PySequenceProtocol<'p> {}
impl<T> PySequenceInplaceRepeatProtocolImpl for T impl<T> PySequenceInplaceRepeatProtocolImpl for T
where where
T: for<'p> PySequenceInplaceRepeatProtocol<'p>, T: for<'p> PySequenceInplaceRepeatProtocol<'p>,
{ {
#[inline]
fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> { fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
py_ssizearg_func!( py_ssizearg_func!(
PySequenceInplaceRepeatProtocol, PySequenceInplaceRepeatProtocol,

View File

@ -23,16 +23,6 @@ pub trait ToBorrowedObject: ToPyObject {
/// May be more efficient than `to_object` because it does not need /// May be more efficient than `to_object` because it does not need
/// to touch any reference counts when the input object already is a Python object. /// to touch any reference counts when the input object already is a Python object.
fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
where
F: FnOnce(*mut ffi::PyObject) -> R;
}
impl<T> ToBorrowedObject for T
where
T: ToPyObject,
{
#[inline]
default fn with_borrowed_ptr<F, R>(&self, py: Python, f: F) -> R
where where
F: FnOnce(*mut ffi::PyObject) -> R, F: FnOnce(*mut ffi::PyObject) -> R,
{ {
@ -43,6 +33,8 @@ where
} }
} }
impl<T> ToBorrowedObject for T where T: ToPyObject {}
/// Conversion trait that allows various objects to be converted into `PyObject` /// Conversion trait that allows various objects to be converted into `PyObject`
/// by consuming original object. /// by consuming original object.
pub trait IntoPyObject { pub trait IntoPyObject {

View File

@ -1,11 +1,11 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
//! Free allocation list //! Free allocation list
use std;
use err::PyResult; use err::PyResult;
use ffi; use ffi;
use python::Python; use python::Python;
use std::mem;
use std::os::raw::c_void; use std::os::raw::c_void;
use typeob::{PyObjectAlloc, PyTypeInfo}; use typeob::{PyObjectAlloc, PyTypeInfo};
@ -45,7 +45,7 @@ impl<T> FreeList<T> {
if idx == 0 { if idx == 0 {
None None
} else { } else {
match std::mem::replace(&mut self.entries[idx - 1], Slot::Empty) { match mem::replace(&mut self.entries[idx - 1], Slot::Empty) {
Slot::Filled(v) => { Slot::Filled(v) => {
self.split = idx - 1; self.split = idx - 1;
Some(v) Some(v)

View File

@ -148,7 +148,7 @@ pub use noargs::NoArgs;
pub use object::PyObject; pub use object::PyObject;
pub use objectprotocol::ObjectProtocol; pub use objectprotocol::ObjectProtocol;
pub use objects::*; pub use objects::*;
pub use python::{IntoPyDictPointer, IntoPyPointer, Python, ToPyPointer}; pub use python::{IntoPyPointer, Python, ToPyPointer};
pub use pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GILPool}; pub use pythonrun::{init_once, prepare_freethreaded_python, GILGuard, GILPool};
pub use typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo}; pub use typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub mod class; pub mod class;

View File

@ -1,23 +1,22 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use std;
use conversion::{IntoPyObject, IntoPyTuple, ToPyObject}; use conversion::{IntoPyObject, IntoPyTuple, ToPyObject};
use ffi;
use instance::Py; use instance::Py;
use object::PyObject; use object::PyObject;
use objects::PyTuple; use objects::PyTuple;
use python::{IntoPyDictPointer, Python}; use python::Python;
/// An empty struct that represents the empty argument list. /// An empty struct that represents the empty argument list.
/// Corresponds to the empty tuple `()` in Python. /// Corresponds to the empty tuple `()` in Python.
/// ///
/// # Example /// # Example
/// ``` /// ```
/// let gil = pyo3::Python::acquire_gil(); /// # use pyo3::prelude::*;
///
/// let gil = Python::acquire_gil();
/// let py = gil.python(); /// let py = gil.python();
/// let os = py.import("os").unwrap(); /// let os = py.import("os").unwrap();
/// let pid = os.call("get_pid", pyo3::NoArgs, pyo3::NoArgs); /// let pid = os.call("get_pid", NoArgs, None);
/// ``` /// ```
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct NoArgs; pub struct NoArgs;
@ -49,10 +48,3 @@ impl IntoPyObject for NoArgs {
PyTuple::empty(py).into() PyTuple::empty(py).into()
} }
} }
/// Converts `NoArgs` to an null pointer.
impl IntoPyDictPointer for NoArgs {
fn into_dict_ptr(self, _: Python) -> *mut ffi::PyObject {
std::ptr::null_mut()
}
}

View File

@ -8,8 +8,9 @@ use conversion::{
use err::{PyDowncastError, PyErr, PyResult}; use err::{PyDowncastError, PyErr, PyResult};
use ffi; use ffi;
use instance::{AsPyRef, PyObjectWithToken}; use instance::{AsPyRef, PyObjectWithToken};
use objects::PyDict;
use objects::{PyObjectRef, PyTuple}; use objects::{PyObjectRef, PyTuple};
use python::{IntoPyDictPointer, IntoPyPointer, Python, ToPyPointer}; use python::{IntoPyPointer, Python, ToPyPointer};
use pythonrun; use pythonrun;
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer. /// Safe wrapper around unsafe `*mut ffi::PyObject` pointer.
@ -166,18 +167,19 @@ impl PyObject {
/// Calls the object. /// Calls the object.
/// This is equivalent to the Python expression: 'self(*args, **kwargs)' /// This is equivalent to the Python expression: 'self(*args, **kwargs)'
pub fn call<A, K>(&self, py: Python, args: A, kwargs: K) -> PyResult<PyObject> pub fn call<A>(&self, py: Python, args: A, kwargs: Option<PyDict>) -> PyResult<PyObject>
where where
A: IntoPyTuple, A: IntoPyTuple,
K: IntoPyDictPointer,
{ {
let args = args.into_tuple(py).into_ptr(); let args = args.into_tuple(py).into_ptr();
let kwargs = kwargs.into_dict_ptr(py);
let result = unsafe { let result = unsafe {
PyObject::from_owned_ptr_or_err(py, ffi::PyObject_Call(self.as_ptr(), args, kwargs)) PyObject::from_owned_ptr_or_err(
py,
ffi::PyObject_Call(self.as_ptr(), args, kwargs.into_ptr()),
)
}; };
py.xdecref(args); py.xdecref(args);
py.xdecref(kwargs); py.xdecref(kwargs.into_ptr());
result result
} }
@ -219,15 +221,14 @@ impl PyObject {
py: Python, py: Python,
name: &str, name: &str,
args: A, args: A,
kwargs: K, kwargs: PyDict,
) -> PyResult<PyObject> ) -> PyResult<PyObject>
where where
A: IntoPyTuple, A: IntoPyTuple,
K: IntoPyDictPointer,
{ {
name.with_borrowed_ptr(py, |name| unsafe { name.with_borrowed_ptr(py, |name| unsafe {
let args = args.into_tuple(py).into_ptr(); let args = args.into_tuple(py).into_ptr();
let kwargs = kwargs.into_dict_ptr(py); let kwargs = kwargs.into_ptr();
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name); let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
let result = PyObject::from_owned_ptr_or_err(py, ffi::PyObject_Call(ptr, args, kwargs)); let result = PyObject::from_owned_ptr_or_err(py, ffi::PyObject_Call(ptr, args, kwargs));
ffi::Py_DECREF(ptr); ffi::Py_DECREF(ptr);

View File

@ -1,16 +1,16 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use std;
use std::cmp::Ordering;
use std::os::raw::c_int;
use conversion::{FromPyObject, IntoPyTuple, PyTryFrom, ToBorrowedObject, ToPyObject}; use conversion::{FromPyObject, IntoPyTuple, PyTryFrom, ToBorrowedObject, ToPyObject};
use err::{self, PyDowncastError, PyErr, PyResult}; use err::{self, PyDowncastError, PyErr, PyResult};
use ffi; use ffi;
use instance::PyObjectWithToken; use instance::PyObjectWithToken;
use object::PyObject; use object::PyObject;
use objects::PyDict;
use objects::{PyIterator, PyObjectRef, PyString, PyTuple, PyType}; use objects::{PyIterator, PyObjectRef, PyString, PyTuple, PyType};
use python::{IntoPyDictPointer, IntoPyPointer, Python, ToPyPointer}; use python::{IntoPyPointer, Python, ToPyPointer};
use std;
use std::cmp::Ordering;
use std::os::raw::c_int;
use typeob::PyTypeInfo; use typeob::PyTypeInfo;
/// Python object model helper methods /// Python object model helper methods
@ -85,10 +85,9 @@ pub trait ObjectProtocol {
/// Calls the object. /// Calls the object.
/// This is equivalent to the Python expression: `self(*args, **kwargs)` /// This is equivalent to the Python expression: `self(*args, **kwargs)`
fn call<A, K>(&self, args: A, kwargs: K) -> PyResult<&PyObjectRef> fn call<A>(&self, args: A, kwargs: Option<PyDict>) -> PyResult<&PyObjectRef>
where where
A: IntoPyTuple, A: IntoPyTuple;
K: IntoPyDictPointer;
/// Calls the object. /// Calls the object.
/// This is equivalent to the Python expression: `self()` /// This is equivalent to the Python expression: `self()`
@ -108,12 +107,11 @@ pub trait ObjectProtocol {
/// let obj = SomePyObject::new(); /// let obj = SomePyObject::new();
/// let args = (arg1, arg2, arg3); /// let args = (arg1, arg2, arg3);
/// let kwargs = ((key1, value1), (key2, value2)); /// let kwargs = ((key1, value1), (key2, value2));
/// let pid = obj.call_method("do_something", args, kwargs); /// let pid = obj.call_method("do_something", args, kwargs.into_py_dict());
/// ``` /// ```
fn call_method<A, K>(&self, name: &str, args: A, kwargs: K) -> PyResult<&PyObjectRef> fn call_method<A>(&self, name: &str, args: A, kwargs: Option<PyDict>) -> PyResult<&PyObjectRef>
where where
A: IntoPyTuple, A: IntoPyTuple;
K: IntoPyDictPointer;
/// Calls a method on the object. /// Calls a method on the object.
/// This is equivalent to the Python expression: `self.name()` /// This is equivalent to the Python expression: `self.name()`
@ -313,19 +311,17 @@ where
unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 } unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 }
} }
fn call<A, K>(&self, args: A, kwargs: K) -> PyResult<&PyObjectRef> fn call<A>(&self, args: A, kwargs: Option<PyDict>) -> PyResult<&PyObjectRef>
where where
A: IntoPyTuple, A: IntoPyTuple,
K: IntoPyDictPointer,
{ {
let args = args.into_tuple(self.py()).into_ptr(); let args = args.into_tuple(self.py()).into_ptr();
let kw_ptr = kwargs.into_dict_ptr(self.py());
let result = unsafe { let result = unsafe {
self.py() let return_value = ffi::PyObject_Call(self.as_ptr(), args, kwargs.into_ptr());
.from_owned_ptr_or_err(ffi::PyObject_Call(self.as_ptr(), args, kw_ptr)) self.py().from_owned_ptr_or_err(return_value)
}; };
self.py().xdecref(args); self.py().xdecref(args);
self.py().xdecref(kw_ptr); self.py().xdecref(kwargs.into_ptr());
result result
} }
@ -358,10 +354,9 @@ where
result result
} }
fn call_method<A, K>(&self, name: &str, args: A, kwargs: K) -> PyResult<&PyObjectRef> fn call_method<A>(&self, name: &str, args: A, kwargs: Option<PyDict>) -> PyResult<&PyObjectRef>
where where
A: IntoPyTuple, A: IntoPyTuple,
K: IntoPyDictPointer,
{ {
name.with_borrowed_ptr(self.py(), |name| unsafe { name.with_borrowed_ptr(self.py(), |name| unsafe {
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name); let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
@ -369,13 +364,12 @@ where
return Err(PyErr::fetch(self.py())); return Err(PyErr::fetch(self.py()));
} }
let args = args.into_tuple(self.py()).into_ptr(); let args = args.into_tuple(self.py()).into_ptr();
let kw_ptr = kwargs.into_dict_ptr(self.py()); let kwargs = kwargs.into_ptr();
let result = self let result_ptr = ffi::PyObject_Call(ptr, args, kwargs);
.py() let result = self.py().from_owned_ptr_or_err(result_ptr);
.from_owned_ptr_or_err(ffi::PyObject_Call(ptr, args, kw_ptr));
ffi::Py_DECREF(ptr); ffi::Py_DECREF(ptr);
self.py().xdecref(args); self.py().xdecref(args);
self.py().xdecref(kw_ptr); self.py().xdecref(kwargs);
result result
}) })
} }
@ -531,7 +525,6 @@ mod test {
use super::*; use super::*;
use conversion::{PyTryFrom, ToPyObject}; use conversion::{PyTryFrom, ToPyObject};
use instance::AsPyRef; use instance::AsPyRef;
use noargs::NoArgs;
use objects::PyString; use objects::PyString;
use python::Python; use python::Python;
@ -559,7 +552,7 @@ mod test {
let py = gil.python(); let py = gil.python();
let a = py.eval("42", None, None).unwrap(); let a = py.eval("42", None, None).unwrap();
a.call_method0("__str__").unwrap(); // ok a.call_method0("__str__").unwrap(); // ok
assert!(a.call_method("nonexistent_method", (1,), NoArgs).is_err()); assert!(a.call_method("nonexistent_method", (1,), None).is_err());
assert!(a.call_method0("nonexistent_method").is_err()); assert!(a.call_method0("nonexistent_method").is_err());
assert!(a.call_method1("nonexistent_method", (1,)).is_err()); assert!(a.call_method1("nonexistent_method", (1,)).is_err());
} }

View File

@ -5,8 +5,8 @@ use ffi;
use instance::PyObjectWithToken; use instance::PyObjectWithToken;
use object::PyObject; use object::PyObject;
use python::{Python, ToPyPointer}; use python::{Python, ToPyPointer};
use std;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::slice;
/// Represents a Python `bytearray`. /// Represents a Python `bytearray`.
#[repr(transparent)] #[repr(transparent)]
@ -51,7 +51,7 @@ impl PyByteArray {
unsafe { unsafe {
let buffer = ffi::PyByteArray_AsString(self.0.as_ptr()) as *mut u8; let buffer = ffi::PyByteArray_AsString(self.0.as_ptr()) as *mut u8;
let length = ffi::PyByteArray_Size(self.0.as_ptr()) as usize; let length = ffi::PyByteArray_Size(self.0.as_ptr()) as usize;
std::slice::from_raw_parts_mut(buffer, length) slice::from_raw_parts_mut(buffer, length)
} }
} }

View File

@ -1,15 +1,14 @@
// Copyright (c) 2017-present PyO3 Project and Contributors // Copyright (c) 2017-present PyO3 Project and Contributors
use std;
use std::{cmp, collections, hash, mem};
use conversion::{IntoPyObject, ToBorrowedObject, ToPyObject}; use conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
use err::{self, PyErr, PyResult}; use err::{self, PyErr, PyResult};
use ffi; use ffi;
use instance::{Py, PyObjectWithToken}; use instance::PyObjectWithToken;
use object::PyObject; use object::PyObject;
use objects::{PyList, PyObjectRef}; use objects::{PyList, PyObjectRef};
use python::{IntoPyDictPointer, IntoPyPointer, Python, ToPyPointer}; use python::{Python, ToPyPointer};
use std;
use std::{cmp, collections, hash, mem};
/// Represents a Python `dict`. /// Represents a Python `dict`.
#[repr(transparent)] #[repr(transparent)]
@ -19,8 +18,6 @@ pyobject_native_type!(PyDict, ffi::PyDict_Type, ffi::PyDict_Check);
impl PyDict { impl PyDict {
/// Creates a new empty dictionary. /// Creates a new empty dictionary.
///
/// May panic when running out of memory.
pub fn new(py: Python) -> &PyDict { pub fn new(py: Python) -> &PyDict {
unsafe { py.from_owned_ptr::<PyDict>(ffi::PyDict_New()) } unsafe { py.from_owned_ptr::<PyDict>(ffi::PyDict_New()) }
} }
@ -169,20 +166,6 @@ impl<'a> std::iter::IntoIterator for &'a PyDict {
} }
} }
impl<'a> IntoPyDictPointer for &'a PyDict {
#[must_use]
fn into_dict_ptr(self, _py: Python) -> *mut ffi::PyObject {
self.into_ptr()
}
}
impl IntoPyDictPointer for Py<PyDict> {
#[must_use]
fn into_dict_ptr(self, _py: Python) -> *mut ffi::PyObject {
self.into_ptr()
}
}
impl<K, V, H> ToPyObject for collections::HashMap<K, V, H> impl<K, V, H> ToPyObject for collections::HashMap<K, V, H>
where where
K: hash::Hash + cmp::Eq + ToPyObject, K: hash::Hash + cmp::Eq + ToPyObject,
@ -245,19 +228,27 @@ where
} }
} }
impl<K, V, I> IntoPyDictPointer for I /// Conversion trait that allows a sequence of tuples to be converted into `PyDict`
/// Primary use case for this trait is `call` and `call_method` methods as keywords argument.
pub trait IntoPyDict {
/// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed
/// depends on implementation.
fn into_py_dict(self, py: Python) -> &PyDict;
}
impl<K, V, I> IntoPyDict for I
where where
K: ToPyObject, K: ToPyObject,
V: ToPyObject, V: ToPyObject,
I: IntoIterator<Item = (K, V)>, I: IntoIterator<Item = (K, V)>,
{ {
default fn into_dict_ptr(self, py: Python) -> *mut ffi::PyObject { fn into_py_dict(self, py: Python) -> &PyDict {
let dict = PyDict::new(py); let dict = PyDict::new(py);
for (key, value) in self { for (key, value) in self {
dict.set_item(key, value) dict.set_item(key, value)
.expect("Failed to set_item on dict"); .expect("Failed to set_item on dict");
} }
dict.into_ptr() dict
} }
} }
@ -265,10 +256,11 @@ where
mod test { mod test {
use conversion::{IntoPyObject, PyTryFrom, ToPyObject}; use conversion::{IntoPyObject, PyTryFrom, ToPyObject};
use instance::AsPyRef; use instance::AsPyRef;
use objects::dict::IntoPyDict;
use objects::{PyDict, PyTuple}; use objects::{PyDict, PyTuple};
use python::{IntoPyDictPointer, Python}; use python::Python;
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use {ObjectProtocol, PyObject}; use ObjectProtocol;
#[test] #[test]
fn test_new() { fn test_new() {
@ -558,12 +550,10 @@ mod test {
let mut map = HashMap::<i32, i32>::new(); let mut map = HashMap::<i32, i32>::new();
map.insert(1, 1); map.insert(1, 1);
let m = map.into_dict_ptr(py); let py_map = map.into_py_dict(py);
let ob = unsafe { PyObject::from_owned_ptr(py, m) };
let py_map = <PyDict as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
assert!(py_map.len() == 1); assert_eq!(py_map.len(), 1);
assert!(py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1); assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);
} }
#[test] #[test]
@ -589,12 +579,10 @@ mod test {
let mut map = BTreeMap::<i32, i32>::new(); let mut map = BTreeMap::<i32, i32>::new();
map.insert(1, 1); map.insert(1, 1);
let m = map.into_dict_ptr(py); let py_map = map.into_py_dict(py);
let ob = unsafe { PyObject::from_owned_ptr(py, m) };
let py_map = <PyDict as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
assert!(py_map.len() == 1); assert_eq!(py_map.len(), 1);
assert!(py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1); assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);
} }
#[test] #[test]
@ -602,12 +590,10 @@ mod test {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
let map = vec![("a", 1), ("b", 2), ("c", 3)]; let vec = vec![("a", 1), ("b", 2), ("c", 3)];
let m = map.into_dict_ptr(py); let py_map = vec.into_py_dict(py);
let ob = unsafe { PyObject::from_owned_ptr(py, m) };
let py_map = <PyDict as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
assert!(py_map.len() == 3); assert_eq!(py_map.len(), 3);
assert!(py_map.get_item("b").unwrap().extract::<i32>().unwrap() == 2); assert_eq!(py_map.get_item("b").unwrap().extract::<i32>().unwrap(), 2);
} }
} }

View File

@ -5,6 +5,7 @@ pub use self::bytearray::PyByteArray;
pub use self::datetime::PyDeltaAccess; pub use self::datetime::PyDeltaAccess;
pub use self::datetime::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo}; pub use self::datetime::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo};
pub use self::datetime::{PyDateAccess, PyTimeAccess}; pub use self::datetime::{PyDateAccess, PyTimeAccess};
pub use self::dict::IntoPyDict;
pub use self::dict::PyDict; pub use self::dict::PyDict;
pub use self::floatob::PyFloat; pub use self::floatob::PyFloat;
pub use self::iterator::PyIterator; pub use self::iterator::PyIterator;

View File

@ -2,7 +2,6 @@
// //
// based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython // based on Daniel Grunwald's https://github.com/dgrunwald/rust-cpython
use std;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::os::raw::c_char; use std::os::raw::c_char;
@ -13,7 +12,8 @@ use instance::PyObjectWithToken;
use object::PyObject; use object::PyObject;
use objectprotocol::ObjectProtocol; use objectprotocol::ObjectProtocol;
use objects::{exc, PyDict, PyObjectRef, PyType}; use objects::{exc, PyDict, PyObjectRef, PyType};
use python::{IntoPyDictPointer, Python, ToPyPointer}; use python::{Python, ToPyPointer};
use std::str;
use typeob::{initialize_type, PyTypeInfo}; use typeob::{initialize_type, PyTypeInfo};
/// Represents a Python `module` object. /// Represents a Python `module` object.
@ -80,7 +80,7 @@ impl PyModule {
Err(PyErr::fetch(self.py())) Err(PyErr::fetch(self.py()))
} else { } else {
let slice = CStr::from_ptr(ptr).to_bytes(); let slice = CStr::from_ptr(ptr).to_bytes();
match std::str::from_utf8(slice) { match str::from_utf8(slice) {
Ok(s) => Ok(s), Ok(s) => Ok(s),
Err(e) => Err(PyErr::from_instance(exc::UnicodeDecodeError::new_utf8( Err(e) => Err(PyErr::from_instance(exc::UnicodeDecodeError::new_utf8(
self.py(), self.py(),
@ -107,10 +107,9 @@ impl PyModule {
/// Calls a function in the module. /// Calls a function in the module.
/// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)` /// This is equivalent to the Python expression: `getattr(module, name)(*args, **kwargs)`
pub fn call<A, K>(&self, name: &str, args: A, kwargs: K) -> PyResult<&PyObjectRef> pub fn call<A>(&self, name: &str, args: A, kwargs: Option<PyDict>) -> PyResult<&PyObjectRef>
where where
A: IntoPyTuple, A: IntoPyTuple,
K: IntoPyDictPointer,
{ {
self.getattr(name)?.call(args, kwargs) self.getattr(name)?.call(args, kwargs)
} }

View File

@ -311,10 +311,10 @@ impl PyTryFrom for PySequence {
mod test { mod test {
use conversion::{PyTryFrom, ToPyObject}; use conversion::{PyTryFrom, ToPyObject};
use instance::AsPyRef; use instance::AsPyRef;
use objectprotocol::ObjectProtocol;
use object::PyObject; use object::PyObject;
use objectprotocol::ObjectProtocol;
use objects::PySequence; use objects::PySequence;
use python::{ToPyPointer, Python}; use python::{Python, ToPyPointer};
fn get_object() -> PyObject { fn get_object() -> PyObject {
// Convenience function for getting a single unique object // Convenience function for getting a single unique object

View File

@ -60,23 +60,15 @@ pub trait IntoPyPointer {
fn into_ptr(self) -> *mut ffi::PyObject; fn into_ptr(self) -> *mut ffi::PyObject;
} }
/// Conversion trait that allows various objects to be converted into `PyDict` object pointer.
/// Primary use case for this trait is `call` and `call_method` methods as keywords argument.
pub trait IntoPyDictPointer {
/// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed
/// depends on implementation.
fn into_dict_ptr(self, py: Python) -> *mut ffi::PyObject;
}
/// Convert `None` into a null pointer. /// Convert `None` into a null pointer.
impl<'p, T> ToPyPointer for Option<&'p T> impl<T> ToPyPointer for Option<T>
where where
T: ToPyPointer, T: ToPyPointer,
{ {
#[inline] #[inline]
default fn as_ptr(&self) -> *mut ffi::PyObject { fn as_ptr(&self) -> *mut ffi::PyObject {
match *self { match *self {
Some(t) => t.as_ptr(), Some(ref t) => t.as_ptr(),
None => std::ptr::null_mut(), None => std::ptr::null_mut(),
} }
} }
@ -102,11 +94,13 @@ where
T: ToPyPointer, T: ToPyPointer,
{ {
#[inline] #[inline]
default fn into_ptr(self) -> *mut ffi::PyObject { fn into_ptr(self) -> *mut ffi::PyObject {
let ptr = self.as_ptr(); let ptr = self.as_ptr();
if ptr != std::ptr::null_mut() {
unsafe { unsafe {
ffi::Py_INCREF(ptr); ffi::Py_INCREF(ptr);
} }
}
ptr ptr
} }
} }

View File

@ -250,37 +250,16 @@ where
Ok(obj) Ok(obj)
} }
#[cfg(Py_3)]
default unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) { default unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
Self::drop(py, obj); Self::drop(py, obj);
#[cfg(Py_3)]
{
if ffi::PyObject_CallFinalizerFromDealloc(obj) < 0 { if ffi::PyObject_CallFinalizerFromDealloc(obj) < 0 {
return; return;
} }
match (*T::type_object()).tp_free {
Some(free) => free(obj as *mut c_void),
None => {
let ty = ffi::Py_TYPE(obj);
if ffi::PyType_IS_GC(ty) != 0 {
ffi::PyObject_GC_Del(obj as *mut c_void);
} else {
ffi::PyObject_Free(obj as *mut c_void);
} }
// For heap types, PyType_GenericAlloc calls INCREF on the type objects,
// so we need to call DECREF here:
if ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE) != 0 {
ffi::Py_DECREF(ty as *mut ffi::PyObject);
}
}
}
}
#[cfg(not(Py_3))]
default unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
Self::drop(py, obj);
match (*T::type_object()).tp_free { match (*T::type_object()).tp_free {
Some(free) => free(obj as *mut c_void), Some(free) => free(obj as *mut c_void),
None => { None => {
@ -357,7 +336,7 @@ where
/// Register new type in python object system. /// Register new type in python object system.
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
pub fn initialize_type<'p, T>(py: Python<'p>, module_name: Option<&str>) -> PyResult<()> pub fn initialize_type<T>(py: Python, module_name: Option<&str>) -> PyResult<()>
where where
T: PyObjectAlloc<T> + PyTypeInfo, T: PyObjectAlloc<T> + PyTypeInfo,
{ {

View File

@ -24,7 +24,7 @@ macro_rules! py_run {
d.set_item(stringify!($val), &$val).unwrap(); d.set_item(stringify!($val), &$val).unwrap();
$py.run(&common::indoc($code), None, Some(d)) $py.run(&common::indoc($code), None, Some(d))
.map_err(|e| e.print($py)) .map_err(|e| e.print($py))
.expect(&common::indoc($code)); .expect(&common::indoc($code))
}}; }};
} }

View File

@ -16,7 +16,7 @@ fn empty_class() {
let py = gil.python(); let py = gil.python();
let typeobj = py.get_type::<EmptyClass>(); let typeobj = py.get_type::<EmptyClass>();
// By default, don't allow creating instances from python. // By default, don't allow creating instances from python.
assert!(typeobj.call(NoArgs, NoArgs).is_err()); assert!(typeobj.call(NoArgs, None).is_err());
py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'"); py_assert!(py, typeobj, "typeobj.__name__ == 'EmptyClass'");
} }

View File

@ -24,7 +24,7 @@ fn empty_class_with_new() {
let typeobj = py.get_type::<EmptyClassWithNew>(); let typeobj = py.get_type::<EmptyClassWithNew>();
assert!( assert!(
typeobj typeobj
.call(NoArgs, NoArgs) .call(NoArgs, None)
.unwrap() .unwrap()
.cast_as::<EmptyClassWithNew>() .cast_as::<EmptyClassWithNew>()
.is_ok() .is_ok()
@ -53,7 +53,7 @@ fn new_with_one_arg() {
let gil = Python::acquire_gil(); let gil = Python::acquire_gil();
let py = gil.python(); let py = gil.python();
let typeobj = py.get_type::<NewWithOneArg>(); let typeobj = py.get_type::<NewWithOneArg>();
let wrp = typeobj.call((42,), NoArgs).unwrap(); let wrp = typeobj.call((42,), None).unwrap();
let obj = wrp.cast_as::<NewWithOneArg>().unwrap(); let obj = wrp.cast_as::<NewWithOneArg>().unwrap();
assert_eq!(obj._data, 42); assert_eq!(obj._data, 42);
} }
@ -84,7 +84,7 @@ fn new_with_two_args() {
let py = gil.python(); let py = gil.python();
let typeobj = py.get_type::<NewWithTwoArgs>(); let typeobj = py.get_type::<NewWithTwoArgs>();
let wrp = typeobj let wrp = typeobj
.call((10, 20), NoArgs) .call((10, 20), None)
.map_err(|e| e.print(py)) .map_err(|e| e.print(py))
.unwrap(); .unwrap();
let obj = wrp.cast_as::<NewWithTwoArgs>().unwrap(); let obj = wrp.cast_as::<NewWithTwoArgs>().unwrap();

View File

@ -263,7 +263,7 @@ fn inheritance_with_new_methods_with_drop() {
let py = gil.python(); let py = gil.python();
let _typebase = py.get_type::<BaseClassWithDrop>(); let _typebase = py.get_type::<BaseClassWithDrop>();
let typeobj = py.get_type::<SubClassWithDrop>(); let typeobj = py.get_type::<SubClassWithDrop>();
let inst = typeobj.call(NoArgs, NoArgs).unwrap(); let inst = typeobj.call(NoArgs, None).unwrap();
let obj = SubClassWithDrop::try_from_mut(inst).unwrap(); let obj = SubClassWithDrop::try_from_mut(inst).unwrap();
obj.data = Some(Arc::clone(&drop_called1)); obj.data = Some(Arc::clone(&drop_called1));

View File

@ -62,6 +62,6 @@ fn inheritance_with_new_methods() {
let py = gil.python(); let py = gil.python();
let _typebase = py.get_type::<BaseClass>(); let _typebase = py.get_type::<BaseClass>();
let typeobj = py.get_type::<SubClass>(); let typeobj = py.get_type::<SubClass>();
let inst = typeobj.call(NoArgs, NoArgs).unwrap(); let inst = typeobj.call(NoArgs, None).unwrap();
py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5"); py_run!(py, inst, "assert inst.val1 == 10; assert inst.val2 == 5");
} }

View File

@ -252,5 +252,4 @@ fn meth_args() {
inst, inst,
"assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]" "assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]"
); );
// py_expect_exception!(py, inst, "inst.get_kwarg(100)", TypeError);
} }