Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pyo3: The trait `PyClass` is not implemented for `&Py<PyAny>`

I am learning rust and trying to make a very simple python module using pyo3 and maturin. I am having a problem on the rust code though,

Cargo.toml

[package]
name = "lenrs"
version = "0.1.0"
authors = ["matheusfillipe"]
edition = "2018"

[dependencies.pyo3]
version = "0.13.2"
features = ["extension-module"]

[lib]
crate-type = ["cdylib"]
name = "lenrs"

src/lib.rs

extern crate pyo3;

use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

#[pyfunction]
fn length(py: Python, obj: &PyObject) -> PyResult<PyObject> {
    if let Ok(s) = obj.extract::<String>(py) {
        return Ok(s.len().to_object(py));
    }
    if let Ok(s) = obj.extract::<Vec<String>>(py) {
        return Ok(s.len().to_object(py));
    }
    Err(PyTypeError::new_err("Not Supported"))
}

#[pymodule]
fn lenrs(py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!(length))?;
    Ok(())
}

lenrs/init.py

from .lenrs import *

Build Output

$ cargo build                 
   Compiling lenrs v0.1.0 (/home/matheus/projects/learn-rust/lenrs)
error[E0277]: the trait bound `&Py<PyAny>: PyClass` is not satisfied
 --> src/lib.rs:7:1
  |
7 | #[pyfunction]
  | ^^^^^^^^^^^^^ the trait `PyClass` is not implemented for `&Py<PyAny>`
  |
  = note: required because of the requirements on the impl of `pyo3::FromPyObject<'_>` for `&Py<PyAny>`
  = note: required because of the requirements on the impl of `ExtractExt<'_>` for `&Py<PyAny>`
  = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `lenrs`

To learn more, run the command again with --verbose.

I see that the problem is on the #[pyfunction]. Everything worked well when I had a simpler version that would work for strings only and the length function would return PyResult<()>, and I would just return Ok(()) in the end but now I am not really sure what to do to get this function to raise a python error if the type is not supported.

like image 385
mattf Avatar asked Oct 17 '25 02:10

mattf


1 Answers

I just figured out obj should not be a reference, changing the function signature to: fn length(py: Python, obj: PyObject) -> PyResult<PyObject> made it work:

extern crate pyo3;

use pyo3::exceptions::PyTypeError;
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

#[pyfunction]
fn length(py: Python, obj: PyObject) -> PyResult<PyObject> {
    if let Ok(s) = obj.extract::<String>(py) {
        return Ok(s.len().to_object(py));
    }
    if let Ok(s) = obj.extract::<Vec<String>>(py) {
        return Ok(s.len().to_object(py));
    }
    Err(PyTypeError::new_err("Not Supported"))
}

#[pymodule]
fn lenrs(py: Python, m: &PyModule) -> PyResult<()> {
    m.add_wrapped(wrap_pyfunction!(length))?;
    Ok(())
}
like image 65
mattf Avatar answered Oct 18 '25 16:10

mattf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!