mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
Bug fixes: Add missing handle_type_name
specializations. (#5073)
* Transfer bug fixes from #4888 wholesale. Full test coverage for all fixes is still missing. * Add cmake option(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION) and use in some tests.
This commit is contained in:
parent
705efccecd
commit
0efff79f01
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -114,6 +114,7 @@ jobs:
|
|||||||
run: >
|
run: >
|
||||||
cmake -S . -B .
|
cmake -S . -B .
|
||||||
-DPYBIND11_WERROR=ON
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DPYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION=ON
|
||||||
-DPYBIND11_SIMPLE_GIL_MANAGEMENT=ON
|
-DPYBIND11_SIMPLE_GIL_MANAGEMENT=ON
|
||||||
-DPYBIND11_NUMPY_1_ONLY=ON
|
-DPYBIND11_NUMPY_1_ONLY=ON
|
||||||
-DDOWNLOAD_CATCH=ON
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
@ -107,6 +107,8 @@ endif()
|
|||||||
option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
|
option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
|
||||||
option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
|
option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
|
||||||
option(PYBIND11_NOPYTHON "Disable search for Python" OFF)
|
option(PYBIND11_NOPYTHON "Disable search for Python" OFF)
|
||||||
|
option(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION
|
||||||
|
"To enforce that a handle_type_name<> specialization exists" OFF)
|
||||||
option(PYBIND11_SIMPLE_GIL_MANAGEMENT
|
option(PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||||
"Use simpler GIL management logic that does not support disassociation" OFF)
|
"Use simpler GIL management logic that does not support disassociation" OFF)
|
||||||
option(PYBIND11_NUMPY_1_ONLY
|
option(PYBIND11_NUMPY_1_ONLY
|
||||||
@ -115,6 +117,9 @@ set(PYBIND11_INTERNALS_VERSION
|
|||||||
""
|
""
|
||||||
CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
|
CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
|
||||||
|
|
||||||
|
if(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
|
||||||
|
add_compile_definitions(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
|
||||||
|
endif()
|
||||||
if(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
if(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
add_compile_definitions(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
add_compile_definitions(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||||
endif()
|
endif()
|
||||||
|
@ -881,10 +881,53 @@ struct is_holder_type
|
|||||||
template <typename base, typename deleter>
|
template <typename base, typename deleter>
|
||||||
struct is_holder_type<base, std::unique_ptr<base, deleter>> : std::true_type {};
|
struct is_holder_type<base, std::unique_ptr<base, deleter>> : std::true_type {};
|
||||||
|
|
||||||
|
#ifdef PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION // See PR #4888
|
||||||
|
|
||||||
|
// This leads to compilation errors if a specialization is missing.
|
||||||
|
template <typename T>
|
||||||
|
struct handle_type_name;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct handle_type_name {
|
struct handle_type_name {
|
||||||
static constexpr auto name = const_name<T>();
|
static constexpr auto name = const_name<T>();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<object> {
|
||||||
|
static constexpr auto name = const_name("object");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<list> {
|
||||||
|
static constexpr auto name = const_name("list");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<dict> {
|
||||||
|
static constexpr auto name = const_name("dict");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<anyset> {
|
||||||
|
static constexpr auto name = const_name("Union[set, frozenset]");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<set> {
|
||||||
|
static constexpr auto name = const_name("set");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<frozenset> {
|
||||||
|
static constexpr auto name = const_name("frozenset");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<str> {
|
||||||
|
static constexpr auto name = const_name("str");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<tuple> {
|
||||||
|
static constexpr auto name = const_name("tuple");
|
||||||
|
};
|
||||||
template <>
|
template <>
|
||||||
struct handle_type_name<bool_> {
|
struct handle_type_name<bool_> {
|
||||||
static constexpr auto name = const_name("bool");
|
static constexpr auto name = const_name("bool");
|
||||||
@ -930,6 +973,34 @@ struct handle_type_name<sequence> {
|
|||||||
static constexpr auto name = const_name("Sequence");
|
static constexpr auto name = const_name("Sequence");
|
||||||
};
|
};
|
||||||
template <>
|
template <>
|
||||||
|
struct handle_type_name<bytearray> {
|
||||||
|
static constexpr auto name = const_name("bytearray");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<memoryview> {
|
||||||
|
static constexpr auto name = const_name("memoryview");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<slice> {
|
||||||
|
static constexpr auto name = const_name("slice");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<type> {
|
||||||
|
static constexpr auto name = const_name("type");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<capsule> {
|
||||||
|
static constexpr auto name = const_name("capsule");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<ellipsis> {
|
||||||
|
static constexpr auto name = const_name("ellipsis");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<weakref> {
|
||||||
|
static constexpr auto name = const_name("weakref");
|
||||||
|
};
|
||||||
|
template <>
|
||||||
struct handle_type_name<args> {
|
struct handle_type_name<args> {
|
||||||
static constexpr auto name = const_name("*args");
|
static constexpr auto name = const_name("*args");
|
||||||
};
|
};
|
||||||
@ -937,6 +1008,30 @@ template <>
|
|||||||
struct handle_type_name<kwargs> {
|
struct handle_type_name<kwargs> {
|
||||||
static constexpr auto name = const_name("**kwargs");
|
static constexpr auto name = const_name("**kwargs");
|
||||||
};
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<obj_attr_accessor> {
|
||||||
|
static constexpr auto name = const_name<obj_attr_accessor>();
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<str_attr_accessor> {
|
||||||
|
static constexpr auto name = const_name<str_attr_accessor>();
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<item_accessor> {
|
||||||
|
static constexpr auto name = const_name<item_accessor>();
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<sequence_accessor> {
|
||||||
|
static constexpr auto name = const_name<sequence_accessor>();
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<list_accessor> {
|
||||||
|
static constexpr auto name = const_name<list_accessor>();
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<tuple_accessor> {
|
||||||
|
static constexpr auto name = const_name<tuple_accessor>();
|
||||||
|
};
|
||||||
|
|
||||||
template <typename type>
|
template <typename type>
|
||||||
struct pyobject_caster {
|
struct pyobject_caster {
|
||||||
|
@ -1201,13 +1201,17 @@ protected:
|
|||||||
static Constructor make_move_constructor(...) { return nullptr; }
|
static Constructor make_move_constructor(...) { return nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::string quote_cpp_type_name(const std::string &cpp_type_name) {
|
||||||
|
return cpp_type_name; // No-op for now. See PR #4888
|
||||||
|
}
|
||||||
|
|
||||||
PYBIND11_NOINLINE std::string type_info_description(const std::type_info &ti) {
|
PYBIND11_NOINLINE std::string type_info_description(const std::type_info &ti) {
|
||||||
if (auto *type_data = get_type_info(ti)) {
|
if (auto *type_data = get_type_info(ti)) {
|
||||||
handle th((PyObject *) type_data->type);
|
handle th((PyObject *) type_data->type);
|
||||||
return th.attr("__module__").cast<std::string>() + '.'
|
return th.attr("__module__").cast<std::string>() + '.'
|
||||||
+ th.attr("__qualname__").cast<std::string>();
|
+ th.attr("__qualname__").cast<std::string>();
|
||||||
}
|
}
|
||||||
return clean_type_id(ti.name());
|
return quote_cpp_type_name(clean_type_id(ti.name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_END(detail)
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
@ -46,10 +46,16 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
|||||||
|
|
||||||
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||||
|
|
||||||
|
class dtype; // Forward declaration
|
||||||
class array; // Forward declaration
|
class array; // Forward declaration
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<dtype> {
|
||||||
|
static constexpr auto name = const_name("numpy.dtype");
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct handle_type_name<array> {
|
struct handle_type_name<array> {
|
||||||
static constexpr auto name = const_name("numpy.ndarray");
|
static constexpr auto name = const_name("numpy.ndarray");
|
||||||
|
@ -492,9 +492,7 @@ protected:
|
|||||||
signature += rec->scope.attr("__module__").cast<std::string>() + "."
|
signature += rec->scope.attr("__module__").cast<std::string>() + "."
|
||||||
+ rec->scope.attr("__qualname__").cast<std::string>();
|
+ rec->scope.attr("__qualname__").cast<std::string>();
|
||||||
} else {
|
} else {
|
||||||
std::string tname(t->name());
|
signature += detail::quote_cpp_type_name(detail::clean_type_id(t->name()));
|
||||||
detail::clean_type_id(tname);
|
|
||||||
signature += tname;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
signature += c;
|
signature += c;
|
||||||
@ -1192,6 +1190,15 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<cpp_function> {
|
||||||
|
static constexpr auto name = const_name("Callable");
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
/// Wrapper for Python extension modules
|
/// Wrapper for Python extension modules
|
||||||
class module_ : public object {
|
class module_ : public object {
|
||||||
public:
|
public:
|
||||||
@ -1319,6 +1326,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<module_> {
|
||||||
|
static constexpr auto name = const_name("module");
|
||||||
|
};
|
||||||
|
|
||||||
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
|
||||||
// When inside a namespace (or anywhere as long as it's not the first item on a line),
|
// When inside a namespace (or anywhere as long as it's not the first item on a line),
|
||||||
// C++20 allows "module" to be used. This is provided for backward compatibility, and for
|
// C++20 allows "module" to be used. This is provided for backward compatibility, and for
|
||||||
// simplicity, if someone wants to use py::module for example, that is perfectly safe.
|
// simplicity, if someone wants to use py::module for example, that is perfectly safe.
|
||||||
@ -2611,6 +2627,11 @@ public:
|
|||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<exception<void>> {
|
||||||
|
static constexpr auto name = const_name("Exception");
|
||||||
|
};
|
||||||
|
|
||||||
// Helper function for register_exception and register_local_exception
|
// Helper function for register_exception and register_local_exception
|
||||||
template <typename CppException>
|
template <typename CppException>
|
||||||
exception<CppException> &
|
exception<CppException> &
|
||||||
|
@ -59,6 +59,7 @@ struct sequence_item;
|
|||||||
struct list_item;
|
struct list_item;
|
||||||
struct tuple_item;
|
struct tuple_item;
|
||||||
} // namespace accessor_policies
|
} // namespace accessor_policies
|
||||||
|
// PLEASE KEEP handle_type_name SPECIALIZATIONS IN SYNC.
|
||||||
using obj_attr_accessor = accessor<accessor_policies::obj_attr>;
|
using obj_attr_accessor = accessor<accessor_policies::obj_attr>;
|
||||||
using str_attr_accessor = accessor<accessor_policies::str_attr>;
|
using str_attr_accessor = accessor<accessor_policies::str_attr>;
|
||||||
using item_accessor = accessor<accessor_policies::generic_item>;
|
using item_accessor = accessor<accessor_policies::generic_item>;
|
||||||
|
@ -382,4 +382,7 @@ TEST_SUBMODULE(exceptions, m) {
|
|||||||
// function returns None instead of int, should give a useful error message
|
// function returns None instead of int, should give a useful error message
|
||||||
fn().cast<int>();
|
fn().cast<int>();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// m.def("pass_exception_void", [](const py::exception<void>&) {}); // Does not compile.
|
||||||
|
m.def("return_exception_void", []() { return py::exception<void>(); });
|
||||||
}
|
}
|
||||||
|
@ -424,3 +424,9 @@ def test_fn_cast_int_exception():
|
|||||||
assert str(excinfo.value).startswith(
|
assert str(excinfo.value).startswith(
|
||||||
"Unable to cast Python instance of type <class 'NoneType'> to C++ type"
|
"Unable to cast Python instance of type <class 'NoneType'> to C++ type"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_return_exception_void():
|
||||||
|
with pytest.raises(TypeError) as excinfo:
|
||||||
|
m.return_exception_void()
|
||||||
|
assert "Exception" in str(excinfo.value)
|
||||||
|
@ -41,6 +41,15 @@ class float_ : public py::object {
|
|||||||
};
|
};
|
||||||
} // namespace external
|
} // namespace external
|
||||||
|
|
||||||
|
namespace pybind11 {
|
||||||
|
namespace detail {
|
||||||
|
template <>
|
||||||
|
struct handle_type_name<external::float_> {
|
||||||
|
static constexpr auto name = const_name("float");
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace pybind11
|
||||||
|
|
||||||
namespace implicit_conversion_from_0_to_handle {
|
namespace implicit_conversion_from_0_to_handle {
|
||||||
// Uncomment to trigger compiler error. Note: Before PR #4008 this used to compile successfully.
|
// Uncomment to trigger compiler error. Note: Before PR #4008 this used to compile successfully.
|
||||||
// void expected_to_trigger_compiler_error() { py::handle(0); }
|
// void expected_to_trigger_compiler_error() { py::handle(0); }
|
||||||
|
@ -121,7 +121,7 @@ def test_set(capture, doc):
|
|||||||
assert m.anyset_contains({"foo"}, "foo")
|
assert m.anyset_contains({"foo"}, "foo")
|
||||||
|
|
||||||
assert doc(m.get_set) == "get_set() -> set"
|
assert doc(m.get_set) == "get_set() -> set"
|
||||||
assert doc(m.print_anyset) == "print_anyset(arg0: anyset) -> None"
|
assert doc(m.print_anyset) == "print_anyset(arg0: Union[set, frozenset]) -> None"
|
||||||
|
|
||||||
|
|
||||||
def test_frozenset(capture, doc):
|
def test_frozenset(capture, doc):
|
||||||
|
Loading…
Reference in New Issue
Block a user