Skip to content

[Question] Return different sub-classes from one function? #1637

Description

@azerupi

Is it possible to return different sub-classes from a function?

In Rust I have an enum containing data

pub enum Frame {
    Type,
    TypeResponse(u8, Version, u8),
    Ping(u8),
    Pong(u8),
}

In Python I though I would expose this by having a Frame base class and a sub-class for each type of frame:

#[pyclass(name="Frame", subclass)]
pub struct PyFrame { /* some fields */ }

#[pyclass(extends=PyFrame, subclass)]
pub struct PingFrame {
    #[pyo3(get)]
    sequence: u8,
}

#[pymethods]
impl PingFrame {
    #[new]
    pub fn new(sequence: u8) -> (Self, PyFrame) {
        let frame = Frame::new_ping(sequence);
        ((&frame).try_into().unwrap(), frame.into())
    }
}

impl TryFrom<&Frame<'_>> for PingFrame {
    type Error = ();
    
    fn try_from(frame: &Frame) -> Result<Self, Self::Error> {
        match frame.payload() {
            Frame::Ping(sequence) => Ok(PingFrame { sequence: *sequence }),
            _ => Err(())
        }
    }
}

Now I'm trying to have a function that can return any of the sub-classes depending on the frame enum variant. Is that possible?

fn parse(&mut self, py: Python, byte: u8) -> PyResult<Option<PyObject>> {
        match self.parser.parse(byte) {
            Ok(f) => Ok(Some(PingFrame::new(5).into_py(py))),
            Err(e) => return Err(ParseError { err: e }.into())
        }
    }

I tried to use PyFrame and PyObject in the return type, but that doesn't seem to work.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions