netgen-mesher 6.2.2504.post11.dev0__cp313-cp313-win_amd64.whl → 6.2.2506.post48.dev0__cp313-cp313-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. netgen/__init__.pyi +3 -3
  2. netgen/cmake/NetgenConfig.cmake +10 -9
  3. netgen/config/__init__.pyi +8 -8
  4. netgen/config/config.py +7 -7
  5. netgen/config/config.pyi +8 -8
  6. netgen/include/core/archive.hpp +18 -3
  7. netgen/include/core/array.hpp +20 -4
  8. netgen/include/core/autodiff.hpp +9 -11
  9. netgen/include/core/autodiffdiff.hpp +0 -2
  10. netgen/include/core/bitarray.hpp +1 -1
  11. netgen/include/core/flags.hpp +1 -1
  12. netgen/include/core/hashtable.hpp +1 -1
  13. netgen/include/core/memtracer.hpp +7 -7
  14. netgen/include/core/ngcore.hpp +5 -0
  15. netgen/include/core/ngcore_api.hpp +11 -0
  16. netgen/include/core/paje_trace.hpp +9 -8
  17. netgen/include/core/profiler.hpp +5 -5
  18. netgen/include/core/register_archive.hpp +8 -0
  19. netgen/include/core/simd.hpp +69 -1
  20. netgen/include/core/simd_arm64.hpp +205 -1
  21. netgen/include/core/simd_avx.hpp +72 -4
  22. netgen/include/core/simd_avx512.hpp +9 -0
  23. netgen/include/core/simd_generic.hpp +274 -8
  24. netgen/include/core/simd_math.hpp +178 -0
  25. netgen/include/core/simd_sse.hpp +11 -1
  26. netgen/include/core/statushandler.hpp +37 -0
  27. netgen/include/core/table.hpp +3 -2
  28. netgen/include/core/taskmanager.hpp +34 -1
  29. netgen/include/core/utils.hpp +3 -8
  30. netgen/include/include/netgen_version.hpp +4 -4
  31. netgen/include/meshing/basegeom.hpp +1 -4
  32. netgen/include/meshing/global.hpp +0 -17
  33. netgen/include/meshing/hpref_tet.hpp +41 -0
  34. netgen/include/meshing/hprefinement.hpp +2 -0
  35. netgen/include/meshing/meshtype.hpp +2 -1
  36. netgen/include/meshing/msghandler.hpp +9 -6
  37. netgen/include/meshing/topology.hpp +2 -2
  38. netgen/include/nginterface.h +3 -2
  39. netgen/include/occ/occ_utils.hpp +26 -0
  40. netgen/include/occ/occgeom.hpp +8 -0
  41. netgen/include/pybind11/attr.h +40 -8
  42. netgen/include/pybind11/buffer_info.h +14 -14
  43. netgen/include/pybind11/cast.h +553 -29
  44. netgen/include/pybind11/chrono.h +4 -1
  45. netgen/include/pybind11/conduit/README.txt +15 -0
  46. netgen/include/pybind11/conduit/pybind11_conduit_v1.h +116 -0
  47. netgen/include/pybind11/conduit/pybind11_platform_abi_id.h +87 -0
  48. netgen/include/pybind11/conduit/wrap_include_python_h.h +72 -0
  49. netgen/include/pybind11/critical_section.h +56 -0
  50. netgen/include/pybind11/detail/class.h +172 -97
  51. netgen/include/pybind11/detail/common.h +270 -189
  52. netgen/include/pybind11/detail/cpp_conduit.h +75 -0
  53. netgen/include/pybind11/detail/descr.h +55 -0
  54. netgen/include/pybind11/detail/dynamic_raw_ptr_cast_if_possible.h +39 -0
  55. netgen/include/pybind11/detail/exception_translation.h +71 -0
  56. netgen/include/pybind11/detail/function_record_pyobject.h +191 -0
  57. netgen/include/pybind11/detail/init.h +113 -9
  58. netgen/include/pybind11/detail/internals.h +479 -344
  59. netgen/include/pybind11/detail/native_enum_data.h +209 -0
  60. netgen/include/pybind11/detail/pybind11_namespace_macros.h +82 -0
  61. netgen/include/pybind11/detail/struct_smart_holder.h +378 -0
  62. netgen/include/pybind11/detail/type_caster_base.h +506 -133
  63. netgen/include/pybind11/detail/using_smart_holder.h +22 -0
  64. netgen/include/pybind11/detail/value_and_holder.h +90 -0
  65. netgen/include/pybind11/eigen/matrix.h +19 -10
  66. netgen/include/pybind11/eigen/tensor.h +15 -11
  67. netgen/include/pybind11/embed.h +50 -46
  68. netgen/include/pybind11/eval.h +11 -6
  69. netgen/include/pybind11/functional.h +58 -49
  70. netgen/include/pybind11/gil.h +34 -82
  71. netgen/include/pybind11/gil_safe_call_once.h +12 -1
  72. netgen/include/pybind11/gil_simple.h +37 -0
  73. netgen/include/pybind11/native_enum.h +67 -0
  74. netgen/include/pybind11/numpy.h +272 -93
  75. netgen/include/pybind11/pybind11.h +947 -265
  76. netgen/include/pybind11/pytypes.h +127 -21
  77. netgen/include/pybind11/stl/filesystem.h +23 -25
  78. netgen/include/pybind11/stl.h +277 -59
  79. netgen/include/pybind11/stl_bind.h +42 -7
  80. netgen/include/pybind11/subinterpreter.h +299 -0
  81. netgen/include/pybind11/trampoline_self_life_support.h +65 -0
  82. netgen/include/pybind11/typing.h +177 -4
  83. netgen/include/pybind11/warnings.h +75 -0
  84. netgen/include/visualization/mvdraw.hpp +48 -12
  85. netgen/include/visualization/vssolution.hpp +3 -1
  86. netgen/lib/libnggui.lib +0 -0
  87. netgen/lib/ngcore.lib +0 -0
  88. netgen/lib/nglib.lib +0 -0
  89. netgen/libnggui.dll +0 -0
  90. netgen/libngguipy.pyd +0 -0
  91. netgen/libngpy/_NgOCC.pyi +224 -139
  92. netgen/libngpy/_csg.pyi +26 -26
  93. netgen/libngpy/_geom2d.pyi +34 -25
  94. netgen/libngpy/_meshing.pyi +262 -111
  95. netgen/libngpy/_stl.pyi +3 -4
  96. netgen/libngpy.pyd +0 -0
  97. netgen/ngcore.dll +0 -0
  98. netgen/nglib.dll +0 -0
  99. netgen/read_gmsh.py +41 -0
  100. netgen/togl.dll +0 -0
  101. netgen/version.py +1 -1
  102. netgen/webgui.py +38 -2
  103. {netgen_mesher-6.2.2504.post11.dev0.dist-info → netgen_mesher-6.2.2506.post48.dev0.dist-info}/METADATA +2 -1
  104. {netgen_mesher-6.2.2504.post11.dev0.dist-info → netgen_mesher-6.2.2506.post48.dev0.dist-info}/RECORD +153 -132
  105. pyngcore/pyngcore.cp313-win_amd64.pyd +0 -0
  106. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/boundarycondition.geo +0 -0
  107. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/boxcyl.geo +0 -0
  108. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/circle_on_cube.geo +0 -0
  109. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cone.geo +0 -0
  110. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cube.geo +0 -0
  111. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cubeandring.geo +0 -0
  112. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cubeandspheres.geo +0 -0
  113. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cubemcyl.geo +0 -0
  114. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cubemsphere.geo +0 -0
  115. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cylinder.geo +0 -0
  116. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/cylsphere.geo +0 -0
  117. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/doc/ng4.pdf +0 -0
  118. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/ellipsoid.geo +0 -0
  119. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/ellipticcyl.geo +0 -0
  120. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/extrusion.geo +0 -0
  121. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/fichera.geo +0 -0
  122. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/frame.step +0 -0
  123. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/hinge.stl +0 -0
  124. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/lshape3d.geo +0 -0
  125. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/manyholes.geo +0 -0
  126. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/manyholes2.geo +0 -0
  127. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/matrix.geo +0 -0
  128. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/ortho.geo +0 -0
  129. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/part1.stl +0 -0
  130. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/period.geo +0 -0
  131. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/py_tutorials/exportNeutral.py +0 -0
  132. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/py_tutorials/mesh.py +0 -0
  133. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/py_tutorials/shaft.geo +0 -0
  134. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/revolution.geo +0 -0
  135. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/screw.step +0 -0
  136. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/sculpture.geo +0 -0
  137. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/shaft.geo +0 -0
  138. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/shell.geo +0 -0
  139. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/sphere.geo +0 -0
  140. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/sphereincube.geo +0 -0
  141. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/square.in2d +0 -0
  142. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/squarecircle.in2d +0 -0
  143. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/squarehole.in2d +0 -0
  144. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/torus.geo +0 -0
  145. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/trafo.geo +0 -0
  146. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/twobricks.geo +0 -0
  147. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/twocubes.geo +0 -0
  148. {netgen_mesher-6.2.2504.post11.dev0.data → netgen_mesher-6.2.2506.post48.dev0.data}/data/share/netgen/twocyl.geo +0 -0
  149. {netgen_mesher-6.2.2504.post11.dev0.dist-info → netgen_mesher-6.2.2506.post48.dev0.dist-info}/AUTHORS +0 -0
  150. {netgen_mesher-6.2.2504.post11.dev0.dist-info → netgen_mesher-6.2.2506.post48.dev0.dist-info}/LICENSE +0 -0
  151. {netgen_mesher-6.2.2504.post11.dev0.dist-info → netgen_mesher-6.2.2506.post48.dev0.dist-info}/WHEEL +0 -0
  152. {netgen_mesher-6.2.2504.post11.dev0.dist-info → netgen_mesher-6.2.2506.post48.dev0.dist-info}/entry_points.txt +0 -0
  153. {netgen_mesher-6.2.2504.post11.dev0.dist-info → netgen_mesher-6.2.2506.post48.dev0.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,7 @@
12
12
 
13
13
  #include "detail/common.h"
14
14
  #include "detail/descr.h"
15
+ #include "detail/native_enum_data.h"
15
16
  #include "detail/type_caster_base.h"
16
17
  #include "detail/typeid.h"
17
18
  #include "pytypes.h"
@@ -53,6 +54,109 @@ cast_op(make_caster<T> &&caster) {
53
54
  return std::move(caster).operator result_t();
54
55
  }
55
56
 
57
+ template <typename EnumType>
58
+ class type_caster_enum_type {
59
+ private:
60
+ using Underlying = typename std::underlying_type<EnumType>::type;
61
+
62
+ public:
63
+ static constexpr auto name = const_name<EnumType>();
64
+
65
+ template <typename SrcType>
66
+ static handle cast(SrcType &&src, return_value_policy, handle parent) {
67
+ handle native_enum
68
+ = global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
69
+ if (native_enum) {
70
+ return native_enum(static_cast<Underlying>(src)).release();
71
+ }
72
+ return type_caster_base<EnumType>::cast(
73
+ std::forward<SrcType>(src),
74
+ // Fixes https://github.com/pybind/pybind11/pull/3643#issuecomment-1022987818:
75
+ return_value_policy::copy,
76
+ parent);
77
+ }
78
+
79
+ template <typename SrcType>
80
+ static handle cast(SrcType *src, return_value_policy policy, handle parent) {
81
+ return cast(*src, policy, parent);
82
+ }
83
+
84
+ bool load(handle src, bool convert) {
85
+ handle native_enum
86
+ = global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
87
+ if (native_enum) {
88
+ if (!isinstance(src, native_enum)) {
89
+ return false;
90
+ }
91
+ type_caster<Underlying> underlying_caster;
92
+ if (!underlying_caster.load(src.attr("value"), convert)) {
93
+ pybind11_fail("native_enum internal consistency failure.");
94
+ }
95
+ value = static_cast<EnumType>(static_cast<Underlying>(underlying_caster));
96
+ return true;
97
+ }
98
+ if (!pybind11_enum_) {
99
+ pybind11_enum_.reset(new type_caster_base<EnumType>());
100
+ }
101
+ return pybind11_enum_->load(src, convert);
102
+ }
103
+
104
+ template <typename T>
105
+ using cast_op_type = detail::cast_op_type<T>;
106
+
107
+ // NOLINTNEXTLINE(google-explicit-constructor)
108
+ operator EnumType *() {
109
+ if (!pybind11_enum_) {
110
+ return &value;
111
+ }
112
+ return pybind11_enum_->operator EnumType *();
113
+ }
114
+
115
+ // NOLINTNEXTLINE(google-explicit-constructor)
116
+ operator EnumType &() {
117
+ if (!pybind11_enum_) {
118
+ return value;
119
+ }
120
+ return pybind11_enum_->operator EnumType &();
121
+ }
122
+
123
+ private:
124
+ std::unique_ptr<type_caster_base<EnumType>> pybind11_enum_;
125
+ EnumType value;
126
+ };
127
+
128
+ template <typename EnumType, typename SFINAE = void>
129
+ struct type_caster_enum_type_enabled : std::true_type {};
130
+
131
+ template <typename T>
132
+ struct type_uses_type_caster_enum_type {
133
+ static constexpr bool value
134
+ = std::is_enum<T>::value && type_caster_enum_type_enabled<T>::value;
135
+ };
136
+
137
+ template <typename EnumType>
138
+ class type_caster<EnumType, detail::enable_if_t<type_uses_type_caster_enum_type<EnumType>::value>>
139
+ : public type_caster_enum_type<EnumType> {};
140
+
141
+ template <typename T, detail::enable_if_t<std::is_enum<T>::value, int> = 0>
142
+ bool isinstance_native_enum_impl(handle obj, const std::type_info &tp) {
143
+ handle native_enum = global_internals_native_enum_type_map_get_item(tp);
144
+ if (!native_enum) {
145
+ return false;
146
+ }
147
+ return isinstance(obj, native_enum);
148
+ }
149
+
150
+ template <typename T, detail::enable_if_t<!std::is_enum<T>::value, int> = 0>
151
+ bool isinstance_native_enum_impl(handle, const std::type_info &) {
152
+ return false;
153
+ }
154
+
155
+ template <typename T>
156
+ bool isinstance_native_enum(handle obj, const std::type_info &tp) {
157
+ return isinstance_native_enum_impl<intrinsic_t<T>>(obj, tp);
158
+ }
159
+
56
160
  template <typename type>
57
161
  class type_caster<std::reference_wrapper<type>> {
58
162
  private:
@@ -158,7 +262,7 @@ public:
158
262
  } else {
159
263
  handle src_or_index = src;
160
264
  // PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
161
- #if PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION)
265
+ #if defined(PYPY_VERSION)
162
266
  object index;
163
267
  if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
164
268
  index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
@@ -241,7 +345,9 @@ public:
241
345
  return PyLong_FromUnsignedLongLong((unsigned long long) src);
242
346
  }
243
347
 
244
- PYBIND11_TYPE_CASTER(T, const_name<std::is_integral<T>::value>("int", "float"));
348
+ PYBIND11_TYPE_CASTER(T,
349
+ io_name<std::is_integral<T>::value>(
350
+ "typing.SupportsInt", "int", "typing.SupportsFloat", "float"));
245
351
  };
