-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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.
What version (or hash if on master) of pybind11 are you using?
2.13.6
Problem description
Suppose that a class called Pet
is implemented in a module called example
. If an attribute reference fails, the error message is AttributeError: 'example.Pet' object has no attribute ...
. However, if the __name__
attribute is specified using pet.attr("__name__") = "PseudoPet";
then the attribute errors look like AttributeError: 'PseudoPet' object has no attribute ...
. Notice that, in the latter, there is no module name example
.
I know that the PyTypeObject.tp_name
member is different depending on whether the class/type was implemented in C or Python, and I think this gets used in include/pybind11/detail/class.h to determine various strings used for reporting. Perhaps this has something to do with the issue?
PEP 737 introduces some functions like PyType_GetModuleName()
, and adds formats to PyUnicode_FromFormat()
which may also be useful here?
Reproducible example code
In example.cpp:
#include <pybind11/pybind11.h>
namespace py = pybind11;
struct Pet {
Pet(const std::string &name) : name(name) {}
std::string name;
};
struct Person {
Person(const std::string &name) : name(name) {}
std::string name;
};
PYBIND11_MODULE(example, m) {
// Class with explicitly set __name__
py::class_<Pet> pet(m, "Pet");
pet.def(py::init<const std::string &>());
pet.attr("__name__") = "PseudoPet";
// Class with default name
py::class_<Person> person(m, "Person");
person.def(py::init<const std::string &>());
}
In an interactive Python session:
>>> from example import Pet, Person
>>> my_pet = Pet("John")
>>> my_pet.age
AttributeError: 'PseudoPet' object has no attribute 'age'
>>> my_person = Person("Jane")
>>> my_person.age
AttributeError: 'example.Person' object has no attribute 'age'
Is this a regression? Put the last known working version here if it is.
Not a regression