[BUG]: __getattr__ and multiple inheritance with smart holders
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 18k
- Forks
- 2.3k
- Avg merge
- 5d 17h
- Merged PRs (30d)
- 10
Description
Required prerequisites
- Make sure you've read the documentation. Your issue may be addressed there.
- Search the issue tracker and Discussions to verify that this hasn't already been reported. +1 or comment there if it has.
- Consider asking first in the Gitter chat room or in a Discussion.
Problem description
Hi, I've found an other issue related to #3788
this is in regard to the smart holder branch
The example code below fails with infinite recursive getattr calls.
removing either Base2, Derived2 or the binding of __getattr__ removes the problem.
removing the following lines
https://github.com/pybind/pybind11/blob/9d4b4dffce6677a7c9a9af37a45f4436d353f5e1/include/pybind11/detail/smart_holder_type_casters.h#L295-L297
also removes the issue.
Reproducible example code
// Binding code
#include <pybind11/pybind11.h>
namespace py = pybind11;
struct Base1 {int a1{};};
struct Base2 {int a2{};};
struct Base12 : Base1, Base2 {
virtual ~Base12() = default;
int foo() const { return 0; }
};
struct Derived1 : Base12 {
int bar() const { return 1; }
};
struct Derived2 : Base12 {
int bar() const { return 2; }
};
PYBIND11_MODULE(foo, m) {
py::class_<Base1>(m, "Base1");
py::class_<Base2>(m, "Base2");
py::class_<Base12, Base1, Base2>(m, "Base12")
.def(py::init<>())
.def("foo", &Base12::foo)
.def("__getattr__", [](Base12&, std::string key) {
return "Base GetAttr: " + key;
});
py::class_<Derived1, Base12>(m, "Derived1")
.def(py::init<>())
.def("bar", &Derived1::bar);
py::class_<Derived2, Base12>(m, "Derived2")
.def(py::init<>())
.def("bar", &Derived2::bar);
}
// Test code
import foo
d1 = foo.Derived1()
print(f"d1.foo(): {d1.foo()}")
print(f"d1.bar(): {d1.bar()}")
print(f"d1.prop1: {d1.prop1}")
d2 = foo.Derived2()
print(f"d2.foo(): {d2.foo()}")
print(f"d2.bar(): {d2.bar()}")
print(f"d2.prop1: {d2.prop2}")
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproducer in the issue and inspect include/pybind11/detail/smart_holder_type_casters.h around lines 295-297. Reproduce the infinite recursive getattr calls with multiple inheritance and smart holders; done means the example no longer recurses while preserving the described bindings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100