246
352
 
247
353
  template <typename T>
@@ -303,7 +409,7 @@ public:
303
409
  template <typename T>
304
410
  using cast_op_type = void *&;
305
411
  explicit operator void *&() { return value; }
306
- static constexpr auto name = const_name("capsule");
412
+ static constexpr auto name = const_name(PYBIND11_CAPSULE_TYPE_TYPE_HINT);
307
413
 
308
414
  private:
309
415
  void *value = nullptr;
@@ -343,7 +449,7 @@ public:
343
449
  #else
344
450
  // Alternate approach for CPython: this does the same as the above, but optimized
345
451
  // using the CPython API so as to avoid an unneeded attribute lookup.
346
- else if (auto *tp_as_number = src.ptr()->ob_type->tp_as_number) {
452
+ else if (auto *tp_as_number = Py_TYPE(src.ptr())->tp_as_number) {
347
453
  if (PYBIND11_NB_BOOL(tp_as_number)) {
348
454
  res = (*PYBIND11_NB_BOOL(tp_as_number))(src.ptr());
349
455
  }
@@ -716,7 +822,9 @@ protected:
716
822
  cast_impl(T &&src, return_value_policy policy, handle parent, index_sequence<Is...>) {
717
823
  PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(src, policy, parent);
718
824
  PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(policy, parent);
825
+
719
826
  std::array<object, size> entries{{reinterpret_steal<object>(
827
+ // NOLINTNEXTLINE(bugprone-use-after-move)
720
828
  make_caster<Ts>::cast(std::get<Is>(std::forward<T>(src)), policy, parent))...}};
721
829
  for (const auto &entry : entries) {
722
830
  if (!entry) {
@@ -740,6 +848,13 @@ class type_caster<std::pair<T1, T2>> : public tuple_caster<std::pair, T1, T2> {}
740
848
  template <typename... Ts>
741
849
  class type_caster<std::tuple<Ts...>> : public tuple_caster<std::tuple, Ts...> {};
742
850
 
851
+ template <>
852
+ class type_caster<std::tuple<>> : public tuple_caster<std::tuple> {
853
+ public:
854
+ // PEP 484 specifies this syntax for an empty tuple
855
+ static constexpr auto name = const_name("tuple[()]");
856
+ };
857
+
743
858
  /// Helper class which abstracts away certain actions. Users can provide specializations for
744
859
  /// custom holders, but it's only necessary if the type has a non-standard interface.
745
860
  template <typename T>
@@ -747,6 +862,7 @@ struct holder_helper {
747
862
  static auto get(const T &p) -> decltype(p.get()) { return p.get(); }
748
863
  };
749
864
 
865
+ // SMART_HOLDER_BAKEIN_FOLLOW_ON: Rewrite comment, with reference to shared_ptr specialization.
750
866
  /// Type caster for holder types like std::shared_ptr, etc.
751
867
  /// The SFINAE hook is provided to help work around the current lack of support
752
868
  /// for smart-pointer interoperability. Please consider it an implementation
@@ -782,16 +898,19 @@ public:
782
898
  protected:
783
899
  friend class type_caster_generic;
784
900
  void check_holder_compat() {
785
- if (typeinfo->default_holder) {
901
+ // SMART_HOLDER_BAKEIN_FOLLOW_ON: Refine holder compatibility checks.
902
+ bool inst_has_unique_ptr_holder
903
+ = (typeinfo->holder_enum_v == holder_enum_t::std_unique_ptr);
904
+ if (inst_has_unique_ptr_holder) {
786
905
  throw cast_error("Unable to load a custom holder type from a default-holder instance");
787
906
  }
788
907
  }
789
908
 
790
- bool load_value(value_and_holder &&v_h) {
909
+ void load_value(value_and_holder &&v_h) {
791
910
  if (v_h.holder_constructed()) {
792
911
  value = v_h.value_ptr();
793
912
  holder = v_h.template holder<holder_type>();
794
- return true;
913
+ return;
795
914
  }
796
915
  throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
797
916
  #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
@@ -828,10 +947,205 @@ protected:
828
947
  holder_type holder;
829
948
  };
830
949
 
950
+ template <typename, typename SFINAE = void>
951
+ struct copyable_holder_caster_shared_ptr_with_smart_holder_support_enabled : std::true_type {};
952
+
953
+ // SMART_HOLDER_BAKEIN_FOLLOW_ON: Refactor copyable_holder_caster to reduce code duplication.
954
+ template <typename type>
955
+ struct copyable_holder_caster<
956
+ type,
957
+ std::shared_ptr<type>,
958
+ enable_if_t<copyable_holder_caster_shared_ptr_with_smart_holder_support_enabled<type>::value>>
959
+ : public type_caster_base<type> {
960
+ public:
961
+ using base = type_caster_base<type>;
962
+ static_assert(std::is_base_of<base, type_caster<type>>::value,
963
+ "Holder classes are only supported for custom types");
964
+ using base::base;
965
+ using base::cast;
966
+ using base::typeinfo;
967
+ using base::value;
968
+
969
+ bool load(handle src, bool convert) {
970
+ if (base::template load_impl<copyable_holder_caster<type, std::shared_ptr<type>>>(
971
+ src, convert)) {
972
+ sh_load_helper.maybe_set_python_instance_is_alias(src);
973
+ return true;
974
+ }
975
+ return false;
976
+ }
977
+
978
+ explicit operator std::shared_ptr<type> *() {
979
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
980
+ pybind11_fail("Passing `std::shared_ptr<T> *` from Python to C++ is not supported "
981
+ "(inherently unsafe).");
982
+ }
983
+ return std::addressof(shared_ptr_storage);
984
+ }
985
+
986
+ explicit operator std::shared_ptr<type> &() {
987
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
988
+ shared_ptr_storage = sh_load_helper.load_as_shared_ptr(typeinfo, value);
989
+ }
990
+ return shared_ptr_storage;
991
+ }
992
+
993
+ std::weak_ptr<type> potentially_slicing_weak_ptr() {
994
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
995
+ // Reusing shared_ptr code to minimize code complexity.
996
+ shared_ptr_storage
997
+ = sh_load_helper.load_as_shared_ptr(typeinfo,
998
+ value,
999
+ /*responsible_parent=*/nullptr,
1000
+ /*force_potentially_slicing_shared_ptr=*/true);
1001
+ }
1002
+ return shared_ptr_storage;
1003
+ }
1004
+
1005
+ static handle
1006
+ cast(const std::shared_ptr<type> &src, return_value_policy policy, handle parent) {
1007
+ const auto *ptr = src.get();
1008
+ auto st = type_caster_base<type>::src_and_type(ptr);
1009
+ if (st.second == nullptr) {
1010
+ return handle(); // no type info: error will be set already
1011
+ }
1012
+ if (st.second->holder_enum_v == detail::holder_enum_t::smart_holder) {
1013
+ return smart_holder_type_caster_support::smart_holder_from_shared_ptr(
1014
+ src, policy, parent, st);
1015
+ }
1016
+ return type_caster_base<type>::cast_holder(ptr, &src);
1017
+ }
1018
+
1019
+ // This function will succeed even if the `responsible_parent` does not own the
1020
+ // wrapped C++ object directly.
1021
+ // It is the responsibility of the caller to ensure that the `responsible_parent`
1022
+ // has a `keep_alive` relationship with the owner of the wrapped C++ object, or
1023
+ // that the wrapped C++ object lives for the duration of the process.
1024
+ static std::shared_ptr<type> shared_ptr_with_responsible_parent(handle responsible_parent) {
1025
+ copyable_holder_caster loader;
1026
+ loader.load(responsible_parent, /*convert=*/false);
1027
+ assert(loader.typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder);
1028
+ return loader.sh_load_helper.load_as_shared_ptr(
1029
+ loader.typeinfo, loader.value, responsible_parent);
1030
+ }
1031
+
1032
+ protected:
1033
+ friend class type_caster_generic;
1034
+ void check_holder_compat() {
1035
+ // SMART_HOLDER_BAKEIN_FOLLOW_ON: Refine holder compatibility checks.
1036
+ bool inst_has_unique_ptr_holder
1037
+ = (typeinfo->holder_enum_v == holder_enum_t::std_unique_ptr);
1038
+ if (inst_has_unique_ptr_holder) {
1039
+ throw cast_error("Unable to load a custom holder type from a default-holder instance");
1040
+ }
1041
+ }
1042
+
1043
+ void load_value(value_and_holder &&v_h) {
1044
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1045
+ sh_load_helper.loaded_v_h = v_h;
1046
+ sh_load_helper.was_populated = true;
1047
+ value = sh_load_helper.get_void_ptr_or_nullptr();
1048
+ return;
1049
+ }
1050
+ if (v_h.holder_constructed()) {
1051
+ value = v_h.value_ptr();
1052
+ shared_ptr_storage = v_h.template holder<std::shared_ptr<type>>();
1053
+ return;
1054
+ }
1055
+ throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) "
1056
+ #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
1057
+ "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for "
1058
+ "type information)");
1059
+ #else
1060
+ "of type '"
1061
+ + type_id<std::shared_ptr<type>>() + "''");
1062
+ #endif
1063
+ }
1064
+
1065
+ template <typename T = std::shared_ptr<type>,
1066
+ detail::enable_if_t<!std::is_constructible<T, const T &, type *>::value, int> = 0>
1067
+ bool try_implicit_casts(handle, bool) {
1068
+ return false;
1069
+ }
1070
+
1071
+ template <typename T = std::shared_ptr<type>,
1072
+ detail::enable_if_t<std::is_constructible<T, const T &, type *>::value, int> = 0>
1073
+ bool try_implicit_casts(handle src, bool convert) {
1074
+ for (auto &cast : typeinfo->implicit_casts) {
1075
+ copyable_holder_caster sub_caster(*cast.first);
1076
+ if (sub_caster.load(src, convert)) {
1077
+ value = cast.second(sub_caster.value);
1078
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1079
+ sh_load_helper.loaded_v_h = sub_caster.sh_load_helper.loaded_v_h;
1080
+ } else {
1081
+ shared_ptr_storage
1082
+ = std::shared_ptr<type>(sub_caster.shared_ptr_storage, (type *) value);
1083
+ }
1084
+ return true;
1085
+ }
1086
+ }
1087
+ return false;
1088
+ }
1089
+
1090
+ static bool try_direct_conversions(handle) { return false; }
1091
+
1092
+ smart_holder_type_caster_support::load_helper<remove_cv_t<type>> sh_load_helper; // Const2Mutbl
1093
+ std::shared_ptr<type> shared_ptr_storage;
1094
+ };
1095
+
831
1096
  /// Specialize for the common std::shared_ptr, so users don't need to
832
1097
  template <typename T>
833
1098
  class type_caster<std::shared_ptr<T>> : public copyable_holder_caster<T, std::shared_ptr<T>> {};
834
1099
 
1100
+ PYBIND11_NAMESPACE_END(detail)
1101
+
1102
+ /// Return a std::shared_ptr with the SAME CONTROL BLOCK as the std::shared_ptr owned by the
1103
+ /// class_ holder. For class_-wrapped types with trampolines, the returned std::shared_ptr
1104
+ /// does NOT keep any derived Python objects alive (see issue #1333).
1105
+ ///
1106
+ /// For class_-wrapped types using std::shared_ptr as the holder, the following expressions
1107
+ /// produce equivalent results (see tests/test_potentially_slicing_weak_ptr.cpp,py):
1108
+ ///
1109
+ /// - obj.cast<std::shared_ptr<T>>()
1110
+ /// - py::potentially_slicing_weak_ptr<T>(obj).lock()
1111
+ ///
1112
+ /// For class_-wrapped types with trampolines and using py::smart_holder, obj.cast<>()
1113
+ /// produces a std::shared_ptr that keeps any derived Python objects alive for its own lifetime,
1114
+ /// but this is achieved by introducing a std::shared_ptr control block that is independent of
1115
+ /// the one owned by the py::smart_holder. This can lead to surprising std::weak_ptr behavior
1116
+ /// (see issue #5623). An easy solution is to use py::potentially_slicing_weak_ptr<>(obj),
1117
+ /// as exercised in tests/test_potentially_slicing_weak_ptr.cpp,py (look for
1118
+ /// "set_wp_potentially_slicing"). Note, however, that this reintroduces the inheritance
1119
+ /// slicing issue (see issue #1333). The ideal — but usually more involved — solution is to use
1120
+ /// a Python weakref to the derived Python object, instead of a C++ base-class std::weak_ptr.
1121
+ ///
1122
+ /// It is not possible (at least no known approach exists at the time of this writing) to
1123
+ /// simultaneously achieve both desirable properties:
1124
+ ///
1125
+ /// - the same std::shared_ptr control block as the class_ holder
1126
+ /// - automatic lifetime extension of any derived Python objects
1127
+ ///
1128
+ /// The reason is that this would introduce a reference cycle that cannot be garbage collected:
1129
+ ///
1130
+ /// - the derived Python object owns the class_ holder
1131
+ /// - the class_ holder owns the std::shared_ptr
1132
+ /// - the std::shared_ptr would own a reference to the derived Python object,
1133
+ /// completing the cycle
1134
+ template <typename T>
1135
+ std::weak_ptr<T> potentially_slicing_weak_ptr(handle obj) {
1136
+ detail::make_caster<std::shared_ptr<T>> caster;
1137
+ if (caster.load(obj, /*convert=*/true)) {
1138
+ return caster.potentially_slicing_weak_ptr();
1139
+ }
1140
+ const char *obj_type_name = detail::obj_class_name(obj.ptr());
1141
+ throw type_error("\"" + std::string(obj_type_name)
1142
+ + "\" object is not convertible to std::weak_ptr<T> (with T = " + type_id<T>()
1143
+ + ")");
1144
+ }
1145
+
1146
+ PYBIND11_NAMESPACE_BEGIN(detail)
1147
+
1148
+ // SMART_HOLDER_BAKEIN_FOLLOW_ON: Rewrite comment, with reference to unique_ptr specialization.
835
1149
  /// Type caster for holder types like std::unique_ptr.
