How to convert &PyClass
to Py<PyAny>
in #[pymethods]
?
#3696
-
# Minimized python code to be rewritten
class ConstExpr:
def __new__(cls, *args, **kwargs):
return super().__new__(cls)
def __init__(self, baseobj: "Class | None", offset: int = 0):
self.baseobj = baseobj
self.offset = offset
def __add__(self, other: int) -> "ConstExpr":
return ConstExpr(self.baseobj, self.offset + other)
def __radd__(self, other: int) -> "ConstExpr":
return self.__add__(other)
class Class(ConstExpr):
def __init__(self):
super().__init__(self)
class Subclass(Class):
def __init__(self):
super().__init__()
if __name__ == "__main__":
obj = Subclass()
expr = 1 + obj
assert expr.baseobj is obj use pyo3::prelude::*;
#[derive(Clone)]
pub(crate) struct ConstExpr {
baseobj: PyObject,
offset: i32,
}
#[derive(Clone)]
#[pyclass(frozen, subclass, name = "ConstExpr")]
pub struct PyConstExpr(ConstExpr);
#[pymethods]
impl PyConstExpr {
#[new]
#[pyo3(signature = (baseobj, offset=0))]
fn new(baseobj: &PyAny, offset: i32) -> Self {
Self(ConstExpr::new(baseobj, offset))
}
// First try
fn __add__(&self, rhs: i32) -> Self {
Self(ConstExpr {
baseobj: self.into(),
offset: self.0.offset + rhs,
})
}
fn __radd__(&self, rhs: i32) -> Self {
self.__add__(rhs)
}
}
/*
error[E0277]: the trait bound `PyConstExpr: AsRef<pyo3::PyAny>` is not satisfied
--> src\allocator\constexpr.rs:68:27
|
68 | baseobj: self.into(),
| ^^^^ the trait `AsRef<pyo3::PyAny>` is not implemented for `PyConstExpr` |
= note: required for `Py<pyo3::PyAny>` to implement `From<&PyConstExpr>`
= note: required for `&PyConstExpr` to implement `Into<Py<pyo3::PyAny>>`
*/ // Second try
fn __add__(slf: Py<Self>, py: Python, rhs: i32) -> PyResult<Self> {
let expr = slf.borrow(py);
Ok(Self(ConstExpr {
baseobj: expr.into_py(py),
offset: expr.0.offset + rhs,
}))
}
fn __radd__(slf: Py<Self>, py: Python, rhs: i32) -> PyResult<Self> {
Self::__add__(slf, py, rhs)
}
/*
error[E0382]: borrow of moved value: `expr`
--> src\allocator\constexpr.rs:70:21
|
67 | let expr = slf.borrow(py);
| ---- move occurs because `expr` has type `PyRef<'_, PyConstExpr>`, which does not implement the `Copy` trait
68 | Ok(Self(ConstExpr {
69 | baseobj: expr.into_py(py),
| ----------- `expr` moved due to this method call
70 | offset: expr.0.offset + rhs,
| ^^^^^^ value borrowed here after move
|
note: `into_py` takes ownership of the receiver `self`, which moves `expr`
--> C:\Users\armo\.cargo\registry\src\index.crates.io-6f17d22bba15001f\pyo3-0.20.0\src\conversion.rs:165:16
|
165 | fn into_py(self, py: Python<'_>) -> T;
| ^^^^
= note: borrow occurs due to deref coercion to `PyConstExpr`
note: deref defined here
--> C:\Users\armo\.cargo\registry\src\index.crates.io-6f17d22bba15001f\pyo3-0.20.0\src\pycell.rs:725:5
|
725 | type Target = T;
| ^^^^^^^^^^^
*/ // Third try
fn __add__(&self, py: Python, rhs: i32) -> PyResult<Self> {
let expr = Py::new(py, self)?;
Ok(Self(ConstExpr {
baseobj: expr.into_py(py),
offset: self.0.offset + rhs,
}))
}
fn __radd__(&self, py: Python, rhs: i32) -> PyResult<Self> {
self.__add__(py, rhs)
}
/*
error[E0277]: the trait bound `&PyConstExpr: PyClass` is not satisfied
--> src\allocator\constexpr.rs:67:32
|
67 | let expr = Py::new(py, self)?;
| ------- ^^^^ the trait `PyClass` is not implemented for `&PyConstExpr`
| |
| required by a bound introduced by this call
|
= help: the trait `PyClass` is implemented for `PyConstExpr`
= note: required for `PyClassInitializer<&PyConstExpr>` to implement `From<&PyConstExpr>`
= note: required for `&PyConstExpr` to implement `Into<PyClassInitializer<&PyConstExpr>>`
note: required by a bound in `pyo3::Py::<T>::new`
--> C:\Users\armo\.cargo\registry\src\index.crates.io-6f17d22bba15001f\pyo3-0.20.0\src\instance.rs:254:44
|
254 | pub fn new(py: Python<'_>, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in
`Py::<T>::new`
*/ |
Beta Was this translation helpful? Give feedback.
Answered by
adamreichold
Dec 24, 2023
Replies: 1 comment 6 replies
-
I think you second try is actually correct, you just need to change the way you call it to universal function call syntax, i.e. fn __radd__(slf: Py<Self>, py: Python, rhs: i32) -> PyResult<Self> {
Self::__add__(slf, py, rhs)
} |
Beta Was this translation helpful? Give feedback.
6 replies
Answer selected by
armoha
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think you second try is actually correct, you just need to change the way you call it to universal function call syntax, i.e.