PyO3 / PyO3/pyo3

IntoPy for #[pyclass(extends=...)] ?

Open
#1,836 3 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

documentation needs-design
Dominant language
Rust
Stars
16.2k
Forks
1k
Avg merge
2d 6h
Merged PRs (30d)
66

Description

Context

I am trying to wrap a few Rust objects in a Python API - basically an enum of a few different types.

enum Things {
    Obj1(String),
    Obj2(f64),
}

I want to represent this as, roughly, something like this:

class BaseThing:
    def as_obj1(self): ...
    def as_obj2(self): ...

class Obj1(BaseThing): ..
class Obj2(BaseThing): ...

So, I created a base pyclass,

#[pyclass(name="BaseThing", subclass)]
#[derive(Debug, Clone)]
pub struct PyBaseThing {
}

..and pyclass for each of the variants:

#[pyclass(name="Obj1", extends=MyBase)]
#[derive(Debug, Clone)]
pub struct PyObj1 {
}

#[pyclass(name="Obj2", extends=MyBase)]
#[derive(Debug, Clone)]
pub struct MyObj2 {
}

All good so far (this explanation is missing a bunch of detail and isn't an entirely correct summary of the actual code, but hopefully enough to give context for my question)

Problem

Problem is when I try to implement the fn as_obj1(&self, py: Python) -> PyResult<PyObj1> { Ok(PyObj1{}.into_py(py)) } , I can't get past the error:

method cannot be called on PyObj1 due to unsatisfied trait bounds because

    = note: the following trait bounds were not satisfied:
            `PyObj1 AsPyPointer`
            which is required by `&PyObj1: pyo3::IntoPy<pyo3::Py<pyo3::PyAny>>`

If I change #[pyclass(name="Obj1", extends=MyBase)] to #[pyclass(name="Obj1")] then all compiles and works, except the Obj1 is of course not a subclass of my BaseThing

After a bit of poking around and rereading the docs several times, I spotted the sentence

All types in PyO3 implement this trait, as does a #[pyclass] which doesn't use extends.

..however this a bit cryptic to me. Is there a reason the "pyclass-with-extends" cannot implement IntoPy? Is there another conversion trait I should instead?

Not urgent as in my case the subclass hierarchy is just a "nice to have" thing, and I can just drop the extends=... for now

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the PyO3 0.14.3 conversions traits documentation and the #[pyclass(extends=...)] examples described in the issue. Reproduce the IntoPy error using the BaseThing and Obj1 sketches, then determine whether extended pyclasses support this conversion or require a documented alternative.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.