836
1150
  /// Please consider the SFINAE hook an implementation detail, as explained
837
1151
  /// in the comment for the copyable_holder_caster.
@@ -847,6 +1161,143 @@ struct move_only_holder_caster {
847
1161
  static constexpr auto name = type_caster_base<type>::name;
848
1162
  };
849
1163
 
1164
+ template <typename, typename SFINAE = void>
1165
+ struct move_only_holder_caster_unique_ptr_with_smart_holder_support_enabled : std::true_type {};
1166
+
1167
+ // SMART_HOLDER_BAKEIN_FOLLOW_ON: Refactor move_only_holder_caster to reduce code duplication.
1168
+ template <typename type, typename deleter>
1169
+ struct move_only_holder_caster<
1170
+ type,
1171
+ std::unique_ptr<type, deleter>,
1172
+ enable_if_t<move_only_holder_caster_unique_ptr_with_smart_holder_support_enabled<type>::value>>
1173
+ : public type_caster_base<type> {
1174
+ public:
1175
+ using base = type_caster_base<type>;
1176
+ static_assert(std::is_base_of<base, type_caster<type>>::value,
1177
+ "Holder classes are only supported for custom types");
1178
+ using base::base;
1179
+ using base::cast;
1180
+ using base::typeinfo;
1181
+ using base::value;
1182
+
1183
+ static handle
1184
+ cast(std::unique_ptr<type, deleter> &&src, return_value_policy policy, handle parent) {
1185
+ auto *ptr = src.get();
1186
+ auto st = type_caster_base<type>::src_and_type(ptr);
1187
+ if (st.second == nullptr) {
1188
+ return handle(); // no type info: error will be set already
1189
+ }
1190
+ if (st.second->holder_enum_v == detail::holder_enum_t::smart_holder) {
1191
+ return smart_holder_type_caster_support::smart_holder_from_unique_ptr(
1192
+ std::move(src), policy, parent, st);
1193
+ }
1194
+ return type_caster_generic::cast(st.first,
1195
+ return_value_policy::take_ownership,
1196
+ {},
1197
+ st.second,
1198
+ nullptr,
1199
+ nullptr,
1200
+ std::addressof(src));
1201
+ }
1202
+
1203
+ static handle
1204
+ cast(const std::unique_ptr<type, deleter> &src, return_value_policy policy, handle parent) {
1205
+ if (!src) {
1206
+ return none().release();
1207
+ }
1208
+ if (policy == return_value_policy::automatic) {
1209
+ policy = return_value_policy::reference_internal;
1210
+ }
1211
+ if (policy != return_value_policy::reference_internal) {
1212
+ throw cast_error("Invalid return_value_policy for const unique_ptr&");
1213
+ }
1214
+ return type_caster_base<type>::cast(src.get(), policy, parent);
1215
+ }
1216
+
1217
+ bool load(handle src, bool convert) {
1218
+ if (base::template load_impl<
1219
+ move_only_holder_caster<type, std::unique_ptr<type, deleter>>>(src, convert)) {
1220
+ sh_load_helper.maybe_set_python_instance_is_alias(src);
1221
+ return true;
1222
+ }
1223
+ return false;
1224
+ }
1225
+
1226
+ void load_value(value_and_holder &&v_h) {
1227
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1228
+ sh_load_helper.loaded_v_h = v_h;
1229
+ sh_load_helper.loaded_v_h.type = typeinfo;
1230
+ sh_load_helper.was_populated = true;
1231
+ value = sh_load_helper.get_void_ptr_or_nullptr();
1232
+ return;
1233
+ }
1234
+ pybind11_fail("Passing `std::unique_ptr<T>` from Python to C++ requires `py::class_<T, "
1235
+ "py::smart_holder>` (with T = "
1236
+ + clean_type_id(typeinfo->cpptype->name()) + ")");
1237
+ }
1238
+
1239
+ template <typename T_>
1240
+ using cast_op_type
1241
+ = conditional_t<std::is_same<typename std::remove_volatile<T_>::type,
1242
+ const std::unique_ptr<type, deleter> &>::value
1243
+ || std::is_same<typename std::remove_volatile<T_>::type,
1244
+ const std::unique_ptr<const type, deleter> &>::value,
1245
+ const std::unique_ptr<type, deleter> &,
1246
+ std::unique_ptr<type, deleter>>;
1247
+
1248
+ explicit operator std::unique_ptr<type, deleter>() {
1249
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1250
+ return sh_load_helper.template load_as_unique_ptr<deleter>(typeinfo, value);
1251
+ }
1252
+ pybind11_fail("Expected to be UNREACHABLE: " __FILE__ ":" PYBIND11_TOSTRING(__LINE__));
1253
+ }
1254
+
1255
+ explicit operator const std::unique_ptr<type, deleter> &() {
1256
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1257
+ // Get shared_ptr to ensure that the Python object is not disowned elsewhere.
1258
+ shared_ptr_storage = sh_load_helper.load_as_shared_ptr(typeinfo, value);
1259
+ // Build a temporary unique_ptr that is meant to never expire.
1260
+ unique_ptr_storage = std::shared_ptr<std::unique_ptr<type, deleter>>(
1261
+ new std::unique_ptr<type, deleter>{
1262
+ sh_load_helper.template load_as_const_unique_ptr<deleter>(
1263
+ typeinfo, shared_ptr_storage.get())},
1264
+ [](std::unique_ptr<type, deleter> *ptr) {
1265
+ if (!ptr) {
1266
+ pybind11_fail("FATAL: `const std::unique_ptr<T, D> &` was disowned "
1267
+ "(EXPECT UNDEFINED BEHAVIOR).");
1268
+ }
1269
+ (void) ptr->release();
1270
+ delete ptr;
1271
+ });
1272
+ return *unique_ptr_storage;
1273
+ }
1274
+ pybind11_fail("Expected to be UNREACHABLE: " __FILE__ ":" PYBIND11_TOSTRING(__LINE__));
1275
+ }
1276
+
1277
+ bool try_implicit_casts(handle src, bool convert) {
1278
+ for (auto &cast : typeinfo->implicit_casts) {
1279
+ move_only_holder_caster sub_caster(*cast.first);
1280
+ if (sub_caster.load(src, convert)) {
1281
+ value = cast.second(sub_caster.value);
1282
+ if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1283
+ sh_load_helper.loaded_v_h = sub_caster.sh_load_helper.loaded_v_h;
1284
+ } else {
1285
+ pybind11_fail("Expected to be UNREACHABLE: " __FILE__
1286
+ ":" PYBIND11_TOSTRING(__LINE__));
1287
+ }
1288
+ return true;
1289
+ }
1290
+ }
1291
+ return false;
1292
+ }
1293
+
1294
+ static bool try_direct_conversions(handle) { return false; }
1295
+
1296
+ smart_holder_type_caster_support::load_helper<remove_cv_t<type>> sh_load_helper; // Const2Mutbl
1297
+ std::shared_ptr<type> shared_ptr_storage; // Serves as a pseudo lock.
1298
+ std::shared_ptr<std::unique_ptr<type, deleter>> unique_ptr_storage;
1299
+ };
1300
+
850
1301
  template <typename type, typename deleter>
