/* pybind11/typing.h: Convenience wrapper classes for basic Python types with more explicit annotations. Copyright (c) 2023 Dustin Spicuzza All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #pragma once #include "detail/common.h" #include "cast.h" #include "pytypes.h" #include #if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L # define PYBIND11_TYPING_H_HAS_STRING_LITERAL # include # include # include #endif PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(typing) /* The following types can be used to direct pybind11-generated docstrings to have have more explicit types (e.g., `list[str]` instead of `list`). Just use these in place of existing types. There is no additional enforcement of types at runtime. */ template class Tuple : public tuple { using tuple::tuple; }; template class Dict : public dict { using dict::dict; }; template class List : public list { using list::list; }; template class Set : public set { using set::set; }; template class Iterable : public iterable { using iterable::iterable; }; template class Iterator : public iterator { using iterator::iterator; }; template class Callable; template class Callable : public function { using function::function; }; template class Type : public type { using type::type; }; template class Union : public object { PYBIND11_OBJECT_DEFAULT(Union, object, PyObject_Type) using object::object; }; template class Optional : public object { PYBIND11_OBJECT_DEFAULT(Optional, object, PyObject_Type) using object::object; }; template class Final : public object { PYBIND11_OBJECT_DEFAULT(Final, object, PyObject_Type) using object::object; }; template class ClassVar : public object { PYBIND11_OBJECT_DEFAULT(ClassVar, object, PyObject_Type) using object::object; }; template class TypeGuard : public bool_ { using bool_::bool_; }; template class TypeIs : public bool_ { using bool_::bool_; }; class NoReturn : public none { using none::none; }; class Never : public none { using none::none; }; #if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL) template struct StringLiteral { constexpr StringLiteral(const char (&str)[N]) { std::copy_n(str, N, name); } char name[N]; }; template class Literal : public object { PYBIND11_OBJECT_DEFAULT(Literal, object, PyObject_Type) }; // Example syntax for creating a TypeVar. // typedef typing::TypeVar<"T"> TypeVarT; template class TypeVar : public object { PYBIND11_OBJECT_DEFAULT(TypeVar, object, PyObject_Type) using object::object; }; #endif PYBIND11_NAMESPACE_END(typing) PYBIND11_NAMESPACE_BEGIN(detail) template struct handle_type_name> { static constexpr auto name = const_name("tuple[") + ::pybind11::detail::concat(make_caster::name...) + const_name("]"); }; template <> struct handle_type_name> { // PEP 484 specifies this syntax for an empty tuple static constexpr auto name = const_name("tuple[()]"); }; template struct handle_type_name> { // PEP 484 specifies this syntax for a variable-length tuple static constexpr auto name = const_name("tuple[") + make_caster::name + const_name(", ...]"); }; template struct handle_type_name> { static constexpr auto name = const_name("dict[") + make_caster::name + const_name(", ") + make_caster::name + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name("list[") + make_caster::name + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name("set[") + make_caster::name + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name("collections.abc.Iterable[") + make_caster::name + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name("collections.abc.Iterator[") + make_caster::name + const_name("]"); }; template struct handle_type_name> { using retval_type = conditional_t::value, void_type, Return>; static constexpr auto name = const_name("collections.abc.Callable[[") + ::pybind11::detail::concat(::pybind11::detail::arg_descr(make_caster::name)...) + const_name("], ") + ::pybind11::detail::return_descr(make_caster::name) + const_name("]"); }; template struct handle_type_name> { // PEP 484 specifies this syntax for defining only return types of callables using retval_type = conditional_t::value, void_type, Return>; static constexpr auto name = const_name("collections.abc.Callable[..., ") + ::pybind11::detail::return_descr(make_caster::name) + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name("type[") + make_caster::name + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = ::pybind11::detail::union_concat(make_caster::name...); }; template struct handle_type_name> { static constexpr auto name = make_caster::name | make_caster::name; }; template struct handle_type_name> { static constexpr auto name = const_name("typing.Final[") + ::pybind11::detail::return_descr(make_caster::name) + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name("typing.ClassVar[") + make_caster::name + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name(PYBIND11_TYPE_GUARD_TYPE_HINT) + const_name("[") + make_caster::name + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name(PYBIND11_TYPE_IS_TYPE_HINT) + const_name("[") + make_caster::name + const_name("]"); }; template <> struct handle_type_name { static constexpr auto name = const_name("typing.NoReturn"); }; template <> struct handle_type_name { static constexpr auto name = const_name(PYBIND11_NEVER_TYPE_HINT); }; #if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL) template consteval auto sanitize_string_literal() { constexpr std::string_view v(StrLit.name); constexpr std::string_view special_chars("!@%{}-"); constexpr auto num_special_chars = std::accumulate( special_chars.begin(), special_chars.end(), (size_t) 0, [&v](auto acc, const char &c) { return std::move(acc) + std::ranges::count(v, c); }); char result[v.size() + num_special_chars + 1]; size_t i = 0; for (auto c : StrLit.name) { if (special_chars.find(c) != std::string_view::npos) { result[i++] = '!'; } result[i++] = c; } return typing::StringLiteral(result); } template struct handle_type_name> { static constexpr auto name = const_name("typing.Literal[") + pybind11::detail::concat(const_name(sanitize_string_literal().name)...) + const_name("]"); }; template struct handle_type_name> { static constexpr auto name = const_name(sanitize_string_literal().name); }; #endif PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)