pyo3 icon indicating copy to clipboard operation
pyo3 copied to clipboard

ENH: boiler plate for `IntoPy<PyObject>`

Open attack68 opened this issue 1 year ago • 2 comments

I may very well be implementing a weak design pattern, but I regularly use an enum to control Rust structs passed as Python classes. The enum itself does not need to be python class (so refutes the doc comment "The easiest way to implement IntoPy is by exposing a struct as a native Python object by annotating it with [#[pyclass]]")

The FromPyObject can be automatically derived, but I often implement IntoPy<PyObject> directly using repeatable boiler plate code such as the following. Can this be automatic in pyo3?

#[derive(Debug, Clone, PartialEq, FromPyObject)]
pub(crate) enum Shape {
    Square(Square),
    Circle(Circle),
    Triangle(Triangle),
}

impl IntoPy<PyObject> for CurveInterpolator {
    fn into_py(self, py: Python<'_>) -> PyObject {
        macro_rules! into_py {
            ($obj: ident) => {
                Py::new(py, $obj).unwrap().to_object(py)
            }
        }

        match self {
            Shape::Square(s) => into_py!(s),
            Shape::Circle(s) => into_py!(s),
            Shape::Triangle(s) => into_py!(s),
        }
    }
}

attack68 avatar Aug 20 '24 18:08 attack68

In PyO3 0.23 we are going to release a new trait IntoPyObject to replace IntoPy based on what we've learned over time. I would be open to discussing the possibility of adding an IntoPyObject derive too (not necessarily in 0.23, though that might be very appealing from the view of helping users migrate). cc @Icxolu

davidhewitt avatar Aug 20 '24 20:08 davidhewitt

That sounds interesting and could be quite useful for migrating. For these newtype enums the conversion seems indeed quite straight forward, but for more complex enums and structs it's a bit unclear what the resulting Python object should be... maybe PyDict and/or PyTuple depending on whether the fields are named or not.

Icxolu avatar Aug 20 '24 21:08 Icxolu