851
1302
  class type_caster<std::unique_ptr<type, deleter>>
852
1303
  : public move_only_holder_caster<type, std::unique_ptr<type, deleter>> {};
@@ -856,18 +1307,20 @@ using type_caster_holder = conditional_t<is_copy_constructible<holder_type>::val
856
1307
  copyable_holder_caster<type, holder_type>,
857
1308
  move_only_holder_caster<type, holder_type>>;
858
1309
 
859
- template <typename T, bool Value = false>
860
- struct always_construct_holder {
1310
+ template <bool Value = false>
1311
+ struct always_construct_holder_value {
861
1312
  static constexpr bool value = Value;
862
1313
  };
863
1314
 
1315
+ template <typename T, bool Value = false>
1316
+ struct always_construct_holder : always_construct_holder_value<Value> {};
1317
+
864
1318
  /// Create a specialization for custom holder types (silently ignores std::shared_ptr)
865
1319
  #define PYBIND11_DECLARE_HOLDER_TYPE(type, holder_type, ...) \
866
1320
  PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) \
867
1321
  namespace detail { \
868
1322
  template <typename type> \
869
- struct always_construct_holder<holder_type> : always_construct_holder<void, ##__VA_ARGS__> { \
870
- }; \
1323
+ struct always_construct_holder<holder_type> : always_construct_holder_value<__VA_ARGS__> {}; \
871
1324
  template <typename type> \
