PyO3 / PyO3/pyo3

Support for classattr and getter on pyclass attribute of the same name

Open
#4,786 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Hi, I'd like to make a pyclass with a classattr and regular attribute with the same name. See this example:

#[pyclass]
struct PyO3Class {
    #[pyo3(get, set)]
    attr: i32,
}

#[pymethods]
impl PyO3Class {
    #[new]
    fn new(attr: i32) -> Self {
        Self { attr }
    }

    #[classattr]
    fn attr() -> String {
        "From the class".to_string()
    }
}

My expectation based on standard Python behaviour is that when I access .attr on a class, I should get the string from the classattr, whereas on an instance I get the integer value out from the instance.

See this Python code demonstrating this:

class PythonClass:
    attr: str = "From the class"

    def __init__(self, attr: int) -> None:
        self.attr = attr


python_instance = PythonClass(123)
print("PythonClass.attr", PythonClass.attr)
print("instance.attr", python_instance.attr)

outputting:

PythonClass.attr From the class
instance.attr 123

However, from PyO3 class above, the equivalent code:

from example import PyO3Class

pyo3_instance = PyO3Class(123)
print("PyO3Class.attr", PyO3Class.attr)
print("pyo3_instance.attr", pyo3_instance.attr)

outputs:

PyO3Class.attr From the class
pyo3_instance.attr From the class

I've tried a few other patterns to try and get this to work:

  • Implement a #[getter] explicitly and play with the order
  • Do inheritance and have the classattr in the base class
  • Call PyO3Class::type_object(py).setattr("attr", "From the class") on module initialisation

However all resulted in the same behaviour.

I've opened this issue as suggested by @davidhewitt on Discord.

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 pyclass and pymethods handling for #[pyo3(get, set)] attributes and #[classattr], then reproduce the Rust and Python examples from the issue. Done means class access returns the class attribute while instance access returns the instance value when both share the same name.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.