Replies: 1 comment
-
To clarify, I am aware of this previous discussion thread (#3503) and Appendix B from the PyO3 user guide. These both implement boilerplate wrapper functions around each trait function for each struct, which is the temporary solution I am using at the moment. #[pymethods]
impl SomeStruct {
fn function_a(&self) -> String {
FirstTrait::function_a(self)
}
} From my perspective, this approach undermines the advantages of using traits in the first place. We still have to manually write wrapper methods for every trait function used by each struct. For large codebases with many structs and traits, this introduces a significant amount of boilerplate and maintenance effort. Since #3503 is >1 year old, I'm wondering if there has been any progress in this area? If not, is there any practical or ideological reason why this could not be a feature in a future PyO3 release? |
Beta Was this translation helpful? Give feedback.
-
Hi everyone,
I’d like to request a feature (or learn about any existing workarounds) for making PyO3 work with Rust trait methods.
Background
Rust traits with default function implementations are a flexible and powerful way to add functionality to multiple structs without duplicating logic. This approach allows function logic to be written once and reused across multiple structs, making maintenance easier and ensuring consistency.
For a minimal example, suppose we have two traits, each providing different functionality:
Now, we can define a struct and give it access to these two functions by implementing the traits.
If we wanted to add another struct which only had access to
function_a
but notfunction_b
, that would be as simple as:If we ever need to update
function_a
orfunction_b
, the logic only needs to change in one place, and all implementing structs will automatically inherit the updated logic. This is a clean and highly-maintainable approach.Issue with PyO3
When trying to expose these trait methods to Python using PyO3, I have encountered the following issues:
1.
#[pymethods]
can’t be applied to a trait impl block.2. Functions inside the trait cannot be labelled with
#[pyfunction]
This may be because
#[pyfunction]
is intended to work only on static functions which do not take&self
? RestrictingSelf
to ensure it is always a struct labelled with#[PyClass]
doesn't seem to help.Temporary solution
The only way I can find to expose these methods is by writing boilerplate wrapper methods for each struct.
This works, but it undermines the advantages of using traits in the first place. We still have to manually write wrapper methods for each struct, which increases boilerplate and maintenance effort. It seems like these wrappers should be fairly simple to automate?
Feature Request / Workaround?
Is there any way to expose trait methods to Python without needing to write explicit wrapper functions for every implementing struct? If not, do you think it would be possible for PyO3 to support this in a future version?
Thanks,
Millie :)
Beta Was this translation helpful? Give feedback.
All reactions