872
1325
  class type_caster<holder_type, enable_if_t<!is_shared_ptr<holder_type>::value>> \
873
1326
  : public type_caster_holder<type, holder_type> {}; \
@@ -878,10 +1331,14 @@ struct always_construct_holder {
878
1331
  template <typename base, typename holder>
879
1332
  struct is_holder_type
880
1333
  : std::is_base_of<detail::type_caster_holder<base, holder>, detail::type_caster<holder>> {};
881
- // Specialization for always-supported unique_ptr holders:
1334
+
1335
+ // Specializations for always-supported holders:
882
1336
  template <typename base, typename deleter>
883
1337
  struct is_holder_type<base, std::unique_ptr<base, deleter>> : std::true_type {};
884
1338
 
1339
+ template <typename base>
1340
+ struct is_holder_type<base, smart_holder> : std::true_type {};
1341
+
885
1342
  #ifdef PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION // See PR #4888
886
1343
 
887
1344
  // This leads to compilation errors if a specialization is missing.
@@ -911,7 +1368,7 @@ struct handle_type_name<dict> {
911
1368
  };
912
1369
  template <>
913
1370
  struct handle_type_name<anyset> {
914
- static constexpr auto name = const_name("Union[set, frozenset]");
1371
+ static constexpr auto name = const_name("set | frozenset");
915
1372
  };
916
1373
  template <>
917
1374
  struct handle_type_name<set> {
@@ -939,27 +1396,27 @@ struct handle_type_name<bytes> {
939
1396
  };
940
1397
  template <>
941
1398
  struct handle_type_name<buffer> {
942
- static constexpr auto name = const_name("Buffer");
1399
+ static constexpr auto name = const_name(PYBIND11_BUFFER_TYPE_HINT);
943
1400
  };
944
1401
  template <>
945
1402
  struct handle_type_name<int_> {
946
- static constexpr auto name = const_name("int");
1403
+ static constexpr auto name = io_name("typing.SupportsInt", "int");
947
1404
  };
948
1405
  template <>
949
1406
  struct handle_type_name<iterable> {
950
- static constexpr auto name = const_name("Iterable");
1407
+ static constexpr auto name = const_name("collections.abc.Iterable");
951
1408
  };
952
1409
  template <>
953
1410
  struct handle_type_name<iterator> {
954
- static constexpr auto name = const_name("Iterator");
1411
+ static constexpr auto name = const_name("collections.abc.Iterator");
955
1412
  };
956
1413
  template <>
957
1414
  struct handle_type_name<float_> {
958
- static constexpr auto name = const_name("float");
1415
+ static constexpr auto name = io_name("typing.SupportsFloat", "float");
959
1416
  };
960
1417
  template <>
961
1418
  struct handle_type_name<function> {
962
- static constexpr auto name = const_name("Callable");
1419
+ static constexpr auto name = const_name("collections.abc.Callable");
963
1420
  };
964
1421
  template <>
965
1422
  struct handle_type_name<handle> {
@@ -971,7 +1428,7 @@ struct handle_type_name<none> {
971
1428
  };
972
1429
  template <>
973
1430
  struct handle_type_name<sequence> {
974
- static constexpr auto name = const_name("Sequence");
1431
+ static constexpr auto name = const_name("collections.abc.Sequence");
975
1432
  };
976
1433
  template <>
977
1434
  struct handle_type_name<bytearray> {
@@ -991,7 +1448,7 @@ struct handle_type_name<type> {
991
1448
  };
992
1449
  template <>
993
1450
  struct handle_type_name<capsule> {
994
- static constexpr auto name = const_name("capsule");
1451
+ static constexpr auto name = const_name(PYBIND11_CAPSULE_TYPE_TYPE_HINT);
995
1452
  };
996
1453
  template <>
997
1454
  struct handle_type_name<ellipsis> {
@@ -999,16 +1456,24 @@ struct handle_type_name<ellipsis> {
999
1456
  };
1000
1457
  template <>
1001
1458
  struct handle_type_name<weakref> {
1002
- static constexpr auto name = const_name("weakref");
1459
+ static constexpr auto name = const_name("weakref.ReferenceType");
1003
1460
  };
1004
1461
  template <>
1005
1462
  struct handle_type_name<args> {
1006
1463
  static constexpr auto name = const_name("*args");
1007
1464
  };
1465
+ template <typename T>
1466
+ struct handle_type_name<Args<T>> {
1467
+ static constexpr auto name = const_name("*args: ") + make_caster<T>::name;
1468
+ };
1008
1469
  template <>
1009
1470
  struct handle_type_name<kwargs> {
1010
1471
  static constexpr auto name = const_name("**kwargs");
1011
1472
  };
1473
+ template <typename T>
1474
+ struct handle_type_name<KWArgs<T>> {
1475
+ static constexpr auto name = const_name("**kwargs: ") + make_caster<T>::name;
1476
+ };
1012
1477
  template <>
1013
1478
  struct handle_type_name<obj_attr_accessor> {
1014
1479
  static constexpr auto name = const_name<obj_attr_accessor>();
@@ -1172,8 +1637,17 @@ template <typename T,
1172
1637
  = 0>
1173
1638
  T cast(const handle &handle) {
1174
1639
  using namespace detail;
1175
- static_assert(!cast_is_temporary_value_reference<T>::value,
1640
+ constexpr bool is_enum_cast = type_uses_type_caster_enum_type<intrinsic_t<T>>::value;
1641
+ static_assert(!cast_is_temporary_value_reference<T>::value || is_enum_cast,
1176
1642
  "Unable to cast type to reference: value is local to type caster");
1643
+ #ifndef NDEBUG
1644
+ if (is_enum_cast && cast_is_temporary_value_reference<T>::value) {
1645
+ if (detail::global_internals_native_enum_type_map_contains(
1646
+ std::type_index(typeid(intrinsic_t<T>)))) {
1647
+ pybind11_fail("Unable to cast native enum type to reference");
1648
+ }
1649
+ }
1650
+ #endif
1177
1651
  return cast_op<T>(load_type<T>(handle));
1178
1652
  }
1179
1653
 
@@ -1308,12 +1782,42 @@ inline void object::cast() && {
1308
1782
 
1309
1783
  PYBIND11_NAMESPACE_BEGIN(detail)
1310
1784
 
1785
+ // forward declaration (definition in pybind11.h)
1786
+ template <typename T>
1787
+ std::string generate_type_signature();
1788
+
1311
1789
  // Declared in pytypes.h:
1312
1790
  template <typename T, enable_if_t<!is_pyobject<T>::value, int>>
1313
1791
  object object_or_cast(T &&o) {
1314
1792
  return pybind11::cast(std::forward<T>(o));
1315
1793
  }
1316
1794
 
1795
+ // Declared in pytypes.h:
1796
+ // Implemented here so that make_caster<T> can be used.
1797
+ template <typename D>
1798
+ template <typename T>
1799
+ str_attr_accessor object_api<D>::attr_with_type_hint(const char *key) const {
1800
+ #if !defined(__cpp_inline_variables)
1801
+ static_assert(always_false<T>::value,
1802
+ "C++17 feature __cpp_inline_variables not available: "
1803
+ "https://en.cppreference.com/w/cpp/language/static#Static_data_members");
1804
+ #endif
1805
+ object ann = annotations();
1806
+ if (ann.contains(key)) {
1807
+ throw std::runtime_error("__annotations__[\"" + std::string(key) + "\"] was set already.");
1808
+ }
1809
+
1810
+ ann[key] = generate_type_signature<T>();
1811
+ return {derived(), key};
1812
+ }
1813
+
1814
+ template <typename D>
1815
+ template <typename T>
1816
+ obj_attr_accessor object_api<D>::attr_with_type_hint(handle key) const {
1817
+ (void) attr_with_type_hint<T>(key.cast<std::string>().c_str());
1818
+ return {derived(), reinterpret_borrow<object>(key)};
1819
+ }
1820
+
1317
1821
  // Placeholder type for the unneeded (and dead code) static variable in the
1318
1822
  // PYBIND11_OVERRIDE_OVERRIDE macro
1319
1823
  struct override_unused {};
@@ -1339,13 +1843,24 @@ enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&,
1339
1843
  // static_assert, even though if it's in dead code, so we provide a "trampoline" to pybind11::cast
1340
1844
  // that only does anything in cases where pybind11::cast is valid.
1341
1845
  template <typename T>
1342
- enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_safe(object &&) {
1846
+ enable_if_t<cast_is_temporary_value_reference<T>::value
1847
+ && !detail::is_same_ignoring_cvref<T, PyObject *>::value,
1848
+ T>
1849
+ cast_safe(object &&) {
1343
1850
  pybind11_fail("Internal error: cast_safe fallback invoked");
1344
1851
  }
1345
1852
  template <typename T>
1346
1853
  enable_if_t<std::is_void<T>::value, void> cast_safe(object &&) {}
1347
1854
  template <typename T>
1348
- enable_if_t<detail::none_of<cast_is_temporary_value_reference<T>, std::is_void<T>>::value, T>
1855
+ enable_if_t<detail::is_same_ignoring_cvref<T, PyObject *>::value, PyObject *>
1856
+ cast_safe(object &&o) {
1857
+ return o.release().ptr();
1858
+ }
1859
+ template <typename T>
1860
+ enable_if_t<detail::none_of<cast_is_temporary_value_reference<T>,
1861
+ detail::is_same_ignoring_cvref<T, PyObject *>,
1862
+ std::is_void<T>>::value,
1863
+ T>
1349
1864
  cast_safe(object &&o) {
1350
1865
  return pybind11::cast<T>(std::move(o));
1351
1866
  }
@@ -1485,7 +2000,7 @@ struct kw_only {};
1485
2000
 
1486
2001
  /// \ingroup annotations
1487
2002
  /// Annotation indicating that all previous arguments are positional-only; the is the equivalent of
1488
- /// an unnamed '/' argument (in Python 3.8)
2003
+ /// an unnamed '/' argument
1489
2004
  struct pos_only {};
1490
2005
 
1491
2006
  template <typename T>
@@ -1546,15 +2061,24 @@ struct function_call {
1546
2061
  handle init_self;
1547
2062
  };
1548
2063
 
2064
+ // See PR #5396 for the discussion that led to this
2065
+ template <typename Base, typename Derived, typename = void>
2066
+ struct is_same_or_base_of : std::is_same<Base, Derived> {};
2067
+
2068
+ // Only evaluate is_base_of if Derived is complete.
2069
+ // is_base_of raises a compiler error if Derived is incomplete.
2070
+ template <typename Base, typename Derived>
2071
+ struct is_same_or_base_of<Base, Derived, decltype(void(sizeof(Derived)))>
2072
+ : any_of<std::is_same<Base, Derived>, std::is_base_of<Base, Derived>> {};
2073
+
1549
2074
  /// Helper class which loads arguments for C++ functions called from Python
1550
2075
  template <typename... Args>
1551
2076
  class argument_loader {
1552
2077
  using indices = make_index_sequence<sizeof...(Args)>;
1553
-
1554
2078
  template <typename Arg>
1555
- using argument_is_args = std::is_same<intrinsic_t<Arg>, args>;
2079
+ using argument_is_args = is_same_or_base_of<args, intrinsic_t<Arg>>;
1556
2080
  template <typename Arg>
1557
- using argument_is_kwargs = std::is_same<intrinsic_t<Arg>, kwargs>;
2081
+ using argument_is_kwargs = is_same_or_base_of<kwargs, intrinsic_t<Arg>>;
1558
2082
  // Get kwargs argument position, or -1 if not present:
1559
2083
  static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();
1560
2084