Refactor `#[pyproto]` Result types

This commit is contained in:
David Hewitt 2020-06-23 10:07:16 +01:00
parent 4c04268bdb
commit c7a4b4770f
16 changed files with 305 additions and 528 deletions

View File

@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Update `num-bigint` optional dependendency from `0.2` to `0.3`. [#978](https://github.com/PyO3/pyo3/pull/978) - Update `num-bigint` optional dependendency from `0.2` to `0.3`. [#978](https://github.com/PyO3/pyo3/pull/978)
- `#[pyproto]` is re-implemented without specialization. [#961](https://github.com/PyO3/pyo3/pull/961) - `#[pyproto]` is re-implemented without specialization. [#961](https://github.com/PyO3/pyo3/pull/961)
- `PyClassAlloc::alloc` is renamed to `PyClassAlloc::new`. [#990](https://github.com/PyO3/pyo3/pull/990) - `PyClassAlloc::alloc` is renamed to `PyClassAlloc::new`. [#990](https://github.com/PyO3/pyo3/pull/990)
- `#[pyproto]` methods can now have return value `T` or `PyResult<T>` (previously only `PyResult<T>` was supported). [#996](https://github.com/PyO3/pyo3/pull/996)
### Removed ### Removed
- Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930) - Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930)
@ -34,6 +35,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed ### Fixed
- Fix passing explicit `None` to `Option<T>` argument `#[pyfunction]` with a default value. [#936](https://github.com/PyO3/pyo3/pull/936) - Fix passing explicit `None` to `Option<T>` argument `#[pyfunction]` with a default value. [#936](https://github.com/PyO3/pyo3/pull/936)
- Fix `PyClass.__new__`'s not respecting subclasses when inherited by a Python class. [#990](https://github.com/PyO3/pyo3/pull/990) - Fix `PyClass.__new__`'s not respecting subclasses when inherited by a Python class. [#990](https://github.com/PyO3/pyo3/pull/990)
- Fix returning `Option<T>` from `#[pyproto]` methods. [#996](https://github.com/PyO3/pyo3/pull/996)
## [0.10.1] - 2020-05-14 ## [0.10.1] - 2020-05-14
### Fixed ### Fixed

View File

@ -688,6 +688,9 @@ mapping or number protocols. PyO3 defines separate traits for each of them. To p
Python object behavior, you need to implement the specific trait for your struct. Important note, Python object behavior, you need to implement the specific trait for your struct. Important note,
each protocol implementation block has to be annotated with the `#[pyproto]` attribute. each protocol implementation block has to be annotated with the `#[pyproto]` attribute.
All `#[pyproto]` methods which can be defined below can return `T` instead of `PyResult<T>` if the
method implementation is infallible.
### Basic object customization ### Basic object customization
The [`PyObjectProtocol`] trait provides several basic customizations. The [`PyObjectProtocol`] trait provides several basic customizations.
@ -823,11 +826,11 @@ struct MyIterator {
#[pyproto] #[pyproto]
impl PyIterProtocol for MyIterator { impl PyIterProtocol for MyIterator {
fn __iter__(slf: PyRef<Self>) -> PyResult<Py<MyIterator>> { fn __iter__(slf: PyRef<Self>) -> Py<MyIterator> {
Ok(slf.into()) slf.into()
} }
fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<PyObject>> { fn __next__(mut slf: PyRefMut<Self>) -> Option<PyObject> {
Ok(slf.iter.next()) slf.iter.next()
} }
} }
``` ```
@ -848,12 +851,12 @@ struct Iter {
#[pyproto] #[pyproto]
impl PyIterProtocol for Iter { impl PyIterProtocol for Iter {
fn __iter__(slf: PyRefMut<Self>) -> PyResult<Py<Iter>> { fn __iter__(slf: PyRefMut<Self>) -> Py<Iter> {
Ok(slf.into()) slf.into()
} }
fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<usize>> { fn __next__(mut slf: PyRefMut<Self>) -> Option<usize> {
Ok(slf.inner.next()) slf.inner.next()
} }
} }
@ -868,7 +871,7 @@ impl PyIterProtocol for Container {
let iter = Iter { let iter = Iter {
inner: slf.iter.clone().into_iter(), inner: slf.iter.clone().into_iter(),
}; };
PyCell::new(slf.py(), iter).map(Into::into) Py::new(slf.py(), iter)
} }
} }

View File

@ -89,57 +89,47 @@ pub const OBJECT: Proto = Proto {
MethodProto::Binary { MethodProto::Binary {
name: "__getattr__", name: "__getattr__",
arg: "Name", arg: "Name",
pyres: true,
proto: "pyo3::class::basic::PyObjectGetAttrProtocol", proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
}, },
MethodProto::Ternary { MethodProto::Ternary {
name: "__setattr__", name: "__setattr__",
arg1: "Name", arg1: "Name",
arg2: "Value", arg2: "Value",
pyres: false,
proto: "pyo3::class::basic::PyObjectSetAttrProtocol", proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__delattr__", name: "__delattr__",
arg: "Name", arg: "Name",
pyres: false,
proto: "pyo3::class::basic::PyObjectDelAttrProtocol", proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__str__", name: "__str__",
pyres: true,
proto: "pyo3::class::basic::PyObjectStrProtocol", proto: "pyo3::class::basic::PyObjectStrProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__repr__", name: "__repr__",
pyres: true,
proto: "pyo3::class::basic::PyObjectReprProtocol", proto: "pyo3::class::basic::PyObjectReprProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__format__", name: "__format__",
arg: "Format", arg: "Format",
pyres: true,
proto: "pyo3::class::basic::PyObjectFormatProtocol", proto: "pyo3::class::basic::PyObjectFormatProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__hash__", name: "__hash__",
pyres: false,
proto: "pyo3::class::basic::PyObjectHashProtocol", proto: "pyo3::class::basic::PyObjectHashProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__bytes__", name: "__bytes__",
pyres: true,
proto: "pyo3::class::basic::PyObjectBytesProtocol", proto: "pyo3::class::basic::PyObjectBytesProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__richcmp__", name: "__richcmp__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::basic::PyObjectRichcmpProtocol", proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__bool__", name: "__bool__",
pyres: false,
proto: "pyo3::class::basic::PyObjectBoolProtocol", proto: "pyo3::class::basic::PyObjectBoolProtocol",
}, },
], ],
@ -173,24 +163,20 @@ pub const ASYNC: Proto = Proto {
MethodProto::UnaryS { MethodProto::UnaryS {
name: "__await__", name: "__await__",
arg: "Receiver", arg: "Receiver",
pyres: true,
proto: "pyo3::class::pyasync::PyAsyncAwaitProtocol", proto: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
}, },
MethodProto::UnaryS { MethodProto::UnaryS {
name: "__aiter__", name: "__aiter__",
arg: "Receiver", arg: "Receiver",
pyres: true,
proto: "pyo3::class::pyasync::PyAsyncAiterProtocol", proto: "pyo3::class::pyasync::PyAsyncAiterProtocol",
}, },
MethodProto::UnaryS { MethodProto::UnaryS {
name: "__anext__", name: "__anext__",
arg: "Receiver", arg: "Receiver",
pyres: true,
proto: "pyo3::class::pyasync::PyAsyncAnextProtocol", proto: "pyo3::class::pyasync::PyAsyncAnextProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__aenter__", name: "__aenter__",
pyres: true,
proto: "pyo3::class::pyasync::PyAsyncAenterProtocol", proto: "pyo3::class::pyasync::PyAsyncAenterProtocol",
}, },
MethodProto::Quaternary { MethodProto::Quaternary {
@ -225,12 +211,10 @@ pub const BUFFER: Proto = Proto {
methods: &[ methods: &[
MethodProto::Unary { MethodProto::Unary {
name: "bf_getbuffer", name: "bf_getbuffer",
pyres: false,
proto: "pyo3::class::buffer::PyBufferGetBufferProtocol", proto: "pyo3::class::buffer::PyBufferGetBufferProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "bf_releasebuffer", name: "bf_releasebuffer",
pyres: false,
proto: "pyo3::class::buffer::PyBufferReleaseBufferProtocol", proto: "pyo3::class::buffer::PyBufferReleaseBufferProtocol",
}, },
], ],
@ -248,7 +232,6 @@ pub const CONTEXT: Proto = Proto {
methods: &[ methods: &[
MethodProto::Unary { MethodProto::Unary {
name: "__enter__", name: "__enter__",
pyres: true,
proto: "pyo3::class::context::PyContextEnterProtocol", proto: "pyo3::class::context::PyContextEnterProtocol",
}, },
MethodProto::Quaternary { MethodProto::Quaternary {
@ -303,7 +286,6 @@ pub const DESCR: Proto = Proto {
arg1: "Receiver", arg1: "Receiver",
arg2: "Inst", arg2: "Inst",
arg3: "Owner", arg3: "Owner",
pyres: true,
proto: "pyo3::class::descr::PyDescrGetProtocol", proto: "pyo3::class::descr::PyDescrGetProtocol",
}, },
MethodProto::TernaryS { MethodProto::TernaryS {
@ -311,19 +293,16 @@ pub const DESCR: Proto = Proto {
arg1: "Receiver", arg1: "Receiver",
arg2: "Inst", arg2: "Inst",
arg3: "Value", arg3: "Value",
pyres: false,
proto: "pyo3::class::descr::PyDescrSetProtocol", proto: "pyo3::class::descr::PyDescrSetProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__det__", name: "__det__",
arg: "Inst", arg: "Inst",
pyres: false,
proto: "pyo3::class::descr::PyDescrDelProtocol", proto: "pyo3::class::descr::PyDescrDelProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__set_name__", name: "__set_name__",
arg: "Inst", arg: "Inst",
pyres: false,
proto: "pyo3::class::descr::PyDescrSetNameProtocol", proto: "pyo3::class::descr::PyDescrSetNameProtocol",
}, },
], ],
@ -349,13 +328,11 @@ pub const ITER: Proto = Proto {
MethodProto::UnaryS { MethodProto::UnaryS {
name: "__iter__", name: "__iter__",
arg: "Receiver", arg: "Receiver",
pyres: true,
proto: "pyo3::class::iter::PyIterIterProtocol", proto: "pyo3::class::iter::PyIterIterProtocol",
}, },
MethodProto::UnaryS { MethodProto::UnaryS {
name: "__next__", name: "__next__",
arg: "Receiver", arg: "Receiver",
pyres: true,
proto: "pyo3::class::iter::PyIterNextProtocol", proto: "pyo3::class::iter::PyIterNextProtocol",
}, },
], ],
@ -372,31 +349,26 @@ pub const MAPPING: Proto = Proto {
methods: &[ methods: &[
MethodProto::Unary { MethodProto::Unary {
name: "__len__", name: "__len__",
pyres: false,
proto: "pyo3::class::mapping::PyMappingLenProtocol", proto: "pyo3::class::mapping::PyMappingLenProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__getitem__", name: "__getitem__",
arg: "Key", arg: "Key",
pyres: true,
proto: "pyo3::class::mapping::PyMappingGetItemProtocol", proto: "pyo3::class::mapping::PyMappingGetItemProtocol",
}, },
MethodProto::Ternary { MethodProto::Ternary {
name: "__setitem__", name: "__setitem__",
arg1: "Key", arg1: "Key",
arg2: "Value", arg2: "Value",
pyres: false,
proto: "pyo3::class::mapping::PyMappingSetItemProtocol", proto: "pyo3::class::mapping::PyMappingSetItemProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__delitem__", name: "__delitem__",
arg: "Key", arg: "Key",
pyres: false,
proto: "pyo3::class::mapping::PyMappingDelItemProtocol", proto: "pyo3::class::mapping::PyMappingDelItemProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__reversed__", name: "__reversed__",
pyres: true,
proto: "pyo3::class::mapping::PyMappingReversedProtocol", proto: "pyo3::class::mapping::PyMappingReversedProtocol",
}, },
], ],
@ -424,56 +396,47 @@ pub const SEQ: Proto = Proto {
methods: &[ methods: &[
MethodProto::Unary { MethodProto::Unary {
name: "__len__", name: "__len__",
pyres: false,
proto: "pyo3::class::sequence::PySequenceLenProtocol", proto: "pyo3::class::sequence::PySequenceLenProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__getitem__", name: "__getitem__",
arg: "Index", arg: "Index",
pyres: true,
proto: "pyo3::class::sequence::PySequenceGetItemProtocol", proto: "pyo3::class::sequence::PySequenceGetItemProtocol",
}, },
MethodProto::Ternary { MethodProto::Ternary {
name: "__setitem__", name: "__setitem__",
arg1: "Index", arg1: "Index",
arg2: "Value", arg2: "Value",
pyres: false,
proto: "pyo3::class::sequence::PySequenceSetItemProtocol", proto: "pyo3::class::sequence::PySequenceSetItemProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__delitem__", name: "__delitem__",
arg: "Index", arg: "Index",
pyres: false,
proto: "pyo3::class::sequence::PySequenceDelItemProtocol", proto: "pyo3::class::sequence::PySequenceDelItemProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__contains__", name: "__contains__",
arg: "Item", arg: "Item",
pyres: false,
proto: "pyo3::class::sequence::PySequenceContainsProtocol", proto: "pyo3::class::sequence::PySequenceContainsProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__concat__", name: "__concat__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::sequence::PySequenceConcatProtocol", proto: "pyo3::class::sequence::PySequenceConcatProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__repeat__", name: "__repeat__",
arg: "Index", arg: "Index",
pyres: true,
proto: "pyo3::class::sequence::PySequenceRepeatProtocol", proto: "pyo3::class::sequence::PySequenceRepeatProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__inplace_concat__", name: "__inplace_concat__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::sequence::PySequenceInplaceConcatProtocol", proto: "pyo3::class::sequence::PySequenceInplaceConcatProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__inplace_repeat__", name: "__inplace_repeat__",
arg: "Index", arg: "Index",
pyres: true,
proto: "pyo3::class::sequence::PySequenceInplaceRepeatProtocol", proto: "pyo3::class::sequence::PySequenceInplaceRepeatProtocol",
}, },
], ],
@ -505,56 +468,48 @@ pub const NUM: Proto = Proto {
name: "__add__", name: "__add__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberAddProtocol", proto: "pyo3::class::number::PyNumberAddProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__sub__", name: "__sub__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberSubProtocol", proto: "pyo3::class::number::PyNumberSubProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__mul__", name: "__mul__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberMulProtocol", proto: "pyo3::class::number::PyNumberMulProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__matmul__", name: "__matmul__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberMatmulProtocol", proto: "pyo3::class::number::PyNumberMatmulProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__truediv__", name: "__truediv__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberTruedivProtocol", proto: "pyo3::class::number::PyNumberTruedivProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__floordiv__", name: "__floordiv__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberFloordivProtocol", proto: "pyo3::class::number::PyNumberFloordivProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__mod__", name: "__mod__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberModProtocol", proto: "pyo3::class::number::PyNumberModProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__divmod__", name: "__divmod__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberDivmodProtocol", proto: "pyo3::class::number::PyNumberDivmodProtocol",
}, },
MethodProto::TernaryS { MethodProto::TernaryS {
@ -562,251 +517,209 @@ pub const NUM: Proto = Proto {
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
arg3: "Modulo", arg3: "Modulo",
pyres: true,
proto: "pyo3::class::number::PyNumberPowProtocol", proto: "pyo3::class::number::PyNumberPowProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__lshift__", name: "__lshift__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberLShiftProtocol", proto: "pyo3::class::number::PyNumberLShiftProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__rshift__", name: "__rshift__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberRShiftProtocol", proto: "pyo3::class::number::PyNumberRShiftProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__and__", name: "__and__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberAndProtocol", proto: "pyo3::class::number::PyNumberAndProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__xor__", name: "__xor__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberXorProtocol", proto: "pyo3::class::number::PyNumberXorProtocol",
}, },
MethodProto::BinaryS { MethodProto::BinaryS {
name: "__or__", name: "__or__",
arg1: "Left", arg1: "Left",
arg2: "Right", arg2: "Right",
pyres: true,
proto: "pyo3::class::number::PyNumberOrProtocol", proto: "pyo3::class::number::PyNumberOrProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__radd__", name: "__radd__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRAddProtocol", proto: "pyo3::class::number::PyNumberRAddProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rsub__", name: "__rsub__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRSubProtocol", proto: "pyo3::class::number::PyNumberRSubProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rmul__", name: "__rmul__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRMulProtocol", proto: "pyo3::class::number::PyNumberRMulProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rmatmul__", name: "__rmatmul__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRMatmulProtocol", proto: "pyo3::class::number::PyNumberRMatmulProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rtruediv__", name: "__rtruediv__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRTruedivProtocol", proto: "pyo3::class::number::PyNumberRTruedivProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rfloordiv__", name: "__rfloordiv__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRFloordivProtocol", proto: "pyo3::class::number::PyNumberRFloordivProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rmod__", name: "__rmod__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRModProtocol", proto: "pyo3::class::number::PyNumberRModProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rdivmod__", name: "__rdivmod__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRDivmodProtocol", proto: "pyo3::class::number::PyNumberRDivmodProtocol",
}, },
MethodProto::Ternary { MethodProto::Ternary {
name: "__rpow__", name: "__rpow__",
arg1: "Other", arg1: "Other",
arg2: "Modulo", arg2: "Modulo",
pyres: true,
proto: "pyo3::class::number::PyNumberRPowProtocol", proto: "pyo3::class::number::PyNumberRPowProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rlshift__", name: "__rlshift__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRLShiftProtocol", proto: "pyo3::class::number::PyNumberRLShiftProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rrshift__", name: "__rrshift__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRRShiftProtocol", proto: "pyo3::class::number::PyNumberRRShiftProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rand__", name: "__rand__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRAndProtocol", proto: "pyo3::class::number::PyNumberRAndProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__rxor__", name: "__rxor__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberRXorProtocol", proto: "pyo3::class::number::PyNumberRXorProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__ror__", name: "__ror__",
arg: "Other", arg: "Other",
pyres: true,
proto: "pyo3::class::number::PyNumberROrProtocol", proto: "pyo3::class::number::PyNumberROrProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__iadd__", name: "__iadd__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIAddProtocol", proto: "pyo3::class::number::PyNumberIAddProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__isub__", name: "__isub__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberISubProtocol", proto: "pyo3::class::number::PyNumberISubProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__imul__", name: "__imul__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIMulProtocol", proto: "pyo3::class::number::PyNumberIMulProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__imatmul__", name: "__imatmul__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIMatmulProtocol", proto: "pyo3::class::number::PyNumberIMatmulProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__itruediv__", name: "__itruediv__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberITruedivProtocol", proto: "pyo3::class::number::PyNumberITruedivProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__ifloordiv__", name: "__ifloordiv__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIFloordivProtocol", proto: "pyo3::class::number::PyNumberIFloordivProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__imod__", name: "__imod__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIModProtocol", proto: "pyo3::class::number::PyNumberIModProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__ipow__", name: "__ipow__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIPowProtocol", proto: "pyo3::class::number::PyNumberIPowProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__ilshift__", name: "__ilshift__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberILShiftProtocol", proto: "pyo3::class::number::PyNumberILShiftProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__irshift__", name: "__irshift__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIRShiftProtocol", proto: "pyo3::class::number::PyNumberIRShiftProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__iand__", name: "__iand__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIAndProtocol", proto: "pyo3::class::number::PyNumberIAndProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__ixor__", name: "__ixor__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIXorProtocol", proto: "pyo3::class::number::PyNumberIXorProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__ior__", name: "__ior__",
arg: "Other", arg: "Other",
pyres: false,
proto: "pyo3::class::number::PyNumberIOrProtocol", proto: "pyo3::class::number::PyNumberIOrProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__neg__", name: "__neg__",
pyres: true,
proto: "pyo3::class::number::PyNumberNegProtocol", proto: "pyo3::class::number::PyNumberNegProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__pos__", name: "__pos__",
pyres: true,
proto: "pyo3::class::number::PyNumberPosProtocol", proto: "pyo3::class::number::PyNumberPosProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__abs__", name: "__abs__",
pyres: true,
proto: "pyo3::class::number::PyNumberAbsProtocol", proto: "pyo3::class::number::PyNumberAbsProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__invert__", name: "__invert__",
pyres: true,
proto: "pyo3::class::number::PyNumberInvertProtocol", proto: "pyo3::class::number::PyNumberInvertProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__complex__", name: "__complex__",
pyres: true,
proto: "pyo3::class::number::PyNumberComplexProtocol", proto: "pyo3::class::number::PyNumberComplexProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__int__", name: "__int__",
pyres: true,
proto: "pyo3::class::number::PyNumberIntProtocol", proto: "pyo3::class::number::PyNumberIntProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__float__", name: "__float__",
pyres: true,
proto: "pyo3::class::number::PyNumberFloatProtocol", proto: "pyo3::class::number::PyNumberFloatProtocol",
}, },
MethodProto::Unary { MethodProto::Unary {
name: "__index__", name: "__index__",
pyres: true,
proto: "pyo3::class::number::PyNumberIndexProtocol", proto: "pyo3::class::number::PyNumberIndexProtocol",
}, },
MethodProto::Binary { MethodProto::Binary {
name: "__round__", name: "__round__",
arg: "NDigits", arg: "NDigits",
pyres: true,
proto: "pyo3::class::number::PyNumberRoundProtocol", proto: "pyo3::class::number::PyNumberRoundProtocol",
}, },
], ],

View File

@ -15,33 +15,28 @@ pub enum MethodProto {
}, },
Unary { Unary {
name: &'static str, name: &'static str,
pyres: bool,
proto: &'static str, proto: &'static str,
}, },
UnaryS { UnaryS {
name: &'static str, name: &'static str,
arg: &'static str, arg: &'static str,
pyres: bool,
proto: &'static str, proto: &'static str,
}, },
Binary { Binary {
name: &'static str, name: &'static str,
arg: &'static str, arg: &'static str,
pyres: bool,
proto: &'static str, proto: &'static str,
}, },
BinaryS { BinaryS {
name: &'static str, name: &'static str,
arg1: &'static str, arg1: &'static str,
arg2: &'static str, arg2: &'static str,
pyres: bool,
proto: &'static str, proto: &'static str,
}, },
Ternary { Ternary {
name: &'static str, name: &'static str,
arg1: &'static str, arg1: &'static str,
arg2: &'static str, arg2: &'static str,
pyres: bool,
proto: &'static str, proto: &'static str,
}, },
TernaryS { TernaryS {
@ -49,7 +44,6 @@ pub enum MethodProto {
arg1: &'static str, arg1: &'static str,
arg2: &'static str, arg2: &'static str,
arg3: &'static str, arg3: &'static str,
pyres: bool,
proto: &'static str, proto: &'static str,
}, },
Quaternary { Quaternary {
@ -88,7 +82,7 @@ pub(crate) fn impl_method_proto(
}; };
} }
let ty = &*if let syn::ReturnType::Type(_, ref ty) = sig.output { let ret_ty = &*if let syn::ReturnType::Type(_, ref ty) = sig.output {
ty.clone() ty.clone()
} else { } else {
panic!("fn return type is not supported") panic!("fn return type is not supported")
@ -96,9 +90,8 @@ pub(crate) fn impl_method_proto(
match *meth { match *meth {
MethodProto::Free { .. } => unreachable!(), MethodProto::Free { .. } => unreachable!(),
MethodProto::Unary { pyres, proto, .. } => { MethodProto::Unary { proto, .. } => {
let p: syn::Path = syn::parse_str(proto).unwrap(); let p: syn::Path = syn::parse_str(proto).unwrap();
let (ty, succ) = get_res_success(ty);
let tmp: syn::ItemFn = syn::parse_quote! { let tmp: syn::ItemFn = syn::parse_quote! {
fn test(&self) -> <#cls as #p<'p>>::Result {} fn test(&self) -> <#cls as #p<'p>>::Result {}
@ -106,26 +99,14 @@ pub(crate) fn impl_method_proto(
sig.output = tmp.sig.output; sig.output = tmp.sig.output;
modify_self_ty(sig); modify_self_ty(sig);
if pyres { quote! {
quote! { impl<'p> #p<'p> for #cls {
impl<'p> #p<'p> for #cls { type Result = #ret_ty;
type Success = #succ;
type Result = #ty;
}
}
} else {
quote! {
impl<'p> #p<'p> for #cls {
type Result = #ty;
}
} }
} }
} }
MethodProto::UnaryS { MethodProto::UnaryS { proto, arg, .. } => {
pyres, proto, arg, ..
} => {
let p: syn::Path = syn::parse_str(proto).unwrap(); let p: syn::Path = syn::parse_str(proto).unwrap();
let (ty, succ) = get_res_success(ty);
let slf_name = syn::Ident::new(arg, Span::call_site()); let slf_name = syn::Ident::new(arg, Span::call_site());
let mut slf_ty = get_arg_ty(sig, 0); let mut slf_ty = get_arg_ty(sig, 0);
@ -156,29 +137,14 @@ pub(crate) fn impl_method_proto(
}); });
} }
if pyres { quote! {
quote! { impl<'p> #p<'p> for #cls {
impl<'p> #p<'p> for #cls { type #slf_name = #slf_ty;
type #slf_name = #slf_ty; type Result = #ret_ty;
type Success = #succ;
type Result = #ty;
}
}
} else {
quote! {
impl<'p> #p<'p> for #cls {
type #slf_name = #slf_ty;
type Result = #ty;
}
} }
} }
} }
MethodProto::Binary { MethodProto::Binary { name, arg, proto } => {
name,
arg,
pyres,
proto,
} => {
if sig.inputs.len() <= 1 { if sig.inputs.len() <= 1 {
println!("Not enough arguments for {}", name); println!("Not enough arguments for {}", name);
return TokenStream::new(); return TokenStream::new();
@ -187,7 +153,6 @@ pub(crate) fn impl_method_proto(
let p: syn::Path = syn::parse_str(proto).unwrap(); let p: syn::Path = syn::parse_str(proto).unwrap();
let arg_name = syn::Ident::new(arg, Span::call_site()); let arg_name = syn::Ident::new(arg, Span::call_site());
let arg_ty = get_arg_ty(sig, 1); let arg_ty = get_arg_ty(sig, 1);
let (ty, succ) = get_res_success(ty);
let tmp = extract_decl(syn::parse_quote! { let tmp = extract_decl(syn::parse_quote! {
fn test(&self,arg: <#cls as #p<'p>>::#arg_name)-> <#cls as #p<'p>>::Result {} fn test(&self,arg: <#cls as #p<'p>>::#arg_name)-> <#cls as #p<'p>>::Result {}
@ -200,20 +165,10 @@ pub(crate) fn impl_method_proto(
modify_arg_ty(sig, 1, &tmp, &tmp2); modify_arg_ty(sig, 1, &tmp, &tmp2);
modify_self_ty(sig); modify_self_ty(sig);
if pyres { quote! {
quote! { impl<'p> #p<'p> for #cls {
impl<'p> #p<'p> for #cls { type #arg_name = #arg_ty;
type #arg_name = #arg_ty; type Result = #ret_ty;
type Success = #succ;
type Result = #ty;
}
}
} else {
quote! {
impl<'p> #p<'p> for #cls {
type #arg_name = #arg_ty;
type Result = #ty;
}
} }
} }
} }
@ -221,7 +176,6 @@ pub(crate) fn impl_method_proto(
name, name,
arg1, arg1,
arg2, arg2,
pyres,
proto, proto,
} => { } => {
if sig.inputs.len() <= 1 { if sig.inputs.len() <= 1 {
@ -233,7 +187,6 @@ pub(crate) fn impl_method_proto(
let arg1_ty = get_arg_ty(sig, 0); let arg1_ty = get_arg_ty(sig, 0);
let arg2_name = syn::Ident::new(arg2, Span::call_site()); let arg2_name = syn::Ident::new(arg2, Span::call_site());
let arg2_ty = get_arg_ty(sig, 1); let arg2_ty = get_arg_ty(sig, 1);
let (ty, succ) = get_res_success(ty);
// rewrite ty // rewrite ty
let tmp = extract_decl(syn::parse_quote! {fn test( let tmp = extract_decl(syn::parse_quote! {fn test(
@ -247,22 +200,11 @@ pub(crate) fn impl_method_proto(
modify_arg_ty(sig, 0, &tmp, &tmp2); modify_arg_ty(sig, 0, &tmp, &tmp2);
modify_arg_ty(sig, 1, &tmp, &tmp2); modify_arg_ty(sig, 1, &tmp, &tmp2);
if pyres { quote! {
quote! { impl<'p> #p<'p> for #cls {
impl<'p> #p<'p> for #cls { type #arg1_name = #arg1_ty;
type #arg1_name = #arg1_ty; type #arg2_name = #arg2_ty;
type #arg2_name = #arg2_ty; type Result = #ret_ty;
type Success = #succ;
type Result = #ty;
}
}
} else {
quote! {
impl<'p> #p<'p> for #cls {
type #arg1_name = #arg1_ty;
type #arg2_name = #arg2_ty;
type Result = #ty;
}
} }
} }
} }
@ -270,7 +212,6 @@ pub(crate) fn impl_method_proto(
name, name,
arg1, arg1,
arg2, arg2,
pyres,
proto, proto,
} => { } => {
if sig.inputs.len() <= 2 { if sig.inputs.len() <= 2 {
@ -282,7 +223,6 @@ pub(crate) fn impl_method_proto(
let arg1_ty = get_arg_ty(sig, 1); let arg1_ty = get_arg_ty(sig, 1);
let arg2_name = syn::Ident::new(arg2, Span::call_site()); let arg2_name = syn::Ident::new(arg2, Span::call_site());
let arg2_ty = get_arg_ty(sig, 2); let arg2_ty = get_arg_ty(sig, 2);
let (ty, succ) = get_res_success(ty);
// rewrite ty // rewrite ty
let tmp = extract_decl(syn::parse_quote! {fn test( let tmp = extract_decl(syn::parse_quote! {fn test(
@ -299,22 +239,11 @@ pub(crate) fn impl_method_proto(
modify_arg_ty(sig, 2, &tmp, &tmp2); modify_arg_ty(sig, 2, &tmp, &tmp2);
modify_self_ty(sig); modify_self_ty(sig);
if pyres { quote! {
quote! { impl<'p> #p<'p> for #cls {
impl<'p> #p<'p> for #cls { type #arg1_name = #arg1_ty;
type #arg1_name = #arg1_ty; type #arg2_name = #arg2_ty;
type #arg2_name = #arg2_ty; type Result = #ret_ty;
type Success = #succ;
type Result = #ty;
}
}
} else {
quote! {
impl<'p> #p<'p> for #cls {
type #arg1_name = #arg1_ty;
type #arg2_name = #arg2_ty;
type Result = #ty;
}
} }
} }
} }
@ -323,7 +252,6 @@ pub(crate) fn impl_method_proto(
arg1, arg1,
arg2, arg2,
arg3, arg3,
pyres,
proto, proto,
} => { } => {
if sig.inputs.len() <= 2 { if sig.inputs.len() <= 2 {
@ -337,7 +265,6 @@ pub(crate) fn impl_method_proto(
let arg2_ty = get_arg_ty(sig, 1); let arg2_ty = get_arg_ty(sig, 1);
let arg3_name = syn::Ident::new(arg3, Span::call_site()); let arg3_name = syn::Ident::new(arg3, Span::call_site());
let arg3_ty = get_arg_ty(sig, 2); let arg3_ty = get_arg_ty(sig, 2);
let (ty, succ) = get_res_success(ty);
// rewrite ty // rewrite ty
let tmp = extract_decl(syn::parse_quote! {fn test( let tmp = extract_decl(syn::parse_quote! {fn test(
@ -354,24 +281,12 @@ pub(crate) fn impl_method_proto(
modify_arg_ty(sig, 1, &tmp, &tmp2); modify_arg_ty(sig, 1, &tmp, &tmp2);
modify_arg_ty(sig, 2, &tmp, &tmp2); modify_arg_ty(sig, 2, &tmp, &tmp2);
if pyres { quote! {
quote! { impl<'p> #p<'p> for #cls {
impl<'p> #p<'p> for #cls { type #arg1_name = #arg1_ty;
type #arg1_name = #arg1_ty; type #arg2_name = #arg2_ty;
type #arg2_name = #arg2_ty; type #arg3_name = #arg3_ty;
type #arg3_name = #arg3_ty; type Result = #ret_ty;
type Success = #succ;
type Result = #ty;
}
}
} else {
quote! {
impl<'p> #p<'p> for #cls {
type #arg1_name = #arg1_ty;
type #arg2_name = #arg2_ty;
type #arg3_name = #arg3_ty;
type Result = #ty;
}
} }
} }
} }
@ -393,7 +308,6 @@ pub(crate) fn impl_method_proto(
let arg2_ty = get_arg_ty(sig, 2); let arg2_ty = get_arg_ty(sig, 2);
let arg3_name = syn::Ident::new(arg3, Span::call_site()); let arg3_name = syn::Ident::new(arg3, Span::call_site());
let arg3_ty = get_arg_ty(sig, 3); let arg3_ty = get_arg_ty(sig, 3);
let (ty, succ) = get_res_success(ty);
// rewrite ty // rewrite ty
let tmp = extract_decl(syn::parse_quote! {fn test( let tmp = extract_decl(syn::parse_quote! {fn test(
@ -418,8 +332,7 @@ pub(crate) fn impl_method_proto(
type #arg1_name = #arg1_ty; type #arg1_name = #arg1_ty;
type #arg2_name = #arg2_ty; type #arg2_name = #arg2_ty;
type #arg3_name = #arg3_ty; type #arg3_name = #arg3_ty;
type Success = #succ; type Result = #ret_ty;
type Result = #ty;
} }
} }
} }
@ -460,62 +373,6 @@ fn get_arg_ty(sig: &syn::Signature, idx: usize) -> syn::Type {
ty ty
} }
// Success
fn get_res_success(ty: &syn::Type) -> (TokenStream, syn::GenericArgument) {
let mut result;
let mut succ;
match ty {
syn::Type::Path(ref typath) => {
if let Some(segment) = typath.path.segments.last() {
match segment.ident.to_string().as_str() {
// check for PyResult<T>
"PyResult" => match segment.arguments {
syn::PathArguments::AngleBracketed(ref data) => {
result = true;
succ = data.args[0].clone();
// check for PyResult<Option<T>>
if let syn::GenericArgument::Type(syn::Type::Path(ref typath)) =
data.args[0]
{
if let Some(segment) = typath.path.segments.last() {
if "Option" == segment.ident.to_string().as_str() {
// get T from Option<T>
if let syn::PathArguments::AngleBracketed(ref data) =
segment.arguments
{
result = false;
succ = data.args[0].clone();
}
}
}
}
}
_ => panic!("fn result type is not supported"),
},
_ => panic!(
"fn result type has to be PyResult or (), got {:?}",
segment.ident
),
}
} else {
panic!("fn result is not supported {:?}", typath)
}
}
_ => panic!("not supported: {:?}", ty),
};
// result
let res = if result {
quote! {PyResult<#succ>}
} else {
quote! {#ty}
};
(res, succ)
}
fn extract_decl(spec: syn::Item) -> syn::Signature { fn extract_decl(spec: syn::Item) -> syn::Signature {
match spec { match spec {
syn::Item::Fn(f) => f.sig, syn::Item::Fn(f) => f.sig,

View File

@ -79,19 +79,40 @@ impl IntoPyCallbackOutput<()> for () {
} }
} }
pub struct LenCallbackOutput(pub usize); impl IntoPyCallbackOutput<ffi::Py_ssize_t> for usize {
impl IntoPyCallbackOutput<ffi::Py_ssize_t> for LenCallbackOutput {
#[inline] #[inline]
fn convert(self, _py: Python) -> PyResult<ffi::Py_ssize_t> { fn convert(self, _py: Python) -> PyResult<ffi::Py_ssize_t> {
if self.0 <= (isize::MAX as usize) { if self <= (isize::MAX as usize) {
Ok(self.0 as isize) Ok(self as isize)
} else { } else {
Err(OverflowError::py_err(())) Err(OverflowError::py_err(()))
} }
} }
} }
// Converters needed for `#[pyproto]` implementations
impl IntoPyCallbackOutput<bool> for bool {
fn convert(self, _: Python) -> PyResult<bool> {
Ok(self)
}
}
impl IntoPyCallbackOutput<usize> for usize {
fn convert(self, _: Python) -> PyResult<usize> {
Ok(self)
}
}
impl<T> IntoPyCallbackOutput<PyObject> for T
where
T: IntoPy<PyObject>,
{
fn convert(self, py: Python) -> PyResult<PyObject> {
Ok(self.into_py(py))
}
}
pub trait WrappingCastTo<T> { pub trait WrappingCastTo<T> {
fn wrapping_cast(self) -> T; fn wrapping_cast(self) -> T;
} }
@ -117,15 +138,12 @@ wrapping_cast!(i32, Py_hash_t);
wrapping_cast!(isize, Py_hash_t); wrapping_cast!(isize, Py_hash_t);
wrapping_cast!(i64, Py_hash_t); wrapping_cast!(i64, Py_hash_t);
pub struct HashCallbackOutput<T>(pub T); pub struct HashCallbackOutput(Py_hash_t);
impl<T> IntoPyCallbackOutput<Py_hash_t> for HashCallbackOutput<T> impl IntoPyCallbackOutput<Py_hash_t> for HashCallbackOutput {
where
T: WrappingCastTo<Py_hash_t>,
{
#[inline] #[inline]
fn convert(self, _py: Python) -> PyResult<Py_hash_t> { fn convert(self, _py: Python) -> PyResult<Py_hash_t> {
let hash = self.0.wrapping_cast(); let hash = self.0;
if hash == -1 { if hash == -1 {
Ok(-2) Ok(-2)
} else { } else {
@ -134,6 +152,16 @@ where
} }
} }
impl<T> IntoPyCallbackOutput<HashCallbackOutput> for T
where
T: WrappingCastTo<Py_hash_t>,
{
#[inline]
fn convert(self, _py: Python) -> PyResult<HashCallbackOutput> {
Ok(HashCallbackOutput(self.wrapping_cast()))
}
}
#[doc(hidden)] #[doc(hidden)]
#[inline] #[inline]
pub fn convert<T, U>(py: Python, value: T) -> PyResult<U> pub fn convert<T, U>(py: Python, value: T) -> PyResult<U>

View File

@ -8,10 +8,8 @@
//! Parts of the documentation are copied from the respective methods from the //! Parts of the documentation are copied from the respective methods from the
//! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html) //! [typeobj docs](https://docs.python.org/3/c-api/typeobj.html)
use crate::callback::HashCallbackOutput; use crate::callback::{HashCallbackOutput, IntoPyCallbackOutput};
use crate::{ use crate::{exceptions, ffi, FromPyObject, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult};
exceptions, ffi, FromPyObject, IntoPy, PyAny, PyCell, PyClass, PyErr, PyObject, PyResult,
};
use std::os::raw::c_int; use std::os::raw::c_int;
/// Operators for the __richcmp__ method /// Operators for the __richcmp__ method
@ -100,45 +98,39 @@ pub trait PyObjectProtocol<'p>: PyClass {
pub trait PyObjectGetAttrProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectGetAttrProtocol<'p>: PyObjectProtocol<'p> {
type Name: FromPyObject<'p>; type Name: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyObjectSetAttrProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectSetAttrProtocol<'p>: PyObjectProtocol<'p> {
type Name: FromPyObject<'p>; type Name: FromPyObject<'p>;
type Value: FromPyObject<'p>; type Value: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyObjectDelAttrProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectDelAttrProtocol<'p>: PyObjectProtocol<'p> {
type Name: FromPyObject<'p>; type Name: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyObjectStrProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectStrProtocol<'p>: PyObjectProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyObjectReprProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectReprProtocol<'p>: PyObjectProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyObjectFormatProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectFormatProtocol<'p>: PyObjectProtocol<'p> {
type Format: FromPyObject<'p>; type Format: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyObjectHashProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectHashProtocol<'p>: PyObjectProtocol<'p> {
type Result: Into<PyResult<isize>>; type Result: IntoPyCallbackOutput<HashCallbackOutput>;
} }
pub trait PyObjectBoolProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectBoolProtocol<'p>: PyObjectProtocol<'p> {
type Result: Into<PyResult<bool>>; type Result: IntoPyCallbackOutput<bool>;
} }
pub trait PyObjectBytesProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectBytesProtocol<'p>: PyObjectProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> { pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
/// All FFI functions for basic protocols. /// All FFI functions for basic protocols.
@ -180,12 +172,7 @@ impl PyObjectMethods {
where where
T: for<'p> PyObjectHashProtocol<'p>, T: for<'p> PyObjectHashProtocol<'p>,
{ {
self.tp_hash = py_unary_func!( self.tp_hash = py_unary_func!(PyObjectHashProtocol, T::__hash__, ffi::Py_hash_t);
PyObjectHashProtocol,
T::__hash__,
ffi::Py_hash_t,
HashCallbackOutput
);
} }
pub fn set_getattr<T>(&mut self) pub fn set_getattr<T>(&mut self)
where where
@ -255,7 +242,7 @@ where
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<PyAny>(arg); let arg = py.from_borrowed_ptr::<PyAny>(arg);
call_ref!(slf, __getattr__, arg) call_ref!(slf, __getattr__, arg).convert(py)
}) })
} }
Some(wrap::<T>) Some(wrap::<T>)
@ -293,7 +280,7 @@ where
let op = extract_op(op)?; let op = extract_op(op)?;
let arg = arg.extract()?; let arg = arg.extract()?;
slf.try_borrow()?.__richcmp__(arg, op).into() slf.try_borrow()?.__richcmp__(arg, op).convert(py)
}) })
} }
Some(wrap::<T>) Some(wrap::<T>)

View File

@ -4,7 +4,7 @@
//! //!
//! For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html) //! For more information check [buffer protocol](https://docs.python.org/3/c-api/buffer.html)
//! c-api //! c-api
use crate::err::PyResult; use crate::callback::IntoPyCallbackOutput;
use crate::{ use crate::{
ffi::{self, PyBufferProcs}, ffi::{self, PyBufferProcs},
PyCell, PyClass, PyRefMut, PyCell, PyClass, PyRefMut,
@ -33,11 +33,11 @@ pub trait PyBufferProtocol<'p>: PyClass {
} }
pub trait PyBufferGetBufferProtocol<'p>: PyBufferProtocol<'p> { pub trait PyBufferGetBufferProtocol<'p>: PyBufferProtocol<'p> {
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyBufferReleaseBufferProtocol<'p>: PyBufferProtocol<'p> { pub trait PyBufferReleaseBufferProtocol<'p>: PyBufferProtocol<'p> {
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
/// Set functions used by `#[pyproto]`. /// Set functions used by `#[pyproto]`.
@ -71,7 +71,7 @@ where
{ {
crate::callback_body!(py, { crate::callback_body!(py, {
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).into() T::bf_getbuffer(slf.try_borrow_mut()?, arg1, arg2).convert(py)
}) })
} }
Some(wrap::<T>) Some(wrap::<T>)
@ -87,7 +87,7 @@ where
{ {
crate::callback_body!(py, { crate::callback_body!(py, {
let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).into() T::bf_releasebuffer(slf.try_borrow_mut()?, arg1).convert(py)
}) })
} }
Some(wrap::<T>) Some(wrap::<T>)

View File

@ -4,7 +4,7 @@
//! Trait and support implementation for context manager api //! Trait and support implementation for context manager api
//! //!
use crate::err::PyResult; use crate::callback::IntoPyCallbackOutput;
use crate::{PyClass, PyObject}; use crate::{PyClass, PyObject};
/// Context manager interface /// Context manager interface
@ -31,14 +31,12 @@ pub trait PyContextProtocol<'p>: PyClass {
} }
pub trait PyContextEnterProtocol<'p>: PyContextProtocol<'p> { pub trait PyContextEnterProtocol<'p>: PyContextProtocol<'p> {
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> { pub trait PyContextExitProtocol<'p>: PyContextProtocol<'p> {
type ExcType: crate::FromPyObject<'p>; type ExcType: crate::FromPyObject<'p>;
type ExcValue: crate::FromPyObject<'p>; type ExcValue: crate::FromPyObject<'p>;
type Traceback: crate::FromPyObject<'p>; type Traceback: crate::FromPyObject<'p>;
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }

View File

@ -5,9 +5,9 @@
//! [Python information]( //! [Python information](
//! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors) //! https://docs.python.org/3/reference/datamodel.html#implementing-descriptors)
use crate::err::PyResult; use crate::callback::IntoPyCallbackOutput;
use crate::types::PyAny; use crate::types::PyAny;
use crate::{ffi, FromPyObject, IntoPy, PyClass, PyObject}; use crate::{ffi, FromPyObject, PyClass, PyObject};
use std::os::raw::c_int; use std::os::raw::c_int;
/// Descriptor interface /// Descriptor interface
@ -50,25 +50,24 @@ pub trait PyDescrGetProtocol<'p>: PyDescrProtocol<'p> {
type Receiver: crate::derive_utils::TryFromPyCell<'p, Self>; type Receiver: crate::derive_utils::TryFromPyCell<'p, Self>;
type Inst: FromPyObject<'p>; type Inst: FromPyObject<'p>;
type Owner: FromPyObject<'p>; type Owner: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyDescrSetProtocol<'p>: PyDescrProtocol<'p> { pub trait PyDescrSetProtocol<'p>: PyDescrProtocol<'p> {
type Receiver: crate::derive_utils::TryFromPyCell<'p, Self>; type Receiver: crate::derive_utils::TryFromPyCell<'p, Self>;
type Inst: FromPyObject<'p>; type Inst: FromPyObject<'p>;
type Value: FromPyObject<'p>; type Value: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyDescrDeleteProtocol<'p>: PyDescrProtocol<'p> { pub trait PyDescrDeleteProtocol<'p>: PyDescrProtocol<'p> {
type Inst: FromPyObject<'p>; type Inst: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> { pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
type Inst: FromPyObject<'p>; type Inst: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
/// All FFI functions for description protocols. /// All FFI functions for description protocols.

View File

@ -30,14 +30,12 @@ pub trait PyIterProtocol<'p>: PyClass {
pub trait PyIterIterProtocol<'p>: PyIterProtocol<'p> { pub trait PyIterIterProtocol<'p>: PyIterProtocol<'p> {
type Receiver: TryFromPyCell<'p, Self>; type Receiver: TryFromPyCell<'p, Self>;
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyIterNextProtocol<'p>: PyIterProtocol<'p> { pub trait PyIterNextProtocol<'p>: PyIterProtocol<'p> {
type Receiver: TryFromPyCell<'p, Self>; type Receiver: TryFromPyCell<'p, Self>;
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<IterNextOutput>;
type Result: Into<PyResult<Option<Self::Success>>>;
} }
#[derive(Default)] #[derive(Default)]
@ -62,20 +60,26 @@ impl PyIterMethods {
where where
T: for<'p> PyIterNextProtocol<'p>, T: for<'p> PyIterNextProtocol<'p>,
{ {
self.tp_iternext = py_unarys_func!(PyIterNextProtocol, T::__next__, IterNextConverter); self.tp_iternext = py_unarys_func!(PyIterNextProtocol, T::__next__);
} }
} }
struct IterNextConverter<T>(Option<T>); pub struct IterNextOutput(Option<PyObject>);
impl<T> IntoPyCallbackOutput<*mut ffi::PyObject> for IterNextConverter<T> impl IntoPyCallbackOutput<*mut ffi::PyObject> for IterNextOutput {
where fn convert(self, _py: Python) -> PyResult<*mut ffi::PyObject> {
T: IntoPy<PyObject>,
{
fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> {
match self.0 { match self.0 {
Some(val) => Ok(val.into_py(py).into_ptr()), Some(o) => Ok(o.into_ptr()),
None => Err(crate::exceptions::StopIteration::py_err(())), None => Err(crate::exceptions::StopIteration::py_err(())),
} }
} }
} }
impl<T> IntoPyCallbackOutput<IterNextOutput> for Option<T>
where
T: IntoPy<PyObject>,
{
fn convert(self, py: Python) -> PyResult<IterNextOutput> {
Ok(IterNextOutput(self.map(|o| o.into_py(py))))
}
}

View File

@ -3,31 +3,31 @@
#[macro_export] #[macro_export]
#[doc(hidden)] #[doc(hidden)]
macro_rules! py_unary_func { macro_rules! py_unary_func {
($trait: ident, $class:ident :: $f:ident, $call:ident, $ret_type: ty $(, $conv:expr)?) => {{ ($trait: ident, $class:ident :: $f:ident, $call:ident, $ret_type: ty) => {{
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> $ret_type
where where
T: for<'p> $trait<'p>, T: for<'p> $trait<'p>,
{ {
$crate::callback_body!(py, { $crate::callback_body!(py, {
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
$call!(slf, $f)$(.map($conv))? $call!(slf, $f).convert(py)
}) })
} }
Some(wrap::<$class>) Some(wrap::<$class>)
}}; }};
// Use call_ref! by default // Use call_ref! by default
($trait:ident, $class:ident :: $f:ident, $ret_type:ty $(, $conv:expr)?) => { ($trait:ident, $class:ident :: $f:ident, $ret_type:ty) => {
py_unary_func!($trait, $class::$f, call_ref, $ret_type $(, $conv)?); py_unary_func!($trait, $class::$f, call_ref, $ret_type);
}; };
($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => { ($trait:ident, $class:ident :: $f:ident) => {
py_unary_func!($trait, $class::$f, call_ref, *mut $crate::ffi::PyObject $(, $conv)?); py_unary_func!($trait, $class::$f, call_ref, *mut $crate::ffi::PyObject);
}; };
} }
#[macro_export] #[macro_export]
#[doc(hidden)] #[doc(hidden)]
macro_rules! py_unarys_func { macro_rules! py_unarys_func {
($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => {{ ($trait:ident, $class:ident :: $f:ident) => {{
unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> *mut $crate::ffi::PyObject unsafe extern "C" fn wrap<T>(slf: *mut $crate::ffi::PyObject) -> *mut $crate::ffi::PyObject
where where
T: for<'p> $trait<'p>, T: for<'p> $trait<'p>,
@ -38,7 +38,7 @@ macro_rules! py_unarys_func {
<T::Receiver as $crate::derive_utils::TryFromPyCell<_>>::try_from_pycell(slf) <T::Receiver as $crate::derive_utils::TryFromPyCell<_>>::try_from_pycell(slf)
.map_err(|e| e.into())?; .map_err(|e| e.into())?;
$class::$f(borrow).into()$(.map($conv))? $class::$f(borrow).convert(py)
}) })
} }
Some(wrap::<$class>) Some(wrap::<$class>)
@ -49,12 +49,7 @@ macro_rules! py_unarys_func {
#[doc(hidden)] #[doc(hidden)]
macro_rules! py_len_func { macro_rules! py_len_func {
($trait:ident, $class:ident :: $f:ident) => { ($trait:ident, $class:ident :: $f:ident) => {
py_unary_func!( py_unary_func!($trait, $class::$f, $crate::ffi::Py_ssize_t)
$trait,
$class::$f,
$crate::ffi::Py_ssize_t,
$crate::callback::LenCallbackOutput
)
}; };
} }
@ -62,7 +57,7 @@ macro_rules! py_len_func {
#[doc(hidden)] #[doc(hidden)]
macro_rules! py_binary_func { macro_rules! py_binary_func {
// Use call_ref! by default // Use call_ref! by default
($trait:ident, $class:ident :: $f:ident, $return:ty, $call:ident $(, $conv:expr)?) => {{ ($trait:ident, $class:ident :: $f:ident, $return:ty, $call:ident) => {{
unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject, arg: *mut ffi::PyObject) -> $return unsafe extern "C" fn wrap<T>(slf: *mut ffi::PyObject, arg: *mut ffi::PyObject) -> $return
where where
T: for<'p> $trait<'p>, T: for<'p> $trait<'p>,
@ -70,16 +65,16 @@ macro_rules! py_binary_func {
$crate::callback_body!(py, { $crate::callback_body!(py, {
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg); let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg);
$call!(slf, $f, arg)$(.map($conv))? $call!(slf, $f, arg).convert(py)
}) })
} }
Some(wrap::<$class>) Some(wrap::<$class>)
}}; }};
($trait:ident, $class:ident :: $f:ident, $return:ty $(, $conv:expr)?) => { ($trait:ident, $class:ident :: $f:ident, $return:ty) => {
py_binary_func!($trait, $class::$f, $return, call_ref $(, $conv)?) py_binary_func!($trait, $class::$f, $return, call_ref)
}; };
($trait:ident, $class:ident :: $f:ident $(, $conv:expr)?) => { ($trait:ident, $class:ident :: $f:ident) => {
py_binary_func!($trait, $class::$f, *mut $crate::ffi::PyObject $(, $conv)?) py_binary_func!($trait, $class::$f, *mut $crate::ffi::PyObject)
}; };
} }
@ -98,7 +93,7 @@ macro_rules! py_binary_num_func {
let lhs = py.from_borrowed_ptr::<$crate::PyAny>(lhs); let lhs = py.from_borrowed_ptr::<$crate::PyAny>(lhs);
let rhs = py.from_borrowed_ptr::<$crate::PyAny>(rhs); let rhs = py.from_borrowed_ptr::<$crate::PyAny>(rhs);
$class::$f(lhs.extract()?, rhs.extract()?).into() $class::$f(lhs.extract()?, rhs.extract()?).convert(py)
}) })
} }
Some(wrap::<$class>) Some(wrap::<$class>)
@ -121,7 +116,7 @@ macro_rules! py_binary_reversed_num_func {
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(rhs); let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(rhs);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(lhs); let arg = py.from_borrowed_ptr::<$crate::PyAny>(lhs);
$class::$f(&*slf.try_borrow()?, arg.extract()?).into() $class::$f(&*slf.try_borrow()?, arg.extract()?).convert(py)
}) })
} }
Some(wrap::<$class>) Some(wrap::<$class>)
@ -143,7 +138,7 @@ macro_rules! py_binary_self_func {
$crate::callback_body!(py, { $crate::callback_body!(py, {
let slf_ = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf); let slf_ = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg); let arg = py.from_borrowed_ptr::<$crate::PyAny>(arg);
call_mut!(slf_, $f, arg)?; call_mut!(slf_, $f, arg).convert(py)?;
ffi::Py_INCREF(slf); ffi::Py_INCREF(slf);
Ok(slf) Ok(slf)
}) })
@ -169,7 +164,7 @@ macro_rules! py_ssizearg_func {
{ {
$crate::callback_body!(py, { $crate::callback_body!(py, {
let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
$call!(slf, $f; arg.into()) $call!(slf, $f; arg.into()).convert(py)
}) })
} }
Some(wrap::<$class>) Some(wrap::<$class>)
@ -200,7 +195,7 @@ macro_rules! py_ternarys_func {
.from_borrowed_ptr::<$crate::types::PyAny>(arg2) .from_borrowed_ptr::<$crate::types::PyAny>(arg2)
.extract()?; .extract()?;
$class::$f(slf, arg1, arg2).into() $class::$f(slf, arg1, arg2).convert(py)
}) })
} }
@ -234,7 +229,7 @@ macro_rules! py_ternary_num_func {
.from_borrowed_ptr::<$crate::types::PyAny>(arg3) .from_borrowed_ptr::<$crate::types::PyAny>(arg3)
.extract()?; .extract()?;
$class::$f(arg1, arg2, arg3).into() $class::$f(arg1, arg2, arg3).convert(py)
}) })
} }
@ -260,7 +255,7 @@ macro_rules! py_ternary_reversed_num_func {
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg3); let arg2 = py.from_borrowed_ptr::<$crate::PyAny>(arg3);
$class::$f(&*slf.try_borrow()?, arg1.extract()?, arg2.extract()?).into() $class::$f(&*slf.try_borrow()?, arg1.extract()?, arg2.extract()?).convert(py)
}) })
} }
Some(wrap::<$class>) Some(wrap::<$class>)
@ -284,7 +279,7 @@ macro_rules! py_dummy_ternary_self_func {
$crate::callback_body!(py, { $crate::callback_body!(py, {
let slf_cell = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf); let slf_cell = py.from_borrowed_ptr::<$crate::PyCell<T>>(slf);
let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1); let arg1 = py.from_borrowed_ptr::<$crate::PyAny>(arg1);
call_mut!(slf_cell, $f, arg1)?; call_mut!(slf_cell, $f, arg1).convert(py)?;
ffi::Py_INCREF(slf); ffi::Py_INCREF(slf);
Ok(slf) Ok(slf)
}) })
@ -316,7 +311,7 @@ macro_rules! py_func_set {
} else { } else {
let name = py.from_borrowed_ptr::<$crate::PyAny>(name); let name = py.from_borrowed_ptr::<$crate::PyAny>(name);
let value = py.from_borrowed_ptr::<$crate::PyAny>(value); let value = py.from_borrowed_ptr::<$crate::PyAny>(value);
call_mut!(slf, $fn_set, name, value) call_mut!(slf, $fn_set, name, value).convert(py)
} }
}) })
} }
@ -341,7 +336,7 @@ macro_rules! py_func_del {
let name = py let name = py
.from_borrowed_ptr::<$crate::types::PyAny>(name) .from_borrowed_ptr::<$crate::types::PyAny>(name)
.extract()?; .extract()?;
slf.try_borrow_mut()?.$fn_del(name).into() slf.try_borrow_mut()?.$fn_del(name).convert(py)
} else { } else {
Err(PyErr::new::<exceptions::NotImplementedError, _>( Err(PyErr::new::<exceptions::NotImplementedError, _>(
"Subscript assignment not supported", "Subscript assignment not supported",
@ -369,10 +364,10 @@ macro_rules! py_func_set_del {
let name = py.from_borrowed_ptr::<$crate::PyAny>(name); let name = py.from_borrowed_ptr::<$crate::PyAny>(name);
if value.is_null() { if value.is_null() {
call_mut!(slf, $fn_del, name) call_mut!(slf, $fn_del, name).convert(py)
} else { } else {
let value = py.from_borrowed_ptr::<$crate::PyAny>(value); let value = py.from_borrowed_ptr::<$crate::PyAny>(value);
call_mut!(slf, $fn_set, name, value) call_mut!(slf, $fn_set, name, value).convert(py)
} }
}) })
} }
@ -382,7 +377,7 @@ macro_rules! py_func_set_del {
macro_rules! _call_impl { macro_rules! _call_impl {
($slf: expr, $fn: ident $(; $args: expr)*) => { ($slf: expr, $fn: ident $(; $args: expr)*) => {
$slf.$fn($($args,)*).into() $slf.$fn($($args,)*)
}; };
($slf: expr, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => { ($slf: expr, $fn: ident, $raw_arg: expr $(,$raw_args: expr)* $(; $args: expr)*) => {
_call_impl!($slf, $fn $(,$raw_args)* $(;$args)* ;$raw_arg.extract()?) _call_impl!($slf, $fn $(,$raw_args)* $(;$args)* ;$raw_arg.extract()?)

View File

@ -3,8 +3,9 @@
//! Python Mapping Interface //! Python Mapping Interface
//! Trait and support implementation for implementing mapping support //! Trait and support implementation for implementing mapping support
use crate::err::{PyErr, PyResult}; use crate::callback::IntoPyCallbackOutput;
use crate::{exceptions, ffi, FromPyObject, IntoPy, PyClass, PyObject}; use crate::err::PyErr;
use crate::{exceptions, ffi, FromPyObject, PyClass, PyObject};
/// Mapping interface /// Mapping interface
#[allow(unused_variables)] #[allow(unused_variables)]
@ -49,29 +50,27 @@ pub trait PyMappingProtocol<'p>: PyClass {
// the existance of a slotted method. // the existance of a slotted method.
pub trait PyMappingLenProtocol<'p>: PyMappingProtocol<'p> { pub trait PyMappingLenProtocol<'p>: PyMappingProtocol<'p> {
type Result: Into<PyResult<usize>>; type Result: IntoPyCallbackOutput<usize>;
} }
pub trait PyMappingGetItemProtocol<'p>: PyMappingProtocol<'p> { pub trait PyMappingGetItemProtocol<'p>: PyMappingProtocol<'p> {
type Key: FromPyObject<'p>; type Key: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyMappingSetItemProtocol<'p>: PyMappingProtocol<'p> { pub trait PyMappingSetItemProtocol<'p>: PyMappingProtocol<'p> {
type Key: FromPyObject<'p>; type Key: FromPyObject<'p>;
type Value: FromPyObject<'p>; type Value: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyMappingDelItemProtocol<'p>: PyMappingProtocol<'p> { pub trait PyMappingDelItemProtocol<'p>: PyMappingProtocol<'p> {
type Key: FromPyObject<'p>; type Key: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> { pub trait PyMappingReversedProtocol<'p>: PyMappingProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
#[doc(hidden)] #[doc(hidden)]

View File

@ -3,8 +3,8 @@
//! Python Number Interface //! Python Number Interface
//! Trait and support implementation for implementing number protocol //! Trait and support implementation for implementing number protocol
use crate::err::PyResult; use crate::callback::IntoPyCallbackOutput;
use crate::{ffi, FromPyObject, IntoPy, PyClass, PyObject}; use crate::{ffi, FromPyObject, PyClass, PyObject};
/// Number interface /// Number interface
#[allow(unused_variables)] #[allow(unused_variables)]
@ -318,301 +318,264 @@ pub trait PyNumberProtocol<'p>: PyClass {
pub trait PyNumberAddProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberAddProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberSubProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberSubProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberMulProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberMulProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberMatmulProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberMatmulProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberTruedivProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberTruedivProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberFloordivProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberFloordivProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberModProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberModProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberDivmodProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberDivmodProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberPowProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberPowProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Modulo: FromPyObject<'p>; type Modulo: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberLShiftProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberLShiftProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRShiftProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRShiftProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberAndProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberAndProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberXorProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberXorProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberOrProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberOrProtocol<'p>: PyNumberProtocol<'p> {
type Left: FromPyObject<'p>; type Left: FromPyObject<'p>;
type Right: FromPyObject<'p>; type Right: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRAddProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRAddProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRSubProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRSubProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRMulProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRMulProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRMatmulProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRMatmulProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRTruedivProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRTruedivProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRFloordivProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRFloordivProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRModProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRModProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRDivmodProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRDivmodProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRPowProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRPowProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Modulo: FromPyObject<'p>; type Modulo: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRLShiftProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRLShiftProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRRShiftProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRRShiftProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRAndProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRAndProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRXorProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRXorProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberROrProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberROrProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberIAddProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIAddProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberISubProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberISubProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIMulProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIMulProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIMatmulProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIMatmulProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberITruedivProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberITruedivProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIFloordivProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIFloordivProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIModProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIModProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIDivmodProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIPowProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberILShiftProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberILShiftProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIRShiftProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIRShiftProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIAndProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIAndProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIXorProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIXorProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberIOrProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIOrProtocol<'p>: PyNumberProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PyNumberNegProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberNegProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberPosProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberPosProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberAbsProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberAbsProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberInvertProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberInvertProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberComplexProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberComplexProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberIntProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIntProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberFloatProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberFloatProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyNumberRoundProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberRoundProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>;
type NDigits: FromPyObject<'p>; type NDigits: FromPyObject<'p>;
type Result: Into<PyResult<Self::Success>>; type Result: IntoPyCallbackOutput<PyObject>;
} }
pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> { pub trait PyNumberIndexProtocol<'p>: PyNumberProtocol<'p> {
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
#[doc(hidden)] #[doc(hidden)]

View File

@ -8,9 +8,10 @@
//! [PEP-0492](https://www.python.org/dev/peps/pep-0492/) //! [PEP-0492](https://www.python.org/dev/peps/pep-0492/)
//! //!
use crate::callback::IntoPyCallbackOutput;
use crate::derive_utils::TryFromPyCell; use crate::derive_utils::TryFromPyCell;
use crate::err::PyResult; use crate::err::PyResult;
use crate::{ffi, PyClass, PyObject}; use crate::{ffi, IntoPy, IntoPyPointer, PyClass, PyObject, Python};
/// Python Async/Await support interface. /// Python Async/Await support interface.
/// ///
@ -60,33 +61,28 @@ pub trait PyAsyncProtocol<'p>: PyClass {
pub trait PyAsyncAwaitProtocol<'p>: PyAsyncProtocol<'p> { pub trait PyAsyncAwaitProtocol<'p>: PyAsyncProtocol<'p> {
type Receiver: TryFromPyCell<'p, Self>; type Receiver: TryFromPyCell<'p, Self>;
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyAsyncAiterProtocol<'p>: PyAsyncProtocol<'p> { pub trait PyAsyncAiterProtocol<'p>: PyAsyncProtocol<'p> {
type Receiver: TryFromPyCell<'p, Self>; type Receiver: TryFromPyCell<'p, Self>;
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyAsyncAnextProtocol<'p>: PyAsyncProtocol<'p> { pub trait PyAsyncAnextProtocol<'p>: PyAsyncProtocol<'p> {
type Receiver: TryFromPyCell<'p, Self>; type Receiver: TryFromPyCell<'p, Self>;
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<IterANextOutput>;
type Result: Into<PyResult<Option<Self::Success>>>;
} }
pub trait PyAsyncAenterProtocol<'p>: PyAsyncProtocol<'p> { pub trait PyAsyncAenterProtocol<'p>: PyAsyncProtocol<'p> {
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> { pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
type ExcType: crate::FromPyObject<'p>; type ExcType: crate::FromPyObject<'p>;
type ExcValue: crate::FromPyObject<'p>; type ExcValue: crate::FromPyObject<'p>;
type Traceback: crate::FromPyObject<'p>; type Traceback: crate::FromPyObject<'p>;
type Success: crate::IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
#[doc(hidden)] #[doc(hidden)]
@ -107,37 +103,34 @@ impl ffi::PyAsyncMethods {
where where
T: for<'p> PyAsyncAnextProtocol<'p>, T: for<'p> PyAsyncAnextProtocol<'p>,
{ {
self.am_anext = anext::am_anext::<T>(); self.am_anext = am_anext::<T>();
} }
} }
mod anext { pub struct IterANextOutput(Option<PyObject>);
use super::PyAsyncAnextProtocol;
use crate::callback::IntoPyCallbackOutput;
use crate::err::PyResult;
use crate::IntoPyPointer;
use crate::Python;
use crate::{ffi, IntoPy, PyObject};
struct IterANextOutput<T>(Option<T>); impl IntoPyCallbackOutput<*mut ffi::PyObject> for IterANextOutput {
fn convert(self, _py: Python) -> PyResult<*mut ffi::PyObject> {
impl<T> IntoPyCallbackOutput<*mut ffi::PyObject> for IterANextOutput<T> match self.0 {
where Some(o) => Ok(o.into_ptr()),
T: IntoPy<PyObject>, None => Err(crate::exceptions::StopAsyncIteration::py_err(())),
{
fn convert(self, py: Python) -> PyResult<*mut ffi::PyObject> {
match self.0 {
Some(val) => Ok(val.into_py(py).into_ptr()),
None => Err(crate::exceptions::StopAsyncIteration::py_err(())),
}
} }
} }
}
#[inline] impl<T> IntoPyCallbackOutput<IterANextOutput> for Option<T>
pub(super) fn am_anext<T>() -> Option<ffi::unaryfunc> where
where T: IntoPy<PyObject>,
T: for<'p> PyAsyncAnextProtocol<'p>, {
{ fn convert(self, py: Python) -> PyResult<IterANextOutput> {
py_unarys_func!(PyAsyncAnextProtocol, T::__anext__, IterANextOutput) Ok(IterANextOutput(self.map(|o| o.into_py(py))))
} }
} }
#[inline]
fn am_anext<T>() -> Option<ffi::unaryfunc>
where
T: for<'p> PyAsyncAnextProtocol<'p>,
{
py_unarys_func!(PyAsyncAnextProtocol, T::__anext__)
}

View File

@ -3,8 +3,9 @@
//! Python Sequence Interface //! Python Sequence Interface
//! Trait and support implementation for implementing sequence //! Trait and support implementation for implementing sequence
use crate::callback::IntoPyCallbackOutput;
use crate::conversion::{FromPyObject, IntoPy}; use crate::conversion::{FromPyObject, IntoPy};
use crate::err::{PyErr, PyResult}; use crate::err::PyErr;
use crate::{exceptions, ffi, PyAny, PyCell, PyClass, PyObject}; use crate::{exceptions, ffi, PyAny, PyCell, PyClass, PyObject};
use std::os::raw::c_int; use std::os::raw::c_int;
@ -79,51 +80,52 @@ pub trait PySequenceProtocol<'p>: PyClass + Sized {
// the existance of a slotted method. // the existance of a slotted method.
pub trait PySequenceLenProtocol<'p>: PySequenceProtocol<'p> { pub trait PySequenceLenProtocol<'p>: PySequenceProtocol<'p> {
type Result: Into<PyResult<usize>>; type Result: IntoPyCallbackOutput<usize>;
} }
pub trait PySequenceGetItemProtocol<'p>: PySequenceProtocol<'p> { pub trait PySequenceGetItemProtocol<'p>: PySequenceProtocol<'p> {
type Index: FromPyObject<'p> + From<isize>; type Index: FromPyObject<'p> + From<isize>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PySequenceSetItemProtocol<'p>: PySequenceProtocol<'p> { pub trait PySequenceSetItemProtocol<'p>: PySequenceProtocol<'p> {
type Index: FromPyObject<'p> + From<isize>; type Index: FromPyObject<'p> + From<isize>;
type Value: FromPyObject<'p>; type Value: FromPyObject<'p>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PySequenceDelItemProtocol<'p>: PySequenceProtocol<'p> { pub trait PySequenceDelItemProtocol<'p>: PySequenceProtocol<'p> {
type Index: FromPyObject<'p> + From<isize>; type Index: FromPyObject<'p> + From<isize>;
type Result: Into<PyResult<()>>; type Result: IntoPyCallbackOutput<()>;
} }
pub trait PySequenceContainsProtocol<'p>: PySequenceProtocol<'p> { pub trait PySequenceContainsProtocol<'p>: PySequenceProtocol<'p> {
type Item: FromPyObject<'p>; type Item: FromPyObject<'p>;
type Result: Into<PyResult<bool>>; type Result: IntoPyCallbackOutput<bool>;
} }
pub trait PySequenceConcatProtocol<'p>: PySequenceProtocol<'p> { pub trait PySequenceConcatProtocol<'p>: PySequenceProtocol<'p> {
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PySequenceRepeatProtocol<'p>: PySequenceProtocol<'p> { pub trait PySequenceRepeatProtocol<'p>: PySequenceProtocol<'p> {
type Index: FromPyObject<'p> + From<isize>; type Index: FromPyObject<'p> + From<isize>;
type Success: IntoPy<PyObject>; type Result: IntoPyCallbackOutput<PyObject>;
type Result: Into<PyResult<Self::Success>>;
} }
pub trait PySequenceInplaceConcatProtocol<'p>: PySequenceProtocol<'p> + IntoPy<PyObject> { pub trait PySequenceInplaceConcatProtocol<'p>:
PySequenceProtocol<'p> + IntoPy<PyObject> + 'p
{
type Other: FromPyObject<'p>; type Other: FromPyObject<'p>;
type Result: Into<PyResult<Self>>; type Result: IntoPyCallbackOutput<Self>;
} }
pub trait PySequenceInplaceRepeatProtocol<'p>: PySequenceProtocol<'p> + IntoPy<PyObject> { pub trait PySequenceInplaceRepeatProtocol<'p>:
PySequenceProtocol<'p> + IntoPy<PyObject> + 'p
{
type Index: FromPyObject<'p> + From<isize>; type Index: FromPyObject<'p> + From<isize>;
type Result: Into<PyResult<Self>>; type Result: IntoPyCallbackOutput<Self>;
} }
#[doc(hidden)] #[doc(hidden)]
@ -230,7 +232,7 @@ mod sq_ass_item_impl {
let mut slf = slf.try_borrow_mut()?; let mut slf = slf.try_borrow_mut()?;
let value = py.from_borrowed_ptr::<PyAny>(value); let value = py.from_borrowed_ptr::<PyAny>(value);
let value = value.extract()?; let value = value.extract()?;
slf.__setitem__(key.into(), value).into() crate::callback::convert(py, slf.__setitem__(key.into(), value))
}) })
} }
Some(wrap::<T>) Some(wrap::<T>)
@ -252,7 +254,7 @@ mod sq_ass_item_impl {
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
if value.is_null() { if value.is_null() {
slf.borrow_mut().__delitem__(key.into()).into() crate::callback::convert(py, slf.borrow_mut().__delitem__(key.into()))
} else { } else {
Err(PyErr::new::<exceptions::NotImplementedError, _>(format!( Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
"Item assignment not supported by {:?}", "Item assignment not supported by {:?}",
@ -280,12 +282,12 @@ mod sq_ass_item_impl {
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf); let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
if value.is_null() { if value.is_null() {
call_mut!(slf, __delitem__; key.into()) call_mut!(slf, __delitem__; key.into()).convert(py)
} else { } else {
let value = py.from_borrowed_ptr::<PyAny>(value); let value = py.from_borrowed_ptr::<PyAny>(value);
let mut slf_ = slf.try_borrow_mut()?; let mut slf_ = slf.try_borrow_mut()?;
let value = value.extract()?; let value = value.extract()?;
slf_.__setitem__(key.into(), value).into() slf_.__setitem__(key.into(), value).convert(py)
} }
}) })
} }

View File

@ -1,6 +1,5 @@
use pyo3::class::PySequenceProtocol; use pyo3::class::PySequenceProtocol;
use pyo3::exceptions::IndexError; use pyo3::exceptions::{IndexError, ValueError};
use pyo3::exceptions::ValueError;
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::{IntoPyDict, PyList}; use pyo3::types::{IntoPyDict, PyList};
@ -232,3 +231,38 @@ fn test_generic_list_set() {
vec![1.to_object(py), 2.to_object(py), 3.to_object(py)] vec![1.to_object(py), 2.to_object(py), 3.to_object(py)]
); );
} }
#[pyclass]
struct OptionList {
#[pyo3(get, set)]
items: Vec<Option<i64>>,
}
#[pyproto]
impl PySequenceProtocol for OptionList {
fn __getitem__(&self, idx: isize) -> PyResult<Option<i64>> {
match self.items.get(idx as usize) {
Some(x) => Ok(*x),
None => Err(PyErr::new::<IndexError, _>("Index out of bounds")),
}
}
}
#[test]
fn test_option_list_get() {
// Regression test for #798
let gil = Python::acquire_gil();
let py = gil.python();
let list = PyCell::new(
py,
OptionList {
items: vec![Some(1), None],
},
)
.unwrap();
py_assert!(py, list, "list[0] == 1");
py_assert!(py, list, "list[1] == None");
py_expect_exception!(py, list, "list[2]", IndexError);
}