I am trying to implement a cache for the private variable of any python class.
Let's suppose I have this:
#[pyclass]
struct ClassA {
pv: Py<PyAny>, // GIL independent type, storable in another #[pyclass]
field_a: Py<PyAny>,
}
#[pyclass]
struct ClassB {
class_a: Py<ClassA>,
field_b: Py<PyAny>,
}
In the impls of ClassA
, I have a method attempting to 'put' a reference of the ClassA
object into the ClassB
's class_a
field. And return a newly instantiated ClassB
object.
#[pymethods]
impl ClassA {
fn ret_class_b {&self, field_b: &PyAny) -> PyResult<ClassB> {
let class_a: Py<ClassA> = Py::clone_ref(self, field_b.py());
ClassB {
class_a: class_a,
field_b: field_b.into_py(),
}
}
}
The above does not compile.
The issue is how do I get &Py<ClassA>
from the receiver of the method so as to return another object where the receiver is referred to as a field in that object?
Edit / Update
Thanks to @cafce25 for his reminder on giving fully reproducible codes and the error from the compiler.
Here is it:
use pyo3::{
prelude::{*, Py, PyAny},
};
#[pymodule]
fn stackoverflowqn(py: Python, pymod: &PyModule) -> PyResult<()> {
#[pyclass(name = "class_a")]
#[derive(Clone, Debug)]
pub struct ClassA {
pv: Option<Py<PyAny>>, // private value
field_a: Py<PyAny>,
}
#[pyclass]
#[derive(Clone, Debug)]
pub struct ClassB {
class_a: Py<ClassA>,
field_b: Py<PyAny>,
}
#[pymethods]
impl ClassA {
#[new]
pub fn __new__(_slf: PyRef<'_, Self>, field_a: PyObject) -> PyResult<ClassA> {
Ok(ClassA {
pv: None,
field_a: field_a,
})
}
fn ret_class_b {&self, field_b: &PyAny) -> PyResult<ClassB> {
let class_a: Py<ClassA> = Py::clone_ref(self, field_b.py());
Ok(ClassB {
class_a: class_a,
field_b: field_b.into_py(),
})
}
}
}
Here is the compiler error:
error[E0277]: the trait bound `ClassA: pyo3::IntoPy<pyo3::Py<ClassA>>` is not satisfied
--> crates\cached-property\src\stackoverflow.rs:36:53
|
36 | pyo3::IntoPy::<Py<ClassA>>::into_py(pty_getter, py);
| ----------------------------------- ^^^^^^^^^^ the trait `pyo3::IntoPy<pyo3::Py<ClassA>>` is not implemented for `ClassA`
| |
| required by a bound introduced by this call
|
= help: the trait `pyo3::IntoPy<pyo3::Py<PyAny>>` is implemented for `ClassA`