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
* Slowly removing specialization uses
* 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`
* `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

View file

@ -76,11 +76,8 @@ fn main() {
}
```
`kwargs` argument is generate over
[`IntoPyDictPointer`][IntoPyDictPointer] trait. `HashMap` or `BTreeMap` could be used as
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.
`kwargs` can by `None` or `Some(PyDict)`. You can use the
[`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.
```rust
extern crate pyo3;
@ -130,4 +127,4 @@ TODO
[IntoPyTuple]: https://docs.rs/pyo3/0.2.7/trait.IntoPyTuple.html
[PyTuple]: https://docs.rs/pyo3/0.2.7/struct.PyTuple.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
.import("array")
.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();
let buffer = PyBuffer::get(py, array.into()).unwrap();
assert_eq!(buffer.dimensions(), 1);

View file

@ -91,24 +91,18 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
#[cfg(Py_3)]
#[doc(hidden)]
pub trait PyAsyncProtocolImpl {
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> {
fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
None
}
#[inline]
default fn methods() -> Vec<PyMethodDef> {
fn methods() -> Vec<PyMethodDef> {
Vec::new()
}
}
#[cfg(Py_3)]
impl<T> PyAsyncProtocolImpl for T {}
#[cfg(Py_3)]
impl<'p, T> PyAsyncProtocolImpl for T
where
@ -139,19 +133,13 @@ where
}
trait PyAsyncAwaitProtocolImpl {
fn am_await() -> Option<ffi::unaryfunc>;
}
impl<'p, T> PyAsyncAwaitProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn am_await() -> Option<ffi::unaryfunc> {
fn am_await() -> Option<ffi::unaryfunc> {
None
}
}
impl<'p, T> PyAsyncAwaitProtocolImpl for T where T: PyAsyncProtocol<'p> {}
impl<T> PyAsyncAwaitProtocolImpl for T
where
T: for<'p> PyAsyncAwaitProtocol<'p>,
@ -168,19 +156,13 @@ where
}
trait PyAsyncAiterProtocolImpl {
fn am_aiter() -> Option<ffi::unaryfunc>;
}
impl<'p, T> PyAsyncAiterProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn am_aiter() -> Option<ffi::unaryfunc> {
fn am_aiter() -> Option<ffi::unaryfunc> {
None
}
}
impl<'p, T> PyAsyncAiterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
impl<T> PyAsyncAiterProtocolImpl for T
where
T: for<'p> PyAsyncAiterProtocol<'p>,
@ -197,19 +179,13 @@ where
}
trait PyAsyncAnextProtocolImpl {
fn am_anext() -> Option<ffi::unaryfunc>;
}
impl<'p, T> PyAsyncAnextProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn am_anext() -> Option<ffi::unaryfunc> {
fn am_anext() -> Option<ffi::unaryfunc> {
None
}
}
impl<'p, T> PyAsyncAnextProtocolImpl for T where T: PyAsyncProtocol<'p> {}
#[cfg(Py_3)]
mod anext {
use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
@ -260,29 +236,17 @@ mod anext {
}
trait PyAsyncAenterProtocolImpl {
fn __aenter__() -> Option<PyMethodDef>;
}
impl<'p, T> PyAsyncAenterProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn __aenter__() -> Option<PyMethodDef> {
fn __aenter__() -> Option<PyMethodDef> {
None
}
}
impl<'p, T> PyAsyncAenterProtocolImpl for T where T: PyAsyncProtocol<'p> {}
trait PyAsyncAexitProtocolImpl {
fn __aexit__() -> Option<PyMethodDef>;
}
impl<'p, T> PyAsyncAexitProtocolImpl for T
where
T: PyAsyncProtocol<'p>,
{
#[inline]
default fn __aexit__() -> Option<PyMethodDef> {
fn __aexit__() -> Option<PyMethodDef> {
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)]
pub trait PyObjectProtocolImpl {
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> {
fn methods() -> Vec<PyMethodDef> {
Vec::new()
}
default fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
default fn nb_bool_fn() -> Option<ffi::inquiry> {
fn tp_as_object(_type_object: &mut ffi::PyTypeObject) {}
fn nb_bool_fn() -> Option<ffi::inquiry> {
None
}
}
impl<T> PyObjectProtocolImpl for T {}
impl<'p, T> PyObjectProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
fn methods() -> Vec<PyMethodDef> {
let mut methods = Vec::new();
@ -203,22 +198,15 @@ where
}
trait PyObjectGetAttrProtocolImpl {
fn tp_getattro() -> Option<ffi::binaryfunc>;
}
impl<'p, T> PyObjectGetAttrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_getattro() -> Option<ffi::binaryfunc> {
fn tp_getattro() -> Option<ffi::binaryfunc> {
None
}
}
impl<'p, T> PyObjectGetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectGetAttrProtocolImpl for T
where
T: for<'p> PyObjectGetAttrProtocol<'p>,
{
#[inline]
fn tp_getattro() -> Option<ffi::binaryfunc> {
py_binary_func!(
PyObjectGetAttrProtocol,
@ -230,45 +218,31 @@ where
}
trait PyObjectSetAttrProtocolImpl {
fn tp_setattro() -> Option<ffi::setattrofunc>;
}
impl<'p, T> PyObjectSetAttrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_setattro() -> Option<ffi::setattrofunc> {
fn tp_setattro() -> Option<ffi::setattrofunc> {
None
}
}
impl<'p, T> PyObjectSetAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectSetAttrProtocolImpl for T
where
T: for<'p> PyObjectSetAttrProtocol<'p>,
{
#[inline]
fn tp_setattro() -> Option<ffi::setattrofunc> {
py_func_set!(PyObjectSetAttrProtocol, T::__setattr__)
}
}
trait PyObjectDelAttrProtocolImpl {
fn tp_delattro() -> Option<ffi::setattrofunc>;
}
impl<'p, T> PyObjectDelAttrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_delattro() -> Option<ffi::setattrofunc> {
fn tp_delattro() -> Option<ffi::setattrofunc> {
None
}
}
impl<'p, T> PyObjectDelAttrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectDelAttrProtocolImpl for T
where
T: for<'p> PyObjectDelAttrProtocol<'p>,
{
#[inline]
default fn tp_delattro() -> Option<ffi::setattrofunc> {
py_func_del!(PyObjectDelAttrProtocol, T::__delattr__)
}
@ -277,33 +251,27 @@ impl<T> PyObjectDelAttrProtocolImpl for T
where
T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
{
#[inline]
fn tp_delattro() -> Option<ffi::setattrofunc> {
py_func_set_del!(
PyObjectSetAttrProtocol,
PyObjectDelAttrProtocol,
T::__setattr__ / __delattr__
T,
__setattr__,
__delattr__
)
}
}
trait PyObjectStrProtocolImpl {
fn tp_str() -> Option<ffi::unaryfunc>;
}
impl<'p, T> PyObjectStrProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_str() -> Option<ffi::unaryfunc> {
fn tp_str() -> Option<ffi::unaryfunc> {
None
}
}
impl<'p, T> PyObjectStrProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectStrProtocolImpl for T
where
T: for<'p> PyObjectStrProtocol<'p>,
{
#[inline]
fn tp_str() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyObjectStrProtocol,
@ -315,22 +283,15 @@ where
}
trait PyObjectReprProtocolImpl {
fn tp_repr() -> Option<ffi::unaryfunc>;
}
impl<'p, T> PyObjectReprProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_repr() -> Option<ffi::unaryfunc> {
fn tp_repr() -> Option<ffi::unaryfunc> {
None
}
}
impl<'p, T> PyObjectReprProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectReprProtocolImpl for T
where
T: for<'p> PyObjectReprProtocol<'p>,
{
#[inline]
fn tp_repr() -> Option<ffi::unaryfunc> {
py_unary_func!(
PyObjectReprProtocol,
@ -343,63 +304,38 @@ where
#[doc(hidden)]
pub trait PyObjectFormatProtocolImpl {
fn __format__() -> Option<PyMethodDef>;
}
impl<'p, T> PyObjectFormatProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn __format__() -> Option<PyMethodDef> {
fn __format__() -> Option<PyMethodDef> {
None
}
}
impl<'p, T> PyObjectFormatProtocolImpl for T where T: PyObjectProtocol<'p> {}
#[doc(hidden)]
pub trait PyObjectBytesProtocolImpl {
fn __bytes__() -> Option<PyMethodDef>;
}
impl<'p, T> PyObjectBytesProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn __bytes__() -> Option<PyMethodDef> {
fn __bytes__() -> Option<PyMethodDef> {
None
}
}
impl<'p, T> PyObjectBytesProtocolImpl for T where T: PyObjectProtocol<'p> {}
#[doc(hidden)]
pub trait PyObjectUnicodeProtocolImpl {
fn __unicode__() -> Option<PyMethodDef>;
}
impl<'p, T> PyObjectUnicodeProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn __unicode__() -> Option<PyMethodDef> {
fn __unicode__() -> Option<PyMethodDef> {
None
}
}
impl<'p, T> PyObjectUnicodeProtocolImpl for T where T: PyObjectProtocol<'p> {}
trait PyObjectHashProtocolImpl {
fn tp_hash() -> Option<ffi::hashfunc>;
}
impl<'p, T> PyObjectHashProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_hash() -> Option<ffi::hashfunc> {
fn tp_hash() -> Option<ffi::hashfunc> {
None
}
}
impl<'p, T> PyObjectHashProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectHashProtocolImpl for T
where
T: for<'p> PyObjectHashProtocol<'p>,
{
#[inline]
fn tp_hash() -> Option<ffi::hashfunc> {
py_unary_func!(
PyObjectHashProtocol,
@ -412,22 +348,15 @@ where
}
trait PyObjectBoolProtocolImpl {
fn nb_bool() -> Option<ffi::inquiry>;
}
impl<'p, T> PyObjectBoolProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn nb_bool() -> Option<ffi::inquiry> {
fn nb_bool() -> Option<ffi::inquiry> {
None
}
}
impl<'p, T> PyObjectBoolProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectBoolProtocolImpl for T
where
T: for<'p> PyObjectBoolProtocol<'p>,
{
#[inline]
fn nb_bool() -> Option<ffi::inquiry> {
py_unary_func!(
PyObjectBoolProtocol,
@ -440,22 +369,15 @@ where
}
trait PyObjectRichcmpProtocolImpl {
fn tp_richcompare() -> Option<ffi::richcmpfunc>;
}
impl<'p, T> PyObjectRichcmpProtocolImpl for T
where
T: PyObjectProtocol<'p>,
{
#[inline]
default fn tp_richcompare() -> Option<ffi::richcmpfunc> {
fn tp_richcompare() -> Option<ffi::richcmpfunc> {
None
}
}
impl<'p, T> PyObjectRichcmpProtocolImpl for T where T: PyObjectProtocol<'p> {}
impl<T> PyObjectRichcmpProtocolImpl for T
where
T: for<'p> PyObjectRichcmpProtocol<'p>,
{
#[inline]
fn tp_richcompare() -> Option<ffi::richcmpfunc> {
unsafe extern "C" fn wrap<T>(
slf: *mut ffi::PyObject,

View file

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

View file

@ -46,16 +46,13 @@ pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> {
#[doc(hidden)]
pub trait PyContextProtocolImpl {
fn methods() -> Vec<PyMethodDef>;
}
impl<T> PyContextProtocolImpl for T {
#[inline]
default fn methods() -> Vec<PyMethodDef> {
fn methods() -> Vec<PyMethodDef> {
Vec::new()
}
}
impl<T> PyContextProtocolImpl for T {}
impl<'p, T> PyContextProtocolImpl for T
where
T: PyContextProtocol<'p>,
@ -77,30 +74,18 @@ where
#[doc(hidden)]
pub trait PyContextEnterProtocolImpl {
fn __enter__() -> Option<PyMethodDef>;
}
impl<'p, T> PyContextEnterProtocolImpl for T
where
T: PyContextProtocol<'p>,
{
#[inline]
default fn __enter__() -> Option<PyMethodDef> {
fn __enter__() -> Option<PyMethodDef> {
None
}
}
impl<'p, T> PyContextEnterProtocolImpl for T where T: PyContextProtocol<'p> {}
#[doc(hidden)]
pub trait PyContextExitProtocolImpl {
fn __exit__() -> Option<PyMethodDef>;
}
impl<'p, T> PyContextExitProtocolImpl for T
where
T: PyContextProtocol<'p>,
{
#[inline]
default fn __exit__() -> Option<PyMethodDef> {
fn __exit__() -> Option<PyMethodDef> {
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 {
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> {
fn tp_descr_get() -> Option<ffi::descrgetfunc> {
None
}
}
impl<'p, T> PyDescrGetProtocolImpl for T where T: PyDescrProtocol<'p> {}
impl<T> PyDescrGetProtocolImpl for T
where
T: for<'p> PyDescrGetProtocol<'p>,
@ -94,17 +90,13 @@ where
)
}
}
trait PyDescrSetProtocolImpl {
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> {
fn tp_descr_set() -> Option<ffi::descrsetfunc> {
None
}
}
impl<'p, T> PyDescrSetProtocolImpl for T where T: PyDescrProtocol<'p> {}
impl<T> PyDescrSetProtocolImpl for T
where
T: for<'p> PyDescrSetProtocol<'p>,
@ -121,42 +113,29 @@ where
}
trait PyDescrDelProtocolImpl {
fn __del__() -> Option<PyMethodDef>;
}
impl<'p, T> PyDescrDelProtocolImpl for T
where
T: PyDescrProtocol<'p>,
{
default fn __del__() -> Option<PyMethodDef> {
fn __del__() -> Option<PyMethodDef> {
None
}
}
impl<'p, T> PyDescrDelProtocolImpl for T where T: PyDescrProtocol<'p> {}
trait PyDescrSetNameProtocolImpl {
fn __set_name__() -> Option<PyMethodDef>;
}
impl<'p, T> PyDescrSetNameProtocolImpl for T
where
T: PyDescrProtocol<'p>,
{
default fn __set_name__() -> Option<PyMethodDef> {
fn __set_name__() -> Option<PyMethodDef> {
None
}
}
impl<'p, T> PyDescrSetNameProtocolImpl for T where T: PyDescrProtocol<'p> {}
#[doc(hidden)]
pub trait PyDescrProtocolImpl {
fn methods() -> Vec<PyMethodDef>;
fn tp_as_descr(type_object: &mut ffi::PyTypeObject);
}
impl<T> PyDescrProtocolImpl for T {
default fn methods() -> Vec<PyMethodDef> {
fn methods() -> Vec<PyMethodDef> {
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
where
T: PyDescrProtocol<'p>,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -23,16 +23,6 @@ pub trait ToBorrowedObject: ToPyObject {
/// 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.
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
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`
/// by consuming original object.
pub trait IntoPyObject {

View file

@ -1,11 +1,11 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
//! Free allocation list
use std;
use err::PyResult;
use ffi;
use python::Python;
use std::mem;
use std::os::raw::c_void;
use typeob::{PyObjectAlloc, PyTypeInfo};
@ -45,7 +45,7 @@ impl<T> FreeList<T> {
if idx == 0 {
None
} 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) => {
self.split = idx - 1;
Some(v)

View file

@ -148,7 +148,7 @@ pub use noargs::NoArgs;
pub use object::PyObject;
pub use objectprotocol::ObjectProtocol;
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 typeob::{PyObjectAlloc, PyRawObject, PyTypeInfo};
pub mod class;

View file

@ -1,23 +1,22 @@
// Copyright (c) 2017-present PyO3 Project and Contributors
use std;
use conversion::{IntoPyObject, IntoPyTuple, ToPyObject};
use ffi;
use instance::Py;
use object::PyObject;
use objects::PyTuple;
use python::{IntoPyDictPointer, Python};
use python::Python;
/// An empty struct that represents the empty argument list.
/// Corresponds to the empty tuple `()` in Python.
///
/// # Example
/// ```
/// let gil = pyo3::Python::acquire_gil();
/// # use pyo3::prelude::*;
///
/// let gil = Python::acquire_gil();
/// let py = gil.python();
/// 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)]
pub struct NoArgs;
@ -49,10 +48,3 @@ impl IntoPyObject for NoArgs {
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 ffi;
use instance::{AsPyRef, PyObjectWithToken};
use objects::PyDict;
use objects::{PyObjectRef, PyTuple};
use python::{IntoPyDictPointer, IntoPyPointer, Python, ToPyPointer};
use python::{IntoPyPointer, Python, ToPyPointer};
use pythonrun;
/// Safe wrapper around unsafe `*mut ffi::PyObject` pointer.
@ -166,18 +167,19 @@ impl PyObject {
/// Calls the object.
/// 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
A: IntoPyTuple,
K: IntoPyDictPointer,
{
let args = args.into_tuple(py).into_ptr();
let kwargs = kwargs.into_dict_ptr(py);
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(kwargs);
py.xdecref(kwargs.into_ptr());
result
}
@ -219,15 +221,14 @@ impl PyObject {
py: Python,
name: &str,
args: A,
kwargs: K,
kwargs: PyDict,
) -> PyResult<PyObject>
where
A: IntoPyTuple,
K: IntoPyDictPointer,
{
name.with_borrowed_ptr(py, |name| unsafe {
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 result = PyObject::from_owned_ptr_or_err(py, ffi::PyObject_Call(ptr, args, kwargs));
ffi::Py_DECREF(ptr);

View file

@ -1,16 +1,16 @@
// 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 err::{self, PyDowncastError, PyErr, PyResult};
use ffi;
use instance::PyObjectWithToken;
use object::PyObject;
use objects::PyDict;
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;
/// Python object model helper methods
@ -85,10 +85,9 @@ pub trait ObjectProtocol {
/// Calls the object.
/// 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
A: IntoPyTuple,
K: IntoPyDictPointer;
A: IntoPyTuple;
/// Calls the object.
/// This is equivalent to the Python expression: `self()`
@ -108,12 +107,11 @@ pub trait ObjectProtocol {
/// let obj = SomePyObject::new();
/// let args = (arg1, arg2, arg3);
/// 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
A: IntoPyTuple,
K: IntoPyDictPointer;
A: IntoPyTuple;
/// Calls a method on the object.
/// This is equivalent to the Python expression: `self.name()`
@ -313,19 +311,17 @@ where
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
A: IntoPyTuple,
K: IntoPyDictPointer,
{
let args = args.into_tuple(self.py()).into_ptr();
let kw_ptr = kwargs.into_dict_ptr(self.py());
let result = unsafe {
self.py()
.from_owned_ptr_or_err(ffi::PyObject_Call(self.as_ptr(), args, kw_ptr))
let return_value = ffi::PyObject_Call(self.as_ptr(), args, kwargs.into_ptr());
self.py().from_owned_ptr_or_err(return_value)
};
self.py().xdecref(args);
self.py().xdecref(kw_ptr);
self.py().xdecref(kwargs.into_ptr());
result
}
@ -358,10 +354,9 @@ where
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
A: IntoPyTuple,
K: IntoPyDictPointer,
{
name.with_borrowed_ptr(self.py(), |name| unsafe {
let ptr = ffi::PyObject_GetAttr(self.as_ptr(), name);
@ -369,13 +364,12 @@ where
return Err(PyErr::fetch(self.py()));
}
let args = args.into_tuple(self.py()).into_ptr();
let kw_ptr = kwargs.into_dict_ptr(self.py());
let result = self
.py()
.from_owned_ptr_or_err(ffi::PyObject_Call(ptr, args, kw_ptr));
let kwargs = kwargs.into_ptr();
let result_ptr = ffi::PyObject_Call(ptr, args, kwargs);
let result = self.py().from_owned_ptr_or_err(result_ptr);
ffi::Py_DECREF(ptr);
self.py().xdecref(args);
self.py().xdecref(kw_ptr);
self.py().xdecref(kwargs);
result
})
}
@ -531,7 +525,6 @@ mod test {
use super::*;
use conversion::{PyTryFrom, ToPyObject};
use instance::AsPyRef;
use noargs::NoArgs;
use objects::PyString;
use python::Python;
@ -559,7 +552,7 @@ mod test {
let py = gil.python();
let a = py.eval("42", None, None).unwrap();
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_method1("nonexistent_method", (1,)).is_err());
}

View file

@ -5,8 +5,8 @@ use ffi;
use instance::PyObjectWithToken;
use object::PyObject;
use python::{Python, ToPyPointer};
use std;
use std::os::raw::c_char;
use std::slice;
/// Represents a Python `bytearray`.
#[repr(transparent)]
@ -51,7 +51,7 @@ impl PyByteArray {
unsafe {
let buffer = ffi::PyByteArray_AsString(self.0.as_ptr()) as *mut u8;
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
use std;
use std::{cmp, collections, hash, mem};
use conversion::{IntoPyObject, ToBorrowedObject, ToPyObject};
use err::{self, PyErr, PyResult};
use ffi;
use instance::{Py, PyObjectWithToken};
use instance::PyObjectWithToken;
use object::PyObject;
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`.
#[repr(transparent)]
@ -19,8 +18,6 @@ pyobject_native_type!(PyDict, ffi::PyDict_Type, ffi::PyDict_Check);
impl PyDict {
/// Creates a new empty dictionary.
///
/// May panic when running out of memory.
pub fn new(py: Python) -> &PyDict {
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>
where
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
K: ToPyObject,
V: ToPyObject,
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);
for (key, value) in self {
dict.set_item(key, value)
.expect("Failed to set_item on dict");
}
dict.into_ptr()
dict
}
}
@ -265,10 +256,11 @@ where
mod test {
use conversion::{IntoPyObject, PyTryFrom, ToPyObject};
use instance::AsPyRef;
use objects::dict::IntoPyDict;
use objects::{PyDict, PyTuple};
use python::{IntoPyDictPointer, Python};
use python::Python;
use std::collections::{BTreeMap, HashMap};
use {ObjectProtocol, PyObject};
use ObjectProtocol;
#[test]
fn test_new() {
@ -558,12 +550,10 @@ mod test {
let mut map = HashMap::<i32, i32>::new();
map.insert(1, 1);
let m = map.into_dict_ptr(py);
let ob = unsafe { PyObject::from_owned_ptr(py, m) };
let py_map = <PyDict as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
let py_map = map.into_py_dict(py);
assert!(py_map.len() == 1);
assert!(py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
assert_eq!(py_map.len(), 1);
assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);
}
#[test]
@ -589,12 +579,10 @@ mod test {
let mut map = BTreeMap::<i32, i32>::new();
map.insert(1, 1);
let m = map.into_dict_ptr(py);
let ob = unsafe { PyObject::from_owned_ptr(py, m) };
let py_map = <PyDict as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
let py_map = map.into_py_dict(py);
assert!(py_map.len() == 1);
assert!(py_map.get_item(1).unwrap().extract::<i32>().unwrap() == 1);
assert_eq!(py_map.len(), 1);
assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);
}
#[test]
@ -602,12 +590,10 @@ mod test {
let gil = Python::acquire_gil();
let py = gil.python();
let map = vec![("a", 1), ("b", 2), ("c", 3)];
let m = map.into_dict_ptr(py);
let ob = unsafe { PyObject::from_owned_ptr(py, m) };
let py_map = <PyDict as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
let vec = vec![("a", 1), ("b", 2), ("c", 3)];
let py_map = vec.into_py_dict(py);
assert!(py_map.len() == 3);
assert!(py_map.get_item("b").unwrap().extract::<i32>().unwrap() == 2);
assert_eq!(py_map.len(), 3);
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::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo};
pub use self::datetime::{PyDateAccess, PyTimeAccess};
pub use self::dict::IntoPyDict;
pub use self::dict::PyDict;
pub use self::floatob::PyFloat;
pub use self::iterator::PyIterator;

View file

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

View file

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

View file

@ -60,23 +60,15 @@ pub trait IntoPyPointer {
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.
impl<'p, T> ToPyPointer for Option<&'p T>
impl<T> ToPyPointer for Option<T>
where
T: ToPyPointer,
{
#[inline]
default fn as_ptr(&self) -> *mut ffi::PyObject {
fn as_ptr(&self) -> *mut ffi::PyObject {
match *self {
Some(t) => t.as_ptr(),
Some(ref t) => t.as_ptr(),
None => std::ptr::null_mut(),
}
}
@ -102,10 +94,12 @@ where
T: ToPyPointer,
{
#[inline]
default fn into_ptr(self) -> *mut ffi::PyObject {
fn into_ptr(self) -> *mut ffi::PyObject {
let ptr = self.as_ptr();
unsafe {
ffi::Py_INCREF(ptr);
if ptr != std::ptr::null_mut() {
unsafe {
ffi::Py_INCREF(ptr);
}
}
ptr
}

View file

@ -250,36 +250,15 @@ where
Ok(obj)
}
#[cfg(Py_3)]
default unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
Self::drop(py, obj);
if ffi::PyObject_CallFinalizerFromDealloc(obj) < 0 {
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(Py_3)]
{
if ffi::PyObject_CallFinalizerFromDealloc(obj) < 0 {
return;
}
}
}
#[cfg(not(Py_3))]
default unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
Self::drop(py, obj);
match (*T::type_object()).tp_free {
Some(free) => free(obj as *mut c_void),
@ -357,7 +336,7 @@ where
/// Register new type in python object system.
#[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
T: PyObjectAlloc<T> + PyTypeInfo,
{

View file

@ -24,7 +24,7 @@ macro_rules! py_run {
d.set_item(stringify!($val), &$val).unwrap();
$py.run(&common::indoc($code), None, Some(d))
.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 typeobj = py.get_type::<EmptyClass>();
// 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'");
}

View file

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

View file

@ -62,6 +62,6 @@ fn inheritance_with_new_methods() {
let py = gil.python();
let _typebase = py.get_type::<BaseClass>();
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");
}

View file

@ -252,5 +252,4 @@ fn meth_args() {
inst,
"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);
}