Skip to content

Commit

Permalink
Fix detail::obj_class_name() to work correctly for meta classes. (#…
Browse files Browse the repository at this point in the history
…4436)

* Fix `detail::obj_class_name()` to work correctly for meta classes.

* Adjust expected name for PyPy
  • Loading branch information
rwgk authored and henryiii committed Jan 3, 2023
1 parent e414c4b commit 0abe64c
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 2 deletions.
2 changes: 1 addition & 1 deletion include/pybind11/pytypes.h
Expand Up @@ -463,7 +463,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)

// Equivalent to obj.__class__.__name__ (or obj.__name__ if obj is a class).
inline const char *obj_class_name(PyObject *obj) {
if (Py_TYPE(obj) == &PyType_Type) {
if (PyType_Check(obj)) {
return reinterpret_cast<PyTypeObject *>(obj)->tp_name;
}
return Py_TYPE(obj)->tp_name;
Expand Down
2 changes: 2 additions & 0 deletions tests/test_class.cpp
Expand Up @@ -55,6 +55,8 @@ void bind_empty0(py::module_ &m) {
} // namespace test_class

TEST_SUBMODULE(class_, m) {
m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });

// test_instance
struct NoConstructor {
NoConstructor() = default;
Expand Down
11 changes: 10 additions & 1 deletion tests/test_class.py
@@ -1,10 +1,19 @@
import pytest

import env # noqa: F401
import env
from pybind11_tests import ConstructorStats, UserType
from pybind11_tests import class_ as m


def test_obj_class_name():
if env.PYPY:
expected_name = "UserType"
else:
expected_name = "pybind11_tests.UserType"
assert m.obj_class_name(UserType(1)) == expected_name
assert m.obj_class_name(UserType) == expected_name


def test_repr():
assert "pybind11_type" in repr(type(UserType))
assert "UserType" in repr(UserType)
Expand Down
2 changes: 2 additions & 0 deletions tests/test_pytypes.cpp
Expand Up @@ -99,6 +99,8 @@ void m_defs(py::module_ &m) {
} // namespace handle_from_move_only_type_with_operator_PyObject

TEST_SUBMODULE(pytypes, m) {
m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });

handle_from_move_only_type_with_operator_PyObject::m_defs(m);

// test_bool
Expand Down
6 changes: 6 additions & 0 deletions tests/test_pytypes.py
Expand Up @@ -9,6 +9,12 @@
from pybind11_tests import pytypes as m


def test_obj_class_name():
assert m.obj_class_name(None) == "NoneType"
assert m.obj_class_name(list) == "list"
assert m.obj_class_name([]) == "list"


def test_handle_from_move_only_type_with_operator_PyObject(): # noqa: N802
assert m.handle_from_move_only_type_with_operator_PyObject_ncnst()
assert m.handle_from_move_only_type_with_operator_PyObject_const()
Expand Down

0 comments on commit 0abe64c

Please sign in to comment.