Allow omitting PyResult wrapping in property get/set methods

fixes #443
This commit is contained in:
Georg Brandl 2019-04-17 20:55:57 +02:00
parent dc2fc80f4a
commit 117f6eb47d
3 changed files with 25 additions and 2 deletions

View File

@ -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). * 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 ### Fixed
* `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB. * `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB.

View File

@ -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 _py = pyo3::Python::assume_gil_acquired();
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf); 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) => { Ok(val) => {
pyo3::IntoPyPointer::into_ptr(val.into_object(_py)) 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 _value = _py.from_borrowed_ptr(_value);
let _result = match <#val_ty as pyo3::FromPyObject>::extract(_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) Err(e) => Err(e)
}; };
match _result { match _result {

View File

@ -26,6 +26,16 @@ impl ClassWithProperties {
self.num = value; self.num = value;
Ok(()) 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] #[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() == 20");
py_run!(py, inst, "assert inst.get_num() == inst.DATA"); 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::<ClassWithProperties>())].into_py_dict(py); let d = [("C", py.get_type::<ClassWithProperties>())].into_py_dict(py);
py.run( py.run(
"assert C.DATA.__doc__ == 'a getter for data'", "assert C.DATA.__doc__ == 'a getter for data'",