Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ class type_caster<void> : public type_caster<void_type> {
template <typename T>
using cast_op_type = void *&;
explicit operator void *&() { return value; }
static constexpr auto name = const_name("types.CapsuleType");
static constexpr auto name = const_name(PYBIND11_CAPSULE_TYPE_TYPE_HINT);

private:
void *value = nullptr;
Expand Down Expand Up @@ -1361,7 +1361,11 @@ struct handle_type_name<dict> {
};
template <>
struct handle_type_name<anyset> {
#if PYBIND11_USE_NEW_UNIONS
static constexpr auto name = const_name("set | frozenset");
#else
static constexpr auto name = const_name("typing.Union[set, frozenset]");
#endif
};
template <>
struct handle_type_name<set> {
Expand Down Expand Up @@ -1441,7 +1445,7 @@ struct handle_type_name<type> {
};
template <>
struct handle_type_name<capsule> {
static constexpr auto name = const_name("types.CapsuleType");
static constexpr auto name = const_name(PYBIND11_CAPSULE_TYPE_TYPE_HINT);
};
template <>
struct handle_type_name<ellipsis> {
Expand Down
25 changes: 25 additions & 0 deletions include/pybind11/detail/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,38 @@
# define PYBIND11_HAS_SUBINTERPRETER_SUPPORT
#endif

// 3.13 Compatibility
#if 0x030D0000 <= PY_VERSION_HEX
# define PYBIND11_TYPE_IS_TYPE_HINT "typing.TypeIs"
# define PYBIND11_CAPSULE_TYPE_TYPE_HINT "types.CapsuleType"
#else
# define PYBIND11_TYPE_IS_TYPE_HINT "typing_extensions.TypeIs"
# define PYBIND11_CAPSULE_TYPE_TYPE_HINT "typing_extensions.CapsuleType"
#endif

// 3.12 Compatibility
#if 0x030C0000 <= PY_VERSION_HEX
# define PYBIND11_BUFFER_TYPE_HINT "collections.abc.Buffer"
#else
# define PYBIND11_BUFFER_TYPE_HINT "typing_extensions.Buffer"
#endif

// 3.11 Compatibility
#if 0x030B0000 <= PY_VERSION_HEX
# define PYBIND11_NEVER_TYPE_HINT "typing.Never"
#else
# define PYBIND11_NEVER_TYPE_HINT "typing_extensions.Never"
#endif

// 3.10 Compatibility
#if 0x030A0000 <= PY_VERSION_HEX
# define PYBIND11_USE_NEW_UNIONS true
# define PYBIND11_TYPE_GUARD_TYPE_HINT "typing.TypeGuard"
#else
# define PYBIND11_USE_NEW_UNIONS false
# define PYBIND11_TYPE_GUARD_TYPE_HINT "typing_extensions.TypeGuard"
#endif

// #define PYBIND11_STR_LEGACY_PERMISSIVE
// If DEFINED, pybind11::str can hold PyUnicodeObject or PyBytesObject
// (probably surprising and never documented, but this was the
Expand Down
24 changes: 24 additions & 0 deletions include/pybind11/detail/descr.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,18 @@ constexpr descr<1, Type> _() {
#endif // #ifndef _

constexpr descr<0> concat() { return {}; }
constexpr descr<0> union_concat() { return {}; }

template <size_t N, typename... Ts>
constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) {
return descr;
}

template <size_t N, typename... Ts>
constexpr descr<N, Ts...> union_concat(const descr<N, Ts...> &descr) {
return descr;
}

#ifdef __cpp_fold_expressions
template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
constexpr descr<N1 + N2 + 2, Ts1..., Ts2...> operator,(const descr<N1, Ts1...> &a,
Expand All @@ -174,12 +180,30 @@ template <size_t N, typename... Ts, typename... Args>
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) {
return (d, ..., args);
}

template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
constexpr descr<N1 + N2 + 3, Ts1..., Ts2...> operator|(const descr<N1, Ts1...> &a,
const descr<N2, Ts2...> &b) {
return a + const_name(" | ") + b;
}

template <size_t N, typename... Ts, typename... Args>
constexpr auto union_concat(const descr<N, Ts...> &d, const Args &...args) {
return (d | ... | args);
}

#else
template <size_t N, typename... Ts, typename... Args>
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
-> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
return d + const_name(", ") + concat(args...);
}

template <size_t N, typename... Ts, typename... Args>
constexpr auto union_concat(const descr<N, Ts...> &d, const Args &...args)
-> decltype(std::declval<descr<N + 3, Ts...>>() + union_concat(args...)) {
return d + const_name(" | ") + union_concat(args...);
}
#endif

template <size_t N, typename... Ts>
Expand Down
4 changes: 4 additions & 0 deletions include/pybind11/stl/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ struct path_caster {
return true;
}

# if PYBIND11_USE_NEW_UNIONS
PYBIND11_TYPE_CASTER(T, io_name("os.PathLike | str | bytes", "pathlib.Path"));
# else
PYBIND11_TYPE_CASTER(T, io_name("typing.Union[os.PathLike, str, bytes]", "pathlib.Path"));
# endif
};

#endif // PYBIND11_HAS_FILESYSTEM || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
Expand Down
19 changes: 14 additions & 5 deletions include/pybind11/typing.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,24 @@ struct handle_type_name<typing::Type<T>> {

template <typename... Types>
struct handle_type_name<typing::Union<Types...>> {
#if PYBIND11_USE_NEW_UNIONS
static constexpr auto name = ::pybind11::detail::union_concat(make_caster<Types>::name...);
#else
static constexpr auto name = const_name("typing.Union[")
+ ::pybind11::detail::concat(make_caster<Types>::name...)
+ const_name("]");
#endif
};

template <typename T>
struct handle_type_name<typing::Optional<T>> {
#if PYBIND11_USE_NEW_UNIONS
static constexpr auto name
= ::pybind11::detail::union_concat(make_caster<T>::name, make_caster<none>::name);
#else
static constexpr auto name
= const_name("typing.Optional[") + make_caster<T>::name + const_name("]");
#endif
};

template <typename T>
Expand All @@ -244,14 +253,14 @@ struct handle_type_name<typing::ClassVar<T>> {

template <typename T>
struct handle_type_name<typing::TypeGuard<T>> {
static constexpr auto name
= const_name("typing.TypeGuard[") + make_caster<T>::name + const_name("]");
static constexpr auto name = const_name(PYBIND11_TYPE_GUARD_TYPE_HINT) + const_name("[")
+ make_caster<T>::name + const_name("]");
};

template <typename T>
struct handle_type_name<typing::TypeIs<T>> {
static constexpr auto name
= const_name("typing.TypeIs[") + make_caster<T>::name + const_name("]");
static constexpr auto name = const_name(PYBIND11_TYPE_IS_TYPE_HINT) + const_name("[")
+ make_caster<T>::name + const_name("]");
};

template <>
Expand All @@ -261,7 +270,7 @@ struct handle_type_name<typing::NoReturn> {

template <>
struct handle_type_name<typing::Never> {
static constexpr auto name = const_name("typing.Never");
static constexpr auto name = const_name(PYBIND11_NEVER_TYPE_HINT);
};

#if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL)
Expand Down
32 changes: 23 additions & 9 deletions tests/test_opaque_types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import sys

import pytest

import env
Expand Down Expand Up @@ -37,15 +39,27 @@ def test_pointers(msg):

with pytest.raises(TypeError) as excinfo:
m.get_void_ptr_value([1, 2, 3]) # This should not work
assert (
msg(excinfo.value)
== """
get_void_ptr_value(): incompatible function arguments. The following argument types are supported:
1. (arg0: types.CapsuleType) -> int

Invoked with: [1, 2, 3]
"""
)

if sys.version_info >= (3, 13):
assert (
msg(excinfo.value)
== """
get_void_ptr_value(): incompatible function arguments. The following argument types are supported:
1. (arg0: types.CapsuleType) -> int

Invoked with: [1, 2, 3]
"""
)
else:
assert (
msg(excinfo.value)
== """
get_void_ptr_value(): incompatible function arguments. The following argument types are supported:
1. (arg0: typing_extensions.CapsuleType) -> int

Invoked with: [1, 2, 3]
"""
)

assert m.return_null_str() is None
assert m.get_null_str_value(m.return_null_str()) is not None
Expand Down
5 changes: 5 additions & 0 deletions tests/test_pytypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,11 @@ namespace detail {

template <>
struct type_caster<RealNumber> {
#if PYBIND11_USE_NEW_UNIONS
PYBIND11_TYPE_CASTER(RealNumber, io_name("float | int", "float"));
#else
PYBIND11_TYPE_CASTER(RealNumber, io_name("typing.Union[float, int]", "float"));
#endif

static handle cast(const RealNumber &number, return_value_policy, handle) {
return py::float_(number.value).release();
Expand All @@ -172,6 +176,7 @@ struct type_caster<RealNumber> {
value.value = src.cast<double>();
return true;
}
// static void f/
};

} // namespace detail
Expand Down
Loading
Loading