File indexing completed on 2026-04-01 08:27:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include "pybind11.h"
0013 #include "detail/common.h"
0014 #include "detail/descr.h"
0015 #include "detail/type_caster_base.h"
0016
0017 #include <deque>
0018 #include <initializer_list>
0019 #include <list>
0020 #include <map>
0021 #include <memory>
0022 #include <ostream>
0023 #include <set>
0024 #include <unordered_map>
0025 #include <unordered_set>
0026 #include <valarray>
0027
0028
0029 #if defined(PYBIND11_HAS_OPTIONAL)
0030 # include <optional>
0031 #elif defined(PYBIND11_HAS_EXP_OPTIONAL)
0032 # include <experimental/optional>
0033 #endif
0034
0035 #if defined(PYBIND11_HAS_VARIANT)
0036 # include <variant>
0037 #endif
0038
0039 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0040 PYBIND11_NAMESPACE_BEGIN(detail)
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 inline bool object_is_instance_with_one_of_tp_names(PyObject *obj,
0078 std::initializer_list<const char *> tp_names) {
0079 if (PyType_Check(obj)) {
0080 return false;
0081 }
0082 const char *obj_tp_name = Py_TYPE(obj)->tp_name;
0083 for (const auto *tp_name : tp_names) {
0084 if (std::strcmp(obj_tp_name, tp_name) == 0) {
0085 return true;
0086 }
0087 }
0088 return false;
0089 }
0090
0091 inline bool object_is_convertible_to_std_vector(const handle &src) {
0092
0093 if (PySequence_Check(src.ptr()) != 0) {
0094 return !PyUnicode_Check(src.ptr()) && !PyBytes_Check(src.ptr());
0095 }
0096
0097 return (PyGen_Check(src.ptr()) != 0) || (PyAnySet_Check(src.ptr()) != 0)
0098 || object_is_instance_with_one_of_tp_names(
0099 src.ptr(), {"dict_keys", "dict_values", "dict_items", "map", "zip"});
0100 }
0101
0102 inline bool object_is_convertible_to_std_set(const handle &src, bool convert) {
0103
0104
0105 return ((PyAnySet_Check(src.ptr()) != 0)
0106 || object_is_instance_with_one_of_tp_names(src.ptr(), {"dict_keys"}))
0107 || (convert && isinstance(src, module_::import("collections.abc").attr("Set")));
0108 }
0109
0110 inline bool object_is_convertible_to_std_map(const handle &src, bool convert) {
0111
0112 if (PyDict_Check(src.ptr())) {
0113 return true;
0114 }
0115
0116
0117
0118
0119 if (PyMapping_Check(src.ptr()) != 0) {
0120 PyObject *items = PyObject_GetAttrString(src.ptr(), "items");
0121 if (items != nullptr) {
0122 bool is_convertible = (PyCallable_Check(items) != 0);
0123 Py_DECREF(items);
0124 if (is_convertible) {
0125 return true;
0126 }
0127 } else {
0128 PyErr_Clear();
0129 }
0130 }
0131
0132 return convert && isinstance(src, module_::import("collections.abc").attr("Mapping"));
0133 }
0134
0135
0136
0137
0138
0139
0140
0141 template <typename T, typename U>
0142 using forwarded_type = conditional_t<std::is_lvalue_reference<T>::value,
0143 remove_reference_t<U> &,
0144 remove_reference_t<U> &&>;
0145
0146
0147
0148 template <typename T, typename U>
0149 constexpr forwarded_type<T, U> forward_like(U &&u) {
0150 return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
0151 }
0152
0153
0154
0155 template <typename C>
0156 using has_reserve_method = std::is_same<decltype(std::declval<C>().reserve(0)), void>;
0157
0158 template <typename Type, typename Key>
0159 struct set_caster {
0160 using type = Type;
0161 using key_conv = make_caster<Key>;
0162
0163 private:
0164 template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0165 void reserve_maybe(const anyset &s, Type *) {
0166 value.reserve(s.size());
0167 }
0168 void reserve_maybe(const anyset &, void *) {}
0169
0170 bool convert_iterable(const iterable &itbl, bool convert) {
0171 for (const auto &it : itbl) {
0172 key_conv conv;
0173 if (!conv.load(it, convert)) {
0174 return false;
0175 }
0176 value.insert(cast_op<Key &&>(std::move(conv)));
0177 }
0178 return true;
0179 }
0180
0181 bool convert_anyset(const anyset &s, bool convert) {
0182 value.clear();
0183 reserve_maybe(s, &value);
0184 return convert_iterable(s, convert);
0185 }
0186
0187 public:
0188 bool load(handle src, bool convert) {
0189 if (!object_is_convertible_to_std_set(src, convert)) {
0190 return false;
0191 }
0192 if (isinstance<anyset>(src)) {
0193 value.clear();
0194 return convert_anyset(reinterpret_borrow<anyset>(src), convert);
0195 }
0196 if (!convert) {
0197 return false;
0198 }
0199 assert(isinstance<iterable>(src));
0200 value.clear();
0201 return convert_iterable(reinterpret_borrow<iterable>(src), convert);
0202 }
0203
0204 template <typename T>
0205 static handle cast(T &&src, return_value_policy policy, handle parent) {
0206 if (!std::is_lvalue_reference<T>::value) {
0207 policy = return_value_policy_override<Key>::policy(policy);
0208 }
0209 pybind11::set s;
0210 for (auto &&value : src) {
0211 auto value_ = reinterpret_steal<object>(
0212 key_conv::cast(detail::forward_like<T>(value), policy, parent));
0213 if (!value_ || !s.add(std::move(value_))) {
0214 return handle();
0215 }
0216 }
0217 return s.release();
0218 }
0219
0220 PYBIND11_TYPE_CASTER(type,
0221 io_name("collections.abc.Set", "set") + const_name("[") + key_conv::name
0222 + const_name("]"));
0223 };
0224
0225 template <typename Type, typename Key, typename Value>
0226 struct map_caster {
0227 using key_conv = make_caster<Key>;
0228 using value_conv = make_caster<Value>;
0229
0230 private:
0231 template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0232 void reserve_maybe(const dict &d, Type *) {
0233 value.reserve(d.size());
0234 }
0235 void reserve_maybe(const dict &, void *) {}
0236
0237 bool convert_elements(const dict &d, bool convert) {
0238 value.clear();
0239 reserve_maybe(d, &value);
0240 for (const auto &it : d) {
0241 key_conv kconv;
0242 value_conv vconv;
0243 if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) {
0244 return false;
0245 }
0246 value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
0247 }
0248 return true;
0249 }
0250
0251 public:
0252 bool load(handle src, bool convert) {
0253 if (!object_is_convertible_to_std_map(src, convert)) {
0254 return false;
0255 }
0256 if (isinstance<dict>(src)) {
0257 return convert_elements(reinterpret_borrow<dict>(src), convert);
0258 }
0259 if (!convert) {
0260 return false;
0261 }
0262 auto items = reinterpret_steal<object>(PyMapping_Items(src.ptr()));
0263 if (!items) {
0264 throw error_already_set();
0265 }
0266 assert(isinstance<iterable>(items));
0267 return convert_elements(dict(reinterpret_borrow<iterable>(items)), convert);
0268 }
0269
0270 template <typename T>
0271 static handle cast(T &&src, return_value_policy policy, handle parent) {
0272 dict d;
0273 return_value_policy policy_key = policy;
0274 return_value_policy policy_value = policy;
0275 if (!std::is_lvalue_reference<T>::value) {
0276 policy_key = return_value_policy_override<Key>::policy(policy_key);
0277 policy_value = return_value_policy_override<Value>::policy(policy_value);
0278 }
0279 for (auto &&kv : src) {
0280 auto key = reinterpret_steal<object>(
0281 key_conv::cast(detail::forward_like<T>(kv.first), policy_key, parent));
0282 auto value = reinterpret_steal<object>(
0283 value_conv::cast(detail::forward_like<T>(kv.second), policy_value, parent));
0284 if (!key || !value) {
0285 return handle();
0286 }
0287 d[std::move(key)] = std::move(value);
0288 }
0289 return d.release();
0290 }
0291
0292 PYBIND11_TYPE_CASTER(Type,
0293 io_name("collections.abc.Mapping", "dict") + const_name("[")
0294 + key_conv::name + const_name(", ") + value_conv::name
0295 + const_name("]"));
0296 };
0297
0298 template <typename Type, typename Value>
0299 struct list_caster {
0300 using value_conv = make_caster<Value>;
0301
0302 bool load(handle src, bool convert) {
0303 if (!object_is_convertible_to_std_vector(src)) {
0304 return false;
0305 }
0306 if (isinstance<sequence>(src)) {
0307 return convert_elements(src, convert);
0308 }
0309 if (!convert) {
0310 return false;
0311 }
0312
0313
0314
0315
0316 assert(isinstance<iterable>(src));
0317 return convert_elements(tuple(reinterpret_borrow<iterable>(src)), convert);
0318 }
0319
0320 private:
0321 template <typename T = Type, enable_if_t<has_reserve_method<T>::value, int> = 0>
0322 void reserve_maybe(const sequence &s, Type *) {
0323 value.reserve(s.size());
0324 }
0325 void reserve_maybe(const sequence &, void *) {}
0326
0327 bool convert_elements(handle seq, bool convert) {
0328 auto s = reinterpret_borrow<sequence>(seq);
0329 value.clear();
0330 reserve_maybe(s, &value);
0331 for (const auto &it : seq) {
0332 value_conv conv;
0333 if (!conv.load(it, convert)) {
0334 return false;
0335 }
0336 value.push_back(cast_op<Value &&>(std::move(conv)));
0337 }
0338 return true;
0339 }
0340
0341 public:
0342 template <typename T>
0343 static handle cast(T &&src, return_value_policy policy, handle parent) {
0344 if (!std::is_lvalue_reference<T>::value) {
0345 policy = return_value_policy_override<Value>::policy(policy);
0346 }
0347 list l(src.size());
0348 ssize_t index = 0;
0349 for (auto &&value : src) {
0350 auto value_ = reinterpret_steal<object>(
0351 value_conv::cast(detail::forward_like<T>(value), policy, parent));
0352 if (!value_) {
0353 return handle();
0354 }
0355 PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr());
0356 }
0357 return l.release();
0358 }
0359
0360 PYBIND11_TYPE_CASTER(Type,
0361 io_name("collections.abc.Sequence", "list") + const_name("[")
0362 + value_conv::name + const_name("]"));
0363 };
0364
0365 template <typename Type, typename Alloc>
0366 struct type_caster<std::vector<Type, Alloc>> : list_caster<std::vector<Type, Alloc>, Type> {};
0367
0368 template <typename Type, typename Alloc>
0369 struct type_caster<std::deque<Type, Alloc>> : list_caster<std::deque<Type, Alloc>, Type> {};
0370
0371 template <typename Type, typename Alloc>
0372 struct type_caster<std::list<Type, Alloc>> : list_caster<std::list<Type, Alloc>, Type> {};
0373
0374 template <typename ArrayType, typename V, size_t... I>
0375 ArrayType vector_to_array_impl(V &&v, index_sequence<I...>) {
0376 return {{std::move(v[I])...}};
0377 }
0378
0379
0380 template <typename ArrayType, size_t N, typename V>
0381 ArrayType vector_to_array(V &&v) {
0382 return vector_to_array_impl<ArrayType, V>(std::forward<V>(v), make_index_sequence<N>{});
0383 }
0384
0385 template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0>
0386 struct array_caster {
0387 using value_conv = make_caster<Value>;
0388
0389 private:
0390 std::unique_ptr<ArrayType> value;
0391
0392 template <bool R = Resizable, enable_if_t<R, int> = 0>
0393 bool convert_elements(handle seq, bool convert) {
0394 auto l = reinterpret_borrow<sequence>(seq);
0395 value.reset(new ArrayType{});
0396
0397
0398
0399
0400 value->resize(l.size());
0401 size_t ctr = 0;
0402 for (const auto &it : l) {
0403 value_conv conv;
0404 if (!conv.load(it, convert)) {
0405 return false;
0406 }
0407 (*value)[ctr++] = cast_op<Value &&>(std::move(conv));
0408 }
0409 return true;
0410 }
0411
0412 template <bool R = Resizable, enable_if_t<!R, int> = 0>
0413 bool convert_elements(handle seq, bool convert) {
0414 auto l = reinterpret_borrow<sequence>(seq);
0415 if (l.size() != Size) {
0416 return false;
0417 }
0418
0419
0420
0421
0422
0423 std::vector<Value> temp;
0424 temp.reserve(l.size());
0425 for (auto it : l) {
0426 value_conv conv;
0427 if (!conv.load(it, convert)) {
0428 return false;
0429 }
0430 temp.emplace_back(cast_op<Value &&>(std::move(conv)));
0431 }
0432 value.reset(new ArrayType(vector_to_array<ArrayType, Size>(std::move(temp))));
0433 return true;
0434 }
0435
0436 public:
0437 bool load(handle src, bool convert) {
0438 if (!object_is_convertible_to_std_vector(src)) {
0439 return false;
0440 }
0441 if (isinstance<sequence>(src)) {
0442 return convert_elements(src, convert);
0443 }
0444 if (!convert) {
0445 return false;
0446 }
0447
0448
0449
0450
0451 assert(isinstance<iterable>(src));
0452 return convert_elements(tuple(reinterpret_borrow<iterable>(src)), convert);
0453 }
0454
0455 template <typename T>
0456 static handle cast(T &&src, return_value_policy policy, handle parent) {
0457 list l(src.size());
0458 ssize_t index = 0;
0459 for (auto &&value : src) {
0460 auto value_ = reinterpret_steal<object>(
0461 value_conv::cast(detail::forward_like<T>(value), policy, parent));
0462 if (!value_) {
0463 return handle();
0464 }
0465 PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr());
0466 }
0467 return l.release();
0468 }
0469
0470
0471
0472 template <typename T_, enable_if_t<std::is_same<ArrayType, remove_cv_t<T_>>::value, int> = 0>
0473 static handle cast(T_ *src, return_value_policy policy, handle parent) {
0474 if (!src) {
0475 return none().release();
0476 }
0477 if (policy == return_value_policy::take_ownership) {
0478 auto h = cast(std::move(*src), policy, parent);
0479 delete src;
0480 return h;
0481 }
0482 return cast(*src, policy, parent);
0483 }
0484
0485
0486 operator ArrayType *() { return &(*value); }
0487
0488 operator ArrayType &() { return *value; }
0489
0490 operator ArrayType &&() && { return std::move(*value); }
0491
0492 template <typename T_>
0493 using cast_op_type = movable_cast_op_type<T_>;
0494
0495 static constexpr auto name
0496 = const_name<Resizable>(const_name(""), const_name("typing.Annotated["))
0497 + io_name("collections.abc.Sequence", "list") + const_name("[") + value_conv::name
0498 + const_name("]")
0499 + const_name<Resizable>(const_name(""),
0500 const_name(", \"FixedSize(") + const_name<Size>()
0501 + const_name(")\"]"));
0502 };
0503
0504 template <typename Type, size_t Size>
0505 struct type_caster<std::array<Type, Size>>
0506 : array_caster<std::array<Type, Size>, Type, false, Size> {};
0507
0508 template <typename Type>
0509 struct type_caster<std::valarray<Type>> : array_caster<std::valarray<Type>, Type, true> {};
0510
0511 template <typename Key, typename Compare, typename Alloc>
0512 struct type_caster<std::set<Key, Compare, Alloc>>
0513 : set_caster<std::set<Key, Compare, Alloc>, Key> {};
0514
0515 template <typename Key, typename Hash, typename Equal, typename Alloc>
0516 struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
0517 : set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> {};
0518
0519 template <typename Key, typename Value, typename Compare, typename Alloc>
0520 struct type_caster<std::map<Key, Value, Compare, Alloc>>
0521 : map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> {};
0522
0523 template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc>
0524 struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
0525 : map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> {};
0526
0527
0528 template <typename Type, typename Value = typename Type::value_type>
0529 struct optional_caster {
0530 using value_conv = make_caster<Value>;
0531
0532 template <typename T>
0533 static handle cast(T &&src, return_value_policy policy, handle parent) {
0534 if (!src) {
0535 return none().release();
0536 }
0537 if (!std::is_lvalue_reference<T>::value) {
0538 policy = return_value_policy_override<Value>::policy(policy);
0539 }
0540
0541 return value_conv::cast(*std::forward<T>(src), policy, parent);
0542 }
0543
0544 bool load(handle src, bool convert) {
0545 if (!src) {
0546 return false;
0547 }
0548 if (src.is_none()) {
0549 return true;
0550 }
0551 value_conv inner_caster;
0552 if (!inner_caster.load(src, convert)) {
0553 return false;
0554 }
0555
0556 value.emplace(cast_op<Value &&>(std::move(inner_caster)));
0557 return true;
0558 }
0559
0560 PYBIND11_TYPE_CASTER(Type, value_conv::name | make_caster<none>::name);
0561 };
0562
0563 #if defined(PYBIND11_HAS_OPTIONAL)
0564 template <typename T>
0565 struct type_caster<std::optional<T>> : public optional_caster<std::optional<T>> {};
0566
0567 template <>
0568 struct type_caster<std::nullopt_t> : public void_caster<std::nullopt_t> {};
0569 #endif
0570
0571 #if defined(PYBIND11_HAS_EXP_OPTIONAL)
0572 template <typename T>
0573 struct type_caster<std::experimental::optional<T>>
0574 : public optional_caster<std::experimental::optional<T>> {};
0575
0576 template <>
0577 struct type_caster<std::experimental::nullopt_t>
0578 : public void_caster<std::experimental::nullopt_t> {};
0579 #endif
0580
0581
0582 struct variant_caster_visitor {
0583 return_value_policy policy;
0584 handle parent;
0585
0586 using result_type = handle;
0587
0588 template <typename T>
0589 result_type operator()(T &&src) const {
0590 return make_caster<T>::cast(std::forward<T>(src), policy, parent);
0591 }
0592 };
0593
0594
0595
0596
0597
0598 template <template <typename...> class Variant>
0599 struct visit_helper {
0600 template <typename... Args>
0601 static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
0602 return visit(std::forward<Args>(args)...);
0603 }
0604 };
0605
0606
0607 template <typename Variant>
0608 struct variant_caster;
0609
0610 template <template <typename...> class V, typename... Ts>
0611 struct variant_caster<V<Ts...>> {
0612 static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
0613
0614 template <typename U, typename... Us>
0615 bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
0616 auto caster = make_caster<U>();
0617 if (caster.load(src, convert)) {
0618 value = cast_op<U>(std::move(caster));
0619 return true;
0620 }
0621 return load_alternative(src, convert, type_list<Us...>{});
0622 }
0623
0624 bool load_alternative(handle, bool, type_list<>) { return false; }
0625
0626 bool load(handle src, bool convert) {
0627
0628
0629
0630
0631 if (convert && load_alternative(src, false, type_list<Ts...>{})) {
0632 return true;
0633 }
0634 return load_alternative(src, convert, type_list<Ts...>{});
0635 }
0636
0637 template <typename Variant>
0638 static handle cast(Variant &&src, return_value_policy policy, handle parent) {
0639 return visit_helper<V>::call(variant_caster_visitor{policy, parent},
0640 std::forward<Variant>(src));
0641 }
0642
0643 using Type = V<Ts...>;
0644 PYBIND11_TYPE_CASTER(Type, ::pybind11::detail::union_concat(make_caster<Ts>::name...));
0645 };
0646
0647 #if defined(PYBIND11_HAS_VARIANT)
0648 template <typename... Ts>
0649 struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> {};
0650
0651 template <>
0652 struct type_caster<std::monostate> : public void_caster<std::monostate> {};
0653 #endif
0654
0655 PYBIND11_NAMESPACE_END(detail)
0656
0657 inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
0658 #ifdef PYBIND11_HAS_STRING_VIEW
0659 os << str(obj).cast<std::string_view>();
0660 #else
0661 os << (std::string) str(obj);
0662 #endif
0663 return os;
0664 }
0665
0666 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)