PyO3 Trait Clone is not implemented for 'PyList'

138 views Asked by At

I am trying to make my own Python Library in Rust using PyO3 bindings. Although it is giving me this weird error, that I cannot seem to fix. I have tried to move it over to refrences to PyList, but then it just requires me to specify a lifetime; which then in turn needs me to use Generics which PyO3 doesn't allow.

Here is the error, and my code:

error[E0277]: the trait bound `PyList: Clone` is not satisfied
 --> src\lib.rs:8:5
  |
5 | #[derive(Clone)]
  |          ----- in this derive macro expansion
...
8 |     arguments: PyList,
  |     ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `PyList`
  |
  = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
use pyo3::types::PyList;
use pyo3::prelude::*;

#[pyclass(unsendable)]
#[derive(Clone)]
struct Crust {
    #[pyo3(get, set)]
    arguments: PyList,
}

#[pymethods]
impl Crust {
    #[new]
    fn new(arguments: PyList) -> Self {
        Crust { arguments }
    }

    fn add_argument(&self, name: String, callback: PyObject) -> PyResult<()> {
        Python::with_gil(|py| {
            print!("Current arguments: {:?}", self.arguments);
        });
        Ok(())
    }
}

#[pymodule]
fn crust(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<Crust>()?;
    Ok(())
}
1

There are 1 answers

0
Chayim Friedman On

You probably do no want to store PyList directly, but Py<PyList>. This will allow you to avoid the #[pyclass(unsendable)] and also be Clone.

use pyo3::types::PyList;
use pyo3::prelude::*;

#[pyclass]
#[derive(Clone)]
struct Crust {
    #[pyo3(get, set)]
    arguments: Py<PyList>,
}

#[pymethods]
impl Crust {
    #[new]
    fn new(arguments: Py<PyList>) -> Self {
        Crust { arguments }
    }

    fn add_argument(&self, name: String, callback: PyObject) -> PyResult<()> {
        Python::with_gil(|py| {
            print!("Current arguments: {:?}", self.arguments);
        });
        Ok(())
    }
}

#[pymodule]
fn crust(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<Crust>()?;
    Ok(())
}