2021-12-03 00:03:32 +00:00
|
|
|
#![cfg(feature = "macros")]
|
|
|
|
|
2018-05-02 18:49:40 +00:00
|
|
|
use pyo3::prelude::*;
|
2019-06-13 09:09:17 +00:00
|
|
|
use pyo3::py_run;
|
2019-07-12 14:41:13 +00:00
|
|
|
use pyo3::types::{IntoPyDict, PyList};
|
2018-05-02 18:49:40 +00:00
|
|
|
|
|
|
|
mod common;
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyclass]
|
2018-05-02 18:49:40 +00:00
|
|
|
struct ClassWithProperties {
|
|
|
|
num: i32,
|
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pymethods]
|
2018-05-02 18:49:40 +00:00
|
|
|
impl ClassWithProperties {
|
2021-02-11 21:37:38 +00:00
|
|
|
fn get_num(&self) -> i32 {
|
|
|
|
self.num
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[getter(DATA)]
|
2019-04-13 22:23:59 +00:00
|
|
|
/// a getter for data
|
2021-02-11 21:37:38 +00:00
|
|
|
fn get_data(&self) -> i32 {
|
|
|
|
self.num
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
#[setter(DATA)]
|
2021-02-11 21:37:38 +00:00
|
|
|
fn set_data(&mut self, value: i32) {
|
2018-05-02 18:49:40 +00:00
|
|
|
self.num = value;
|
|
|
|
}
|
2019-04-17 18:55:57 +00:00
|
|
|
|
|
|
|
#[getter]
|
|
|
|
/// a getter with a type un-wrapped by PyResult
|
|
|
|
fn get_unwrapped(&self) -> i32 {
|
|
|
|
self.num
|
|
|
|
}
|
2019-07-12 14:41:13 +00:00
|
|
|
|
2019-04-17 18:55:57 +00:00
|
|
|
#[setter]
|
|
|
|
fn set_unwrapped(&mut self, value: i32) {
|
|
|
|
self.num = value;
|
|
|
|
}
|
2019-07-12 14:41:13 +00:00
|
|
|
|
|
|
|
#[getter]
|
|
|
|
fn get_data_list<'py>(&self, py: Python<'py>) -> &'py PyList {
|
|
|
|
PyList::new(py, &[self.num])
|
|
|
|
}
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn class_with_properties() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let inst = Py::new(py, ClassWithProperties { num: 10 }).unwrap();
|
2018-05-02 18:49:40 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_run!(py, inst, "assert inst.get_num() == 10");
|
|
|
|
py_run!(py, inst, "assert inst.get_num() == inst.DATA");
|
|
|
|
py_run!(py, inst, "inst.DATA = 20");
|
|
|
|
py_run!(py, inst, "assert inst.get_num() == 20 == inst.DATA");
|
2018-05-02 18:49:40 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_expect_exception!(py, inst, "del inst.DATA", PyAttributeError);
|
2019-04-13 22:23:59 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
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");
|
|
|
|
py_run!(py, inst, "assert inst.data_list == [42]");
|
2021-08-11 00:48:50 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
let d = [("C", py.get_type::<ClassWithProperties>())].into_py_dict(py);
|
|
|
|
py_assert!(py, *d, "C.DATA.__doc__ == 'a getter for data'");
|
|
|
|
});
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pyclass]
|
2018-05-02 18:49:40 +00:00
|
|
|
struct GetterSetter {
|
2019-02-18 19:07:41 +00:00
|
|
|
#[pyo3(get, set)]
|
2018-05-02 18:49:40 +00:00
|
|
|
num: i32,
|
2019-02-18 19:07:41 +00:00
|
|
|
#[pyo3(get, set)]
|
2018-06-12 15:47:24 +00:00
|
|
|
text: String,
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
|
2018-07-08 21:33:48 +00:00
|
|
|
#[pymethods]
|
2018-05-02 18:49:40 +00:00
|
|
|
impl GetterSetter {
|
2021-02-11 21:37:38 +00:00
|
|
|
fn get_num2(&self) -> i32 {
|
|
|
|
self.num
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn getter_setter_autogen() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let inst = Py::new(
|
|
|
|
py,
|
|
|
|
GetterSetter {
|
|
|
|
num: 10,
|
|
|
|
text: "Hello".to_string(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
py_run!(py, inst, "assert inst.num == 10");
|
|
|
|
py_run!(py, inst, "inst.num = 20; assert inst.num == 20");
|
|
|
|
py_run!(
|
|
|
|
py,
|
|
|
|
inst,
|
|
|
|
"assert inst.text == 'Hello'; inst.text = 'There'; assert inst.text == 'There'"
|
|
|
|
);
|
|
|
|
});
|
2018-05-02 18:49:40 +00:00
|
|
|
}
|
2020-06-23 14:19:20 +00:00
|
|
|
|
|
|
|
#[pyclass]
|
|
|
|
struct RefGetterSetter {
|
|
|
|
num: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl RefGetterSetter {
|
|
|
|
#[getter]
|
2022-03-23 07:07:28 +00:00
|
|
|
fn get_num(slf: PyRef<'_, Self>) -> i32 {
|
2020-06-23 14:19:20 +00:00
|
|
|
slf.num
|
|
|
|
}
|
|
|
|
|
|
|
|
#[setter]
|
2022-03-23 07:07:28 +00:00
|
|
|
fn set_num(mut slf: PyRefMut<'_, Self>, value: i32) {
|
2020-06-23 14:19:20 +00:00
|
|
|
slf.num = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn ref_getter_setter() {
|
|
|
|
// Regression test for #837
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let inst = Py::new(py, RefGetterSetter { num: 10 }).unwrap();
|
2020-06-23 14:19:20 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_run!(py, inst, "assert inst.num == 10");
|
|
|
|
py_run!(py, inst, "inst.num = 20; assert inst.num == 20");
|
|
|
|
});
|
2020-06-23 14:19:20 +00:00
|
|
|
}
|
2021-03-17 16:04:25 +00:00
|
|
|
|
|
|
|
#[pyclass]
|
|
|
|
struct TupleClassGetterSetter(i32);
|
|
|
|
|
|
|
|
#[pymethods]
|
|
|
|
impl TupleClassGetterSetter {
|
|
|
|
#[getter(num)]
|
|
|
|
fn get_num(&self) -> i32 {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
|
|
|
#[setter(num)]
|
|
|
|
fn set_num(&mut self, value: i32) {
|
|
|
|
self.0 = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn tuple_struct_getter_setter() {
|
2022-07-19 17:34:23 +00:00
|
|
|
Python::with_gil(|py| {
|
|
|
|
let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap();
|
2021-03-17 16:04:25 +00:00
|
|
|
|
2022-07-19 17:34:23 +00:00
|
|
|
py_assert!(py, inst, "inst.num == 10");
|
|
|
|
py_run!(py, inst, "inst.num = 20");
|
|
|
|
py_assert!(py, inst, "inst.num == 20");
|
|
|
|
});
|
2021-03-17 16:04:25 +00:00
|
|
|
}
|