Skip to content

Commit f12e098

Browse files
authored
Fix detail::obj_class_name() to work correctly for meta classes. (#4436)
* Fix `detail::obj_class_name()` to work correctly for meta classes. * Adjust expected name for PyPy
1 parent 60f02f5 commit f12e098

File tree

5 files changed

+21
-2
lines changed

5 files changed

+21
-2
lines changed

include/pybind11/pytypes.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
463463

464464
// Equivalent to obj.__class__.__name__ (or obj.__name__ if obj is a class).
465465
inline const char *obj_class_name(PyObject *obj) {
466-
if (Py_TYPE(obj) == &PyType_Type) {
466+
if (PyType_Check(obj)) {
467467
return reinterpret_cast<PyTypeObject *>(obj)->tp_name;
468468
}
469469
return Py_TYPE(obj)->tp_name;

tests/test_class.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ void bind_empty0(py::module_ &m) {
5555
} // namespace test_class
5656

5757
TEST_SUBMODULE(class_, m) {
58+
m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });
59+
5860
// test_instance
5961
struct NoConstructor {
6062
NoConstructor() = default;

tests/test_class.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import pytest
22

3-
import env # noqa: F401
3+
import env
44
from pybind11_tests import ConstructorStats, UserType
55
from pybind11_tests import class_ as m
66

77

8+
def test_obj_class_name():
9+
if env.PYPY:
10+
expected_name = "UserType"
11+
else:
12+
expected_name = "pybind11_tests.UserType"
13+
assert m.obj_class_name(UserType(1)) == expected_name
14+
assert m.obj_class_name(UserType) == expected_name
15+
16+
817
def test_repr():
918
assert "pybind11_type" in repr(type(UserType))
1019
assert "UserType" in repr(UserType)

tests/test_pytypes.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ void m_defs(py::module_ &m) {
9999
} // namespace handle_from_move_only_type_with_operator_PyObject
100100

101101
TEST_SUBMODULE(pytypes, m) {
102+
m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });
103+
102104
handle_from_move_only_type_with_operator_PyObject::m_defs(m);
103105

104106
// test_bool

tests/test_pytypes.py

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
from pybind11_tests import pytypes as m
1010

1111

12+
def test_obj_class_name():
13+
assert m.obj_class_name(None) == "NoneType"
14+
assert m.obj_class_name(list) == "list"
15+
assert m.obj_class_name([]) == "list"
16+
17+
1218
def test_handle_from_move_only_type_with_operator_PyObject(): # noqa: N802
1319
assert m.handle_from_move_only_type_with_operator_PyObject_ncnst()
1420
assert m.handle_from_move_only_type_with_operator_PyObject_const()

0 commit comments

Comments
 (0)