feat: add #[pyo3(get, set)] for Cell
This commit is contained in:
parent
59bbb40a35
commit
a629e8267a
|
@ -437,6 +437,8 @@ To use these annotations, your field type must implement some conversion traits:
|
||||||
- For `get` the field type must implement both `IntoPy<PyObject>` and `Clone`.
|
- For `get` the field type must implement both `IntoPy<PyObject>` and `Clone`.
|
||||||
- For `set` the field type must implement `FromPyObject`.
|
- For `set` the field type must implement `FromPyObject`.
|
||||||
|
|
||||||
|
For example, implementations of those traits are provided for the `Cell` type, if the inner type also implements the trait. This means you can use `#[pyo3(get, set)]` on fields wrapped in a `Cell`.
|
||||||
|
|
||||||
### Object properties using `#[getter]` and `#[setter]`
|
### Object properties using `#[getter]` and `#[setter]`
|
||||||
|
|
||||||
For cases which don't satisfy the `#[pyo3(get, set)]` trait requirements, or need side effects, descriptor methods can be defined in a `#[pymethods]` `impl` block.
|
For cases which don't satisfy the `#[pyo3(get, set)]` trait requirements, or need side effects, descriptor methods can be defined in a `#[pymethods]` `impl` block.
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add an `IntoPy<PyObject>`, `ToPyObject` and `FromPyObject` impl for `Cell`.
|
|
@ -10,6 +10,7 @@ use crate::types::PyTuple;
|
||||||
use crate::{
|
use crate::{
|
||||||
ffi, gil, Py, PyAny, PyCell, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
|
ffi, gil, Py, PyAny, PyCell, PyClass, PyNativeType, PyObject, PyRef, PyRefMut, Python,
|
||||||
};
|
};
|
||||||
|
use std::cell::Cell;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
/// Returns a borrowed pointer to a Python object.
|
/// Returns a borrowed pointer to a Python object.
|
||||||
|
@ -370,6 +371,24 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Copy + ToPyObject> ToPyObject for Cell<T> {
|
||||||
|
fn to_object(&self, py: Python<'_>) -> PyObject {
|
||||||
|
self.get().to_object(py)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Copy + IntoPy<PyObject>> IntoPy<PyObject> for Cell<T> {
|
||||||
|
fn into_py(self, py: Python<'_>) -> PyObject {
|
||||||
|
self.get().into_py(py)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: FromPyObject<'a>> FromPyObject<'a> for Cell<T> {
|
||||||
|
fn extract(ob: &'a PyAny) -> PyResult<Self> {
|
||||||
|
T::extract(ob).map(Cell::new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T> FromPyObject<'a> for &'a PyCell<T>
|
impl<'a, T> FromPyObject<'a> for &'a PyCell<T>
|
||||||
where
|
where
|
||||||
T: PyClass,
|
T: PyClass,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#![cfg(feature = "macros")]
|
#![cfg(feature = "macros")]
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::py_run;
|
use pyo3::py_run;
|
||||||
use pyo3::types::{IntoPyDict, PyList};
|
use pyo3::types::{IntoPyDict, PyList};
|
||||||
|
@ -189,3 +191,28 @@ fn get_all_and_set() {
|
||||||
py_run!(py, inst, "inst.num = 20; assert inst.num == 20");
|
py_run!(py, inst, "inst.num = 20; assert inst.num == 20");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[pyclass]
|
||||||
|
struct CellGetterSetter {
|
||||||
|
#[pyo3(get, set)]
|
||||||
|
cell_inner: Cell<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn cell_getter_setter() {
|
||||||
|
let c = CellGetterSetter {
|
||||||
|
cell_inner: Cell::new(10),
|
||||||
|
};
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let inst = Py::new(py, c).unwrap().to_object(py);
|
||||||
|
let cell = Cell::new(20).to_object(py);
|
||||||
|
|
||||||
|
py_run!(py, cell, "assert cell == 20");
|
||||||
|
py_run!(py, inst, "assert inst.cell_inner == 10");
|
||||||
|
py_run!(
|
||||||
|
py,
|
||||||
|
inst,
|
||||||
|
"inst.cell_inner = 20; assert inst.cell_inner == 20"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue