diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d4995ee..31f8478f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. * Have `PyModule` generate an index of its members (`__all__` list). +### Changed + + * Methods decorated with `#[getter]` and `#[setter]` can now omit wrapping the + result type in `PyResult` if they don't raise exceptions. + ### Fixed * `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB. diff --git a/pyo3-derive-backend/src/pymethod.rs b/pyo3-derive-backend/src/pymethod.rs index 010e0c0e..c19d4893 100644 --- a/pyo3-derive-backend/src/pymethod.rs +++ b/pyo3-derive-backend/src/pymethod.rs @@ -273,7 +273,9 @@ pub(crate) fn impl_wrap_getter(cls: &syn::Type, name: &syn::Ident) -> TokenStrea let _py = pyo3::Python::assume_gil_acquired(); let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf); - match _slf.#name() { + let result = pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name()); + + match result { Ok(val) => { pyo3::IntoPyPointer::into_ptr(val.into_object(_py)) } @@ -314,7 +316,9 @@ pub(crate) fn impl_wrap_setter( let _value = _py.from_borrowed_ptr(_value); let _result = match <#val_ty as pyo3::FromPyObject>::extract(_value) { - Ok(_val) => _slf.#name(_val), + Ok(_val) => { + pyo3::derive_utils::IntoPyResult::into_py_result(_slf.#name(_val)) + } Err(e) => Err(e) }; match _result { diff --git a/tests/test_getter_setter.rs b/tests/test_getter_setter.rs index aed89f0e..9b3b58c8 100644 --- a/tests/test_getter_setter.rs +++ b/tests/test_getter_setter.rs @@ -26,6 +26,16 @@ impl ClassWithProperties { self.num = value; Ok(()) } + + #[getter] + /// a getter with a type un-wrapped by PyResult + fn get_unwrapped(&self) -> i32 { + self.num + } + #[setter] + fn set_unwrapped(&mut self, value: i32) { + self.num = value; + } } #[test] @@ -41,6 +51,10 @@ fn class_with_properties() { py_run!(py, inst, "assert inst.get_num() == 20"); py_run!(py, inst, "assert inst.get_num() == inst.DATA"); + py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 20"); + py_run!(py, inst, "inst.unwrapped = 42"); + py_run!(py, inst, "assert inst.get_num() == inst.unwrapped == 42"); + let d = [("C", py.get_type::())].into_py_dict(py); py.run( "assert C.DATA.__doc__ == 'a getter for data'",