rustpicklepyo3

How to return an empty tuple to Python from Rust function with PyO3?


For pickling purposes I am implementing the following methods in a rust pyclass:

#[pymethods]
impl SomePyStruct {
    #[new]
    pub fn new() -> Self { Self {} }

    // Pickling
    pub fn __setstate__(&mut self, state: Bound<'_, PyBytes>) -> PyResult<()> {
        *self = deserialize(state.as_bytes()).unwrap();
        Ok(())
    }
    pub fn __getstate__<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyBytes>> {
        Ok(PyBytes::new_bound(py, &serialize(&self).unwrap()))
    }
    /// THE FOLLOWING FUNCTION FAILS
    pub fn __getnewargs__(&self) -> PyResult<()> {
        Ok(())
    }
    /// THE ABOVE FUNCTION FAILS
}

When pickling on the Python side I get the error:

>       bytes = pickle.dumps(obj)
E       TypeError: __getnewargs__ should return a tuple, not 'NoneType'

Why is __getnewargs__ not returning an empty tuple but returning None. And better yet, how to fix?


Solution

  • Use PyTuple::empty(py) instead of ()

    https://pyo3.rs/main/doc/pyo3/types/struct.pytuple#method.empty