feat: py::type::of<T>() and py::type::of(h) (#2364)
* feat: type<T>()
* refactor: using py::type as class
* refactor: py::object as base
* wip: tigher api
* refactor: fix conversion and limit API further
* docs: some added notes from @EricCousineau-TRI
* refactor: use py::type::of
diff --git a/tests/test_class.cpp b/tests/test_class.cpp
index 5369cb0..b7d52a1 100644
--- a/tests/test_class.cpp
+++ b/tests/test_class.cpp
@@ -134,6 +134,32 @@
);
});
+ struct Invalid {};
+
+ // test_type
+ m.def("check_type", [](int category) {
+ // Currently not supported (via a fail at compile time)
+ // See https://github.com/pybind/pybind11/issues/2486
+ // if (category == 2)
+ // return py::type::of<int>();
+ if (category == 1)
+ return py::type::of<DerivedClass1>();
+ else
+ return py::type::of<Invalid>();
+ });
+
+ m.def("get_type_of", [](py::object ob) {
+ return py::type::of(ob);
+ });
+
+ m.def("as_type", [](py::object ob) {
+ auto tp = py::type(ob);
+ if (py::isinstance<py::type>(ob))
+ return tp;
+ else
+ throw std::runtime_error("Invalid type");
+ });
+
// test_mismatched_holder
struct MismatchBase1 { };
struct MismatchDerived1 : MismatchBase1 { };
diff --git a/tests/test_class.py b/tests/test_class.py
index 4214fe7..be21f37 100644
--- a/tests/test_class.py
+++ b/tests/test_class.py
@@ -26,6 +26,40 @@
assert cstats.alive() == 0
+def test_type():
+ assert m.check_type(1) == m.DerivedClass1
+ with pytest.raises(RuntimeError) as execinfo:
+ m.check_type(0)
+
+ assert 'pybind11::detail::get_type_info: unable to find type info' in str(execinfo.value)
+ assert 'Invalid' in str(execinfo.value)
+
+ # Currently not supported
+ # See https://github.com/pybind/pybind11/issues/2486
+ # assert m.check_type(2) == int
+
+
+def test_type_of_py():
+ assert m.get_type_of(1) == int
+ assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
+ assert m.get_type_of(int) == type
+
+
+def test_type_of_py_nodelete():
+ # If the above test deleted the class, this will segfault
+ assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
+
+
+def test_as_type_py():
+ assert m.as_type(int) == int
+
+ with pytest.raises(RuntimeError):
+ assert m.as_type(1) == int
+
+ with pytest.raises(RuntimeError):
+ assert m.as_type(m.DerivedClass1()) == m.DerivedClass1
+
+
def test_docstrings(doc):
assert doc(UserType) == "A `py::class_` type for testing"
assert UserType.__name__ == "UserType"