aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-04-11 17:06:57 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-04-11 17:23:45 +0300
commit9b6896144521146a81c633555dd67ba846d5a98f (patch)
tree07253fcbb3ba2e7970caf4d5a10553ae37907bc7
parentafe9a2e8d0bd9c3e6c61ca56cb40ef9f108cfcd3 (diff)
downloadydb-9b6896144521146a81c633555dd67ba846d5a98f.tar.gz
Intermediate changes
-rw-r--r--contrib/libs/pybind11/README.rst9
-rw-r--r--contrib/libs/pybind11/include/pybind11/cast.h151
-rw-r--r--contrib/libs/pybind11/include/pybind11/detail/class.h31
-rw-r--r--contrib/libs/pybind11/include/pybind11/detail/common.h20
-rw-r--r--contrib/libs/pybind11/include/pybind11/detail/init.h2
-rw-r--r--contrib/libs/pybind11/include/pybind11/detail/internals.h21
-rw-r--r--contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h61
-rw-r--r--contrib/libs/pybind11/include/pybind11/gil.h14
-rw-r--r--contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h91
-rw-r--r--contrib/libs/pybind11/include/pybind11/numpy.h179
-rw-r--r--contrib/libs/pybind11/include/pybind11/pybind11.h169
-rw-r--r--contrib/libs/pybind11/include/pybind11/pytypes.h27
-rw-r--r--contrib/libs/pybind11/include/pybind11/typing.h125
-rw-r--r--contrib/libs/pybind11/ya.make4
-rw-r--r--contrib/python/matplotlib/py3/matplotlib/backends/backend_webagg.py22
15 files changed, 800 insertions, 126 deletions
diff --git a/contrib/libs/pybind11/README.rst b/contrib/libs/pybind11/README.rst
index 80213a4062..4032f97a57 100644
--- a/contrib/libs/pybind11/README.rst
+++ b/contrib/libs/pybind11/README.rst
@@ -36,10 +36,10 @@ with everything stripped away that isn't relevant for binding
generation. Without comments, the core header files only require ~4K
lines of code and depend on Python (3.6+, or PyPy) and the C++
standard library. This compact implementation was possible thanks to
-some of the new C++11 language features (specifically: tuples, lambda
-functions and variadic templates). Since its creation, this library has
-grown beyond Boost.Python in many ways, leading to dramatically simpler
-binding code in many common situations.
+some C++11 language features (specifically: tuples, lambda functions and
+variadic templates). Since its creation, this library has grown beyond
+Boost.Python in many ways, leading to dramatically simpler binding code in many
+common situations.
Tutorial and reference documentation is provided at
`pybind11.readthedocs.io <https://pybind11.readthedocs.io/en/latest>`_.
@@ -71,6 +71,7 @@ pybind11 can map the following core C++ features to Python:
- Internal references with correct reference counting
- C++ classes with virtual (and pure virtual) methods can be extended
in Python
+- Integrated NumPy support (NumPy 2 requires pybind11 2.12+)
Goodies
-------
diff --git a/contrib/libs/pybind11/include/pybind11/cast.h b/contrib/libs/pybind11/include/pybind11/cast.h
index aa7dd494ad..6a37d265c0 100644
--- a/contrib/libs/pybind11/include/pybind11/cast.h
+++ b/contrib/libs/pybind11/include/pybind11/cast.h
@@ -43,13 +43,15 @@ using make_caster = type_caster<intrinsic_t<type>>;
// Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T
template <typename T>
typename make_caster<T>::template cast_op_type<T> cast_op(make_caster<T> &caster) {
- return caster.operator typename make_caster<T>::template cast_op_type<T>();
+ using result_t = typename make_caster<T>::template cast_op_type<T>; // See PR #4893
+ return caster.operator result_t();
}
template <typename T>
typename make_caster<T>::template cast_op_type<typename std::add_rvalue_reference<T>::type>
cast_op(make_caster<T> &&caster) {
- return std::move(caster).operator typename make_caster<T>::
- template cast_op_type<typename std::add_rvalue_reference<T>::type>();
+ using result_t = typename make_caster<T>::template cast_op_type<
+ typename std::add_rvalue_reference<T>::type>; // See PR #4893
+ return std::move(caster).operator result_t();
}
template <typename type>
@@ -326,8 +328,9 @@ public:
value = false;
return true;
}
- if (convert || (std::strcmp("numpy.bool_", Py_TYPE(src.ptr())->tp_name) == 0)) {
- // (allow non-implicit conversion for numpy booleans)
+ if (convert || is_numpy_bool(src)) {
+ // (allow non-implicit conversion for numpy booleans), use strncmp
+ // since NumPy 1.x had an additional trailing underscore.
Py_ssize_t res = -1;
if (src.is_none()) {
@@ -359,6 +362,15 @@ public:
return handle(src ? Py_True : Py_False).inc_ref();
}
PYBIND11_TYPE_CASTER(bool, const_name("bool"));
+
+private:
+ // Test if an object is a NumPy boolean (without fetching the type).
+ static inline bool is_numpy_bool(handle object) {
+ const char *type_name = Py_TYPE(object.ptr())->tp_name;
+ // Name changed to `numpy.bool` in NumPy 2, `numpy.bool_` is needed for 1.x support
+ return std::strcmp("numpy.bool", type_name) == 0
+ || std::strcmp("numpy.bool_", type_name) == 0;
+ }
};
// Helper class for UTF-{8,16,32} C++ stl strings:
@@ -687,8 +699,9 @@ public:
return cast(*src, policy, parent);
}
- static constexpr auto name
- = const_name("Tuple[") + concat(make_caster<Ts>::name...) + const_name("]");
+ static constexpr auto name = const_name("tuple[")
+ + ::pybind11::detail::concat(make_caster<Ts>::name...)
+ + const_name("]");
template <typename T>
using cast_op_type = type;
@@ -896,10 +909,53 @@ struct is_holder_type
template <typename base, typename deleter>
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>
struct handle_type_name {
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 <>
struct handle_type_name<bool_> {
static constexpr auto name = const_name("bool");
@@ -909,6 +965,10 @@ struct handle_type_name<bytes> {
static constexpr auto name = const_name(PYBIND11_BYTES_NAME);
};
template <>
+struct handle_type_name<buffer> {
+ static constexpr auto name = const_name("Buffer");
+};
+template <>
struct handle_type_name<int_> {
static constexpr auto name = const_name("int");
};
@@ -925,10 +985,50 @@ struct handle_type_name<float_> {
static constexpr auto name = const_name("float");
};
template <>
+struct handle_type_name<function> {
+ static constexpr auto name = const_name("Callable");
+};
+template <>
+struct handle_type_name<handle> {
+ static constexpr auto name = handle_type_name<object>::name;
+};
+template <>
struct handle_type_name<none> {
static constexpr auto name = const_name("None");
};
template <>
+struct handle_type_name<sequence> {
+ static constexpr auto name = const_name("Sequence");
+};
+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> {
static constexpr auto name = const_name("*args");
};
@@ -936,6 +1036,30 @@ template <>
struct handle_type_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>
struct pyobject_caster {
@@ -1416,7 +1540,15 @@ inline namespace literals {
/** \rst
String literal version of `arg`
\endrst */
-constexpr arg operator"" _a(const char *name, size_t) { return arg(name); }
+constexpr arg
+#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5
+operator"" _a // gcc 4.8.5 insists on having a space (hard error).
+#else
+operator""_a // clang 17 generates a deprecation warning if there is a space.
+#endif
+ (const char *name, size_t) {
+ return arg(name);
+}
} // namespace literals
PYBIND11_NAMESPACE_BEGIN(detail)
@@ -1477,7 +1609,8 @@ public:
static_assert(args_pos == -1 || args_pos == constexpr_first<argument_is_args, Args...>(),
"py::args cannot be specified more than once");
- static constexpr auto arg_names = concat(type_descr(make_caster<Args>::name)...);
+ static constexpr auto arg_names
+ = ::pybind11::detail::concat(type_descr(make_caster<Args>::name)...);
bool load_args(function_call &call) { return load_impl_sequence(call, indices{}); }
diff --git a/contrib/libs/pybind11/include/pybind11/detail/class.h b/contrib/libs/pybind11/include/pybind11/detail/class.h
index fd192530b5..2657148af2 100644
--- a/contrib/libs/pybind11/include/pybind11/detail/class.h
+++ b/contrib/libs/pybind11/include/pybind11/detail/class.h
@@ -86,17 +86,16 @@ inline PyTypeObject *make_static_property_type() {
type->tp_descr_get = pybind11_static_get;
type->tp_descr_set = pybind11_static_set;
- if (PyType_Ready(type) < 0) {
- pybind11_fail("make_static_property_type(): failure in PyType_Ready()!");
- }
-
# if PY_VERSION_HEX >= 0x030C0000
- // PRE 3.12 FEATURE FREEZE. PLEASE REVIEW AFTER FREEZE.
// Since Python-3.12 property-derived types are required to
// have dynamic attributes (to set `__doc__`)
enable_dynamic_attributes(heap_type);
# endif
+ if (PyType_Ready(type) < 0) {
+ pybind11_fail("make_static_property_type(): failure in PyType_Ready()!");
+ }
+
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
@@ -191,12 +190,10 @@ extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, P
return nullptr;
}
- // This must be a pybind11 instance
- auto *instance = reinterpret_cast<detail::instance *>(self);
-
// Ensure that the base __init__ function(s) were called
- for (const auto &vh : values_and_holders(instance)) {
- if (!vh.holder_constructed()) {
+ values_and_holders vhs(self);
+ for (const auto &vh : vhs) {
+ if (!vh.holder_constructed() && !vhs.is_redundant_value_and_holder(vh)) {
PyErr_Format(PyExc_TypeError,
"%.200s.__init__() must be called when overriding __init__",
get_fully_qualified_tp_name(vh.type->type).c_str());
@@ -379,7 +376,7 @@ extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *,
extern "C" inline int pybind11_object_init(PyObject *self, PyObject *, PyObject *) {
PyTypeObject *type = Py_TYPE(self);
std::string msg = get_fully_qualified_tp_name(type) + ": No constructor defined!";
- PyErr_SetString(PyExc_TypeError, msg.c_str());
+ set_error(PyExc_TypeError, msg.c_str());
return -1;
}
@@ -553,8 +550,12 @@ extern "C" inline int pybind11_set_dict(PyObject *self, PyObject *new_dict, void
/// dynamic_attr: Allow the garbage collector to traverse the internal instance `__dict__`.
extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) {
+#if PY_VERSION_HEX >= 0x030D0000
+ PyObject_VisitManagedDict(self, visit, arg);
+#else
PyObject *&dict = *_PyObject_GetDictPtr(self);
Py_VISIT(dict);
+#endif
// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
#if PY_VERSION_HEX >= 0x03090000
Py_VISIT(Py_TYPE(self));
@@ -564,8 +565,12 @@ extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *a
/// dynamic_attr: Allow the GC to clear the dictionary.
extern "C" inline int pybind11_clear(PyObject *self) {
+#if PY_VERSION_HEX >= 0x030D0000
+ PyObject_ClearManagedDict(self);
+#else
PyObject *&dict = *_PyObject_GetDictPtr(self);
Py_CLEAR(dict);
+#endif
return 0;
}
@@ -615,7 +620,7 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
if (view) {
view->obj = nullptr;
}
- PyErr_SetString(PyExc_BufferError, "pybind11_getbuffer(): Internal error");
+ set_error(PyExc_BufferError, "pybind11_getbuffer(): Internal error");
return -1;
}
std::memset(view, 0, sizeof(Py_buffer));
@@ -623,7 +628,7 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly) {
delete info;
// view->obj = nullptr; // Was just memset to 0, so not necessary
- PyErr_SetString(PyExc_BufferError, "Writable buffer requested for readonly storage");
+ set_error(PyExc_BufferError, "Writable buffer requested for readonly storage");
return -1;
}
view->obj = obj;
diff --git a/contrib/libs/pybind11/include/pybind11/detail/common.h b/contrib/libs/pybind11/include/pybind11/detail/common.h
index 601408153a..f14ea1238f 100644
--- a/contrib/libs/pybind11/include/pybind11/detail/common.h
+++ b/contrib/libs/pybind11/include/pybind11/detail/common.h
@@ -10,12 +10,12 @@
#pragma once
#define PYBIND11_VERSION_MAJOR 2
-#define PYBIND11_VERSION_MINOR 11
-#define PYBIND11_VERSION_PATCH 1
+#define PYBIND11_VERSION_MINOR 12
+#define PYBIND11_VERSION_PATCH 0
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
// Additional convention: 0xD = dev
-#define PYBIND11_VERSION_HEX 0x020B0100
+#define PYBIND11_VERSION_HEX 0x020C0000
// Define some generic pybind11 helper macros for warning management.
//
@@ -118,6 +118,14 @@
# endif
#endif
+#if defined(PYBIND11_CPP20)
+# define PYBIND11_CONSTINIT constinit
+# define PYBIND11_DTOR_CONSTEXPR constexpr
+#else
+# define PYBIND11_CONSTINIT
+# define PYBIND11_DTOR_CONSTEXPR
+#endif
+
// Compiler version assertions
#if defined(__INTEL_COMPILER)
# if __INTEL_COMPILER < 1800
@@ -285,6 +293,10 @@ PYBIND11_WARNING_DISABLE_MSVC(4505)
# undef copysign
#endif
+#if defined(PYBIND11_NUMPY_1_ONLY)
+# define PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED
+#endif
+
#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
# define PYBIND11_SIMPLE_GIL_MANAGEMENT
#endif
@@ -433,7 +445,7 @@ PYBIND11_WARNING_POP
return nullptr; \
} \
catch (const std::exception &e) { \
- PyErr_SetString(PyExc_ImportError, e.what()); \
+ ::pybind11::set_error(PyExc_ImportError, e.what()); \
return nullptr; \
}
diff --git a/contrib/libs/pybind11/include/pybind11/detail/init.h b/contrib/libs/pybind11/include/pybind11/detail/init.h
index ca5a5178c8..89a471f5b4 100644
--- a/contrib/libs/pybind11/include/pybind11/detail/init.h
+++ b/contrib/libs/pybind11/include/pybind11/detail/init.h
@@ -65,7 +65,7 @@ constexpr bool is_alias(void *) {
}
// Constructs and returns a new object; if the given arguments don't map to a constructor, we fall
-// back to brace aggregate initiailization so that for aggregate initialization can be used with
+// back to brace aggregate initialization so that for aggregate initialization can be used with
// py::init, e.g. `py::init<int, int>` to initialize a `struct T { int a; int b; }`. For
// non-aggregate types, we need to use an ordinary T(...) constructor (invoking as `T{...}` usually
// works, but will not do the expected thing when `T` has an `initializer_list<T>` constructor).
diff --git a/contrib/libs/pybind11/include/pybind11/detail/internals.h b/contrib/libs/pybind11/include/pybind11/detail/internals.h
index 5f4ba6959a..049dbcaa19 100644
--- a/contrib/libs/pybind11/include/pybind11/detail/internals.h
+++ b/contrib/libs/pybind11/include/pybind11/detail/internals.h
@@ -36,8 +36,9 @@
/// further ABI-incompatible changes may be made before the ABI is officially
/// changed to the new version.
#ifndef PYBIND11_INTERNALS_VERSION
-# if PY_VERSION_HEX >= 0x030C0000
+# if PY_VERSION_HEX >= 0x030C0000 || defined(_MSC_VER)
// Version bump for Python 3.12+, before first 3.12 beta release.
+// Version bump for MSVC piggy-backed on PR #4779. See comments there.
# define PYBIND11_INTERNALS_VERSION 5
# else
# define PYBIND11_INTERNALS_VERSION 4
@@ -68,9 +69,14 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
// `Py_LIMITED_API` anyway.
# if PYBIND11_INTERNALS_VERSION > 4
# define PYBIND11_TLS_KEY_REF Py_tss_t &
-# if defined(__GNUC__) && !defined(__INTEL_COMPILER)
-// Clang on macOS warns due to `Py_tss_NEEDS_INIT` not specifying an initializer
-// for every field.
+# if defined(__clang__)
+# define PYBIND11_TLS_KEY_INIT(var) \
+ _Pragma("clang diagnostic push") /**/ \
+ _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
+ Py_tss_t var \
+ = Py_tss_NEEDS_INIT; \
+ _Pragma("clang diagnostic pop")
+# elif defined(__GNUC__) && !defined(__INTEL_COMPILER)
# define PYBIND11_TLS_KEY_INIT(var) \
_Pragma("GCC diagnostic push") /**/ \
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
@@ -293,9 +299,12 @@ struct type_info {
#endif
/// On Linux/OSX, changes in __GXX_ABI_VERSION__ indicate ABI incompatibility.
+/// On MSVC, changes in _MSC_VER may indicate ABI incompatibility (#2898).
#ifndef PYBIND11_BUILD_ABI
# if defined(__GXX_ABI_VERSION)
# define PYBIND11_BUILD_ABI "_cxxabi" PYBIND11_TOSTRING(__GXX_ABI_VERSION)
+# elif defined(_MSC_VER)
+# define PYBIND11_BUILD_ABI "_mscver" PYBIND11_TOSTRING(_MSC_VER)
# else
# define PYBIND11_BUILD_ABI ""
# endif
@@ -365,7 +374,7 @@ inline bool raise_err(PyObject *exc_type, const char *msg) {
return true;
}
#endif
- PyErr_SetString(exc_type, msg);
+ set_error(exc_type, msg);
return false;
}
@@ -462,6 +471,7 @@ inline object get_python_state_dict() {
if (!state_dict) {
#if PY_VERSION_HEX >= 0x03030000
raise_from(PyExc_SystemError, "pybind11::detail::get_python_state_dict() FAILED");
+ throw error_already_set();
#else
PyErr_SetString(PyExc_SystemError, "pybind11::detail::get_python_state_dict() FAILED");
#endif
@@ -478,6 +488,7 @@ inline internals **get_internals_pp_from_capsule(handle obj) {
if (raw_ptr == nullptr) {
#if PY_VERSION_HEX >= 0x03030000
raise_from(PyExc_SystemError, "pybind11::detail::get_internals_pp_from_capsule() FAILED");
+ throw error_already_set();
#else
PyErr_SetString(PyExc_SystemError, "pybind11::detail::get_internals_pp_from_capsule() FAILED");
#endif
diff --git a/contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h b/contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h
index 245bf99d2d..4d5e322c2b 100644
--- a/contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h
+++ b/contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h
@@ -103,8 +103,22 @@ public:
inline std::pair<decltype(internals::registered_types_py)::iterator, bool>
all_type_info_get_cache(PyTypeObject *type);
+// Band-aid workaround to fix a subtle but serious bug in a minimalistic fashion. See PR #4762.
+inline void all_type_info_add_base_most_derived_first(std::vector<type_info *> &bases,
+ type_info *addl_base) {
+ for (auto it = bases.begin(); it != bases.end(); it++) {
+ type_info *existing_base = *it;
+ if (PyType_IsSubtype(addl_base->type, existing_base->type) != 0) {
+ bases.insert(it, addl_base);
+ return;
+ }
+ }
+ bases.push_back(addl_base);
+}
+
// Populates a just-created cache entry.
PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_info *> &bases) {
+ assert(bases.empty());
std::vector<PyTypeObject *> check;
for (handle parent : reinterpret_borrow<tuple>(t->tp_bases)) {
check.push_back((PyTypeObject *) parent.ptr());
@@ -137,7 +151,7 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
}
}
if (!found) {
- bases.push_back(tinfo);
+ all_type_info_add_base_most_derived_first(bases, tinfo);
}
}
} else if (type->tp_bases) {
@@ -323,18 +337,29 @@ public:
explicit values_and_holders(instance *inst)
: inst{inst}, tinfo(all_type_info(Py_TYPE(inst))) {}
+ explicit values_and_holders(PyObject *obj)
+ : inst{nullptr}, tinfo(all_type_info(Py_TYPE(obj))) {
+ if (!tinfo.empty()) {
+ inst = reinterpret_cast<instance *>(obj);
+ }
+ }
+
struct iterator {
private:
instance *inst = nullptr;
const type_vec *types = nullptr;
value_and_holder curr;
friend struct values_and_holders;
- iterator(instance *inst, const type_vec *tinfo)
- : inst{inst}, types{tinfo},
- curr(inst /* instance */,
- types->empty() ? nullptr : (*types)[0] /* type info */,
- 0, /* vpos: (non-simple types only): the first vptr comes first */
- 0 /* index */) {}
+ iterator(instance *inst, const type_vec *tinfo) : inst{inst}, types{tinfo} {
+ if (inst != nullptr) {
+ assert(!types->empty());
+ curr = value_and_holder(
+ inst /* instance */,
+ (*types)[0] /* type info */,
+ 0, /* vpos: (non-simple types only): the first vptr comes first */
+ 0 /* index */);
+ }
+ }
// Past-the-end iterator:
explicit iterator(size_t end) : curr(end) {}
@@ -365,6 +390,16 @@ public:
}
size_t size() { return tinfo.size(); }
+
+ // Band-aid workaround to fix a subtle but serious bug in a minimalistic fashion. See PR #4762.
+ bool is_redundant_value_and_holder(const value_and_holder &vh) {
+ for (size_t i = 0; i < vh.index; i++) {
+ if (PyType_IsSubtype(tinfo[i]->type, tinfo[vh.index]->type) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
};
/**
@@ -496,8 +531,10 @@ inline PyThreadState *get_thread_state_unchecked() {
return PyThreadState_GET();
#elif PY_VERSION_HEX < 0x03000000
return _PyThreadState_Current;
-#else
+#elif PY_VERSION_HEX < 0x030D0000
return _PyThreadState_UncheckedGet();
+#else
+ return PyThreadState_GetUnchecked();
#endif
}
@@ -796,7 +833,7 @@ public:
std::string tname = rtti_type ? rtti_type->name() : cast_type.name();
detail::clean_type_id(tname);
std::string msg = "Unregistered type : " + tname;
- PyErr_SetString(PyExc_TypeError, msg.c_str());
+ set_error(PyExc_TypeError, msg.c_str());
return {nullptr, nullptr};
}
@@ -1174,13 +1211,17 @@ protected:
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) {
if (auto *type_data = get_type_info(ti)) {
handle th((PyObject *) type_data->type);
return th.attr("__module__").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)
diff --git a/contrib/libs/pybind11/include/pybind11/gil.h b/contrib/libs/pybind11/include/pybind11/gil.h
index 570a5581d5..b9d8b88a3b 100644
--- a/contrib/libs/pybind11/include/pybind11/gil.h
+++ b/contrib/libs/pybind11/include/pybind11/gil.h
@@ -11,6 +11,8 @@
#include "detail/common.h"
+#include <cassert>
+
#if defined(WITH_THREAD) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
# include "detail/internals.h"
#endif
@@ -137,7 +139,11 @@ private:
class gil_scoped_release {
public:
+ // PRECONDITION: The GIL must be held when this constructor is called.
explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
+#ifdef PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF
+ assert(PyGILState_Check());
+#endif
// `get_internals()` must be called here unconditionally in order to initialize
// `internals.tstate` for subsequent `gil_scoped_acquire` calls. Otherwise, an
// initialization race could occur as multiple threads try `gil_scoped_acquire`.
@@ -201,7 +207,13 @@ class gil_scoped_release {
PyThreadState *state;
public:
- gil_scoped_release() : state{PyEval_SaveThread()} {}
+ // PRECONDITION: The GIL must be held when this constructor is called.
+ gil_scoped_release() {
+#ifdef PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF
+ assert(PyGILState_Check());
+#endif
+ state = PyEval_SaveThread();
+ }
gil_scoped_release(const gil_scoped_release &) = delete;
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
~gil_scoped_release() { PyEval_RestoreThread(state); }
diff --git a/contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h b/contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h
new file mode 100644
index 0000000000..eaf84d16e8
--- /dev/null
+++ b/contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h
@@ -0,0 +1,91 @@
+// Copyright (c) 2023 The pybind Community.
+
+#pragma once
+
+#include "detail/common.h"
+#include "gil.h"
+
+#include <cassert>
+#include <mutex>
+
+PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
+
+// Use the `gil_safe_call_once_and_store` class below instead of the naive
+//
+// static auto imported_obj = py::module_::import("module_name"); // BAD, DO NOT USE!
+//
+// which has two serious issues:
+//
+// 1. Py_DECREF() calls potentially after the Python interpreter was finalized already, and
+// 2. deadlocks in multi-threaded processes (because of missing lock ordering).
+//
+// The following alternative avoids both problems:
+//
+// PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object> storage;
+// auto &imported_obj = storage // Do NOT make this `static`!
+// .call_once_and_store_result([]() {
+// return py::module_::import("module_name");
+// })
+// .get_stored();
+//
+// The parameter of `call_once_and_store_result()` must be callable. It can make
+// CPython API calls, and in particular, it can temporarily release the GIL.
+//
+// `T` can be any C++ type, it does not have to involve CPython API types.
+//
+// The behavior with regard to signals, e.g. `SIGINT` (`KeyboardInterrupt`),
+// is not ideal. If the main thread is the one to actually run the `Callable`,
+// then a `KeyboardInterrupt` will interrupt it if it is running normal Python
+// code. The situation is different if a non-main thread runs the
+// `Callable`, and then the main thread starts waiting for it to complete:
+// a `KeyboardInterrupt` will not interrupt the non-main thread, but it will
+// get processed only when it is the main thread's turn again and it is running
+// normal Python code. However, this will be unnoticeable for quick call-once
+// functions, which is usually the case.
+template <typename T>
+class gil_safe_call_once_and_store {
+public:
+ // PRECONDITION: The GIL must be held when `call_once_and_store_result()` is called.
+ template <typename Callable>
+ gil_safe_call_once_and_store &call_once_and_store_result(Callable &&fn) {
+ if (!is_initialized_) { // This read is guarded by the GIL.
+ // Multiple threads may enter here, because the GIL is released in the next line and
+ // CPython API calls in the `fn()` call below may release and reacquire the GIL.
+ gil_scoped_release gil_rel; // Needed to establish lock ordering.
+ std::call_once(once_flag_, [&] {
+ // Only one thread will ever enter here.
+ gil_scoped_acquire gil_acq;
+ ::new (storage_) T(fn()); // fn may release, but will reacquire, the GIL.
+ is_initialized_ = true; // This write is guarded by the GIL.
+ });
+ // All threads will observe `is_initialized_` as true here.
+ }
+ // Intentionally not returning `T &` to ensure the calling code is self-documenting.
+ return *this;
+ }
+
+ // This must only be called after `call_once_and_store_result()` was called.
+ T &get_stored() {
+ assert(is_initialized_);
+ PYBIND11_WARNING_PUSH
+#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5
+ // Needed for gcc 4.8.5
+ PYBIND11_WARNING_DISABLE_GCC("-Wstrict-aliasing")
+#endif
+ return *reinterpret_cast<T *>(storage_);
+ PYBIND11_WARNING_POP
+ }
+
+ constexpr gil_safe_call_once_and_store() = default;
+ PYBIND11_DTOR_CONSTEXPR ~gil_safe_call_once_and_store() = default;
+
+private:
+ alignas(T) char storage_[sizeof(T)] = {};
+ std::once_flag once_flag_ = {};
+ bool is_initialized_ = false;
+ // The `is_initialized_`-`storage_` pair is very similar to `std::optional`,
+ // but the latter does not have the triviality properties of former,
+ // therefore `std::optional` is not a viable alternative here.
+};
+
+PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
diff --git a/contrib/libs/pybind11/include/pybind11/numpy.h b/contrib/libs/pybind11/include/pybind11/numpy.h
index 8162908edd..b0af0a42ec 100644
--- a/contrib/libs/pybind11/include/pybind11/numpy.h
+++ b/contrib/libs/pybind11/include/pybind11/numpy.h
@@ -10,7 +10,10 @@
#pragma once
#include "pybind11.h"
+#include "detail/common.h"
#include "complex.h"
+#include "gil_safe_call_once.h"
+#include "pytypes.h"
#include <algorithm>
#include <array>
@@ -26,10 +29,15 @@
#include <utility>
#include <vector>
+#if defined(PYBIND11_NUMPY_1_ONLY) && !defined(PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED)
+# error PYBIND11_NUMPY_1_ONLY must be defined before any pybind11 header is included.
+#endif
+
/* This will be true on all flat address space platforms and allows us to reduce the
whole npy_intp / ssize_t / Py_intptr_t business down to just ssize_t for all size
and dimension types (e.g. shape, strides, indexing), instead of inflicting this
- upon the library user. */
+ upon the library user.
+ Note that NumPy 2 now uses ssize_t for `npy_intp` to simplify this. */
static_assert(sizeof(::pybind11::ssize_t) == sizeof(Py_intptr_t), "ssize_t != Py_intptr_t");
static_assert(std::is_signed<Py_intptr_t>::value, "Py_intptr_t must be signed");
// We now can reinterpret_cast between py::ssize_t and Py_intptr_t (MSVC + PyPy cares)
@@ -38,11 +46,17 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
+class dtype; // Forward declaration
class array; // Forward declaration
PYBIND11_NAMESPACE_BEGIN(detail)
template <>
+struct handle_type_name<dtype> {
+ static constexpr auto name = const_name("numpy.dtype");
+};
+
+template <>
struct handle_type_name<array> {
static constexpr auto name = const_name("numpy.ndarray");
};
@@ -50,7 +64,8 @@ struct handle_type_name<array> {
template <typename type, typename SFINAE = void>
struct npy_format_descriptor;
-struct PyArrayDescr_Proxy {
+/* NumPy 1 proxy (always includes legacy fields) */
+struct PyArrayDescr1_Proxy {
PyObject_HEAD
PyObject *typeobj;
char kind;
@@ -65,6 +80,43 @@ struct PyArrayDescr_Proxy {
PyObject *names;
};
+#ifndef PYBIND11_NUMPY_1_ONLY
+struct PyArrayDescr_Proxy {
+ PyObject_HEAD
+ PyObject *typeobj;
+ char kind;
+ char type;
+ char byteorder;
+ char _former_flags;
+ int type_num;
+ /* Additional fields are NumPy version specific. */
+};
+#else
+/* NumPy 1.x only, we can expose all fields */
+using PyArrayDescr_Proxy = PyArrayDescr1_Proxy;
+#endif
+
+/* NumPy 2 proxy, including legacy fields */
+struct PyArrayDescr2_Proxy {
+ PyObject_HEAD
+ PyObject *typeobj;
+ char kind;
+ char type;
+ char byteorder;
+ char _former_flags;
+ int type_num;
+ std::uint64_t flags;
+ ssize_t elsize;
+ ssize_t alignment;
+ PyObject *metadata;
+ Py_hash_t hash;
+ void *reserved_null[2];
+ /* The following fields only exist if 0 <= type_num < 2056 */
+ char *subarray;
+ PyObject *fields;
+ PyObject *names;
+};
+
struct PyArray_Proxy {
PyObject_HEAD
char *data;
@@ -120,6 +172,28 @@ inline numpy_internals &get_numpy_internals() {
return *ptr;
}
+PYBIND11_NOINLINE module_ import_numpy_core_submodule(const char *submodule_name) {
+ module_ numpy = module_::import("numpy");
+ str version_string = numpy.attr("__version__");
+
+ module_ numpy_lib = module_::import("numpy.lib");
+ object numpy_version = numpy_lib.attr("NumpyVersion")(version_string);
+ int major_version = numpy_version.attr("major").cast<int>();
+
+#ifdef PYBIND11_NUMPY_1_ONLY
+ if (major_version >= 2) {
+ throw std::runtime_error(
+ "This extension was built with PYBIND11_NUMPY_1_ONLY defined, "
+ "but NumPy 2 is used in this process. For NumPy2 compatibility, "
+ "this extension needs to be rebuilt without the PYBIND11_NUMPY_1_ONLY define.");
+ }
+#endif
+ /* `numpy.core` was renamed to `numpy._core` in NumPy 2.0 as it officially
+ became a private module. */
+ std::string numpy_core_path = major_version >= 2 ? "numpy._core" : "numpy.core";
+ return module_::import((numpy_core_path + "." + submodule_name).c_str());
+}
+
template <typename T>
struct same_size {
template <typename U>
@@ -186,14 +260,16 @@ struct npy_api {
NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_),
};
+ unsigned int PyArray_RUNTIME_VERSION_;
+
struct PyArray_Dims {
Py_intptr_t *ptr;
int len;
};
static npy_api &get() {
- static npy_api api = lookup();
- return api;
+ PYBIND11_CONSTINIT static gil_safe_call_once_and_store<npy_api> storage;
+ return storage.call_once_and_store_result(lookup).get_stored();
}
bool PyArray_Check_(PyObject *obj) const {
@@ -224,6 +300,7 @@ struct npy_api {
PyObject *(*PyArray_FromAny_)(PyObject *, PyObject *, int, int, int, PyObject *);
int (*PyArray_DescrConverter_)(PyObject *, PyObject **);
bool (*PyArray_EquivTypes_)(PyObject *, PyObject *);
+#ifdef PYBIND11_NUMPY_1_ONLY
int (*PyArray_GetArrayParamsFromObject_)(PyObject *,
PyObject *,
unsigned char,
@@ -232,6 +309,7 @@ struct npy_api {
Py_intptr_t *,
PyObject **,
PyObject *);
+#endif
PyObject *(*PyArray_Squeeze_)(PyObject *);
// Unused. Not removed because that affects ABI of the class.
int (*PyArray_SetBaseObject_)(PyObject *, PyObject *);
@@ -249,7 +327,8 @@ private:
API_PyArray_DescrFromScalar = 57,
API_PyArray_FromAny = 69,
API_PyArray_Resize = 80,
- API_PyArray_CopyInto = 82,
+ // CopyInto was slot 82 and 50 was effectively an alias. NumPy 2 removed 82.
+ API_PyArray_CopyInto = 50,
API_PyArray_NewCopy = 85,
API_PyArray_NewFromDescr = 94,
API_PyArray_DescrNewFromType = 96,
@@ -258,22 +337,29 @@ private:
API_PyArray_View = 137,
API_PyArray_DescrConverter = 174,
API_PyArray_EquivTypes = 182,
+#ifdef PYBIND11_NUMPY_1_ONLY
API_PyArray_GetArrayParamsFromObject = 278,
+#endif
API_PyArray_SetBaseObject = 282
};
static npy_api lookup() {
- module_ m = module_::import("numpy.core.multiarray");
+ module_ m = detail::import_numpy_core_submodule("multiarray");
auto c = m.attr("_ARRAY_API");
#if PY_MAJOR_VERSION >= 3
void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), nullptr);
#else
void **api_ptr = (void **) PyCObject_AsVoidPtr(c.ptr());
#endif
+ if (api_ptr == nullptr) {
+ raise_from(PyExc_SystemError, "FAILURE obtaining numpy _ARRAY_API pointer.");
+ throw error_already_set();
+ }
npy_api api;
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
- if (api.PyArray_GetNDArrayCFeatureVersion_() < 0x7) {
+ api.PyArray_RUNTIME_VERSION_ = api.PyArray_GetNDArrayCFeatureVersion_();
+ if (api.PyArray_RUNTIME_VERSION_ < 0x7) {
pybind11_fail("pybind11 numpy support requires numpy >= 1.7.0");
}
DECL_NPY_API(PyArray_Type);
@@ -292,7 +378,9 @@ private:
DECL_NPY_API(PyArray_View);
DECL_NPY_API(PyArray_DescrConverter);
DECL_NPY_API(PyArray_EquivTypes);
+#ifdef PYBIND11_NUMPY_1_ONLY
DECL_NPY_API(PyArray_GetArrayParamsFromObject);
+#endif
DECL_NPY_API(PyArray_SetBaseObject);
#undef DECL_NPY_API
@@ -314,6 +402,14 @@ inline const PyArrayDescr_Proxy *array_descriptor_proxy(const PyObject *ptr) {
return reinterpret_cast<const PyArrayDescr_Proxy *>(ptr);
}
+inline const PyArrayDescr1_Proxy *array_descriptor1_proxy(const PyObject *ptr) {
+ return reinterpret_cast<const PyArrayDescr1_Proxy *>(ptr);
+}
+
+inline const PyArrayDescr2_Proxy *array_descriptor2_proxy(const PyObject *ptr) {
+ return reinterpret_cast<const PyArrayDescr2_Proxy *>(ptr);
+}
+
inline bool check_flags(const void *ptr, int flag) {
return (flag == (array_proxy(ptr)->flags & flag));
}
@@ -354,7 +450,7 @@ struct array_info<std::array<T, N>> {
}
static constexpr auto extents = const_name<array_info<T>::is_array>(
- concat(const_name<N>(), array_info<T>::extents), const_name<N>());
+ ::pybind11::detail::concat(const_name<N>(), array_info<T>::extents), const_name<N>());
};
// For numpy we have special handling for arrays of characters, so we don't include
// the size in the array extents.
@@ -593,10 +689,32 @@ public:
}
/// Size of the data type in bytes.
+#ifdef PYBIND11_NUMPY_1_ONLY
ssize_t itemsize() const { return detail::array_descriptor_proxy(m_ptr)->elsize; }
+#else
+ ssize_t itemsize() const {
+ if (detail::npy_api::get().PyArray_RUNTIME_VERSION_ < 0x12) {
+ return detail::array_descriptor1_proxy(m_ptr)->elsize;
+ }
+ return detail::array_descriptor2_proxy(m_ptr)->elsize;
+ }
+#endif
/// Returns true for structured data types.
+#ifdef PYBIND11_NUMPY_1_ONLY
bool has_fields() const { return detail::array_descriptor_proxy(m_ptr)->names != nullptr; }
+#else
+ bool has_fields() const {
+ if (detail::npy_api::get().PyArray_RUNTIME_VERSION_ < 0x12) {
+ return detail::array_descriptor1_proxy(m_ptr)->names != nullptr;
+ }
+ const auto *proxy = detail::array_descriptor2_proxy(m_ptr);
+ if (proxy->type_num < 0 || proxy->type_num >= 2056) {
+ return false;
+ }
+ return proxy->names != nullptr;
+ }
+#endif
/// Single-character code for dtype's kind.
/// For example, floating point types are 'f' and integral types are 'i'.
@@ -622,20 +740,39 @@ public:
/// Single character for byteorder
char byteorder() const { return detail::array_descriptor_proxy(m_ptr)->byteorder; }
- /// Alignment of the data type
+/// Alignment of the data type
+#ifdef PYBIND11_NUMPY_1_ONLY
int alignment() const { return detail::array_descriptor_proxy(m_ptr)->alignment; }
+#else
+ ssize_t alignment() const {
+ if (detail::npy_api::get().PyArray_RUNTIME_VERSION_ < 0x12) {
+ return detail::array_descriptor1_proxy(m_ptr)->alignment;
+ }
+ return detail::array_descriptor2_proxy(m_ptr)->alignment;
+ }
+#endif
- /// Flags for the array descriptor
+/// Flags for the array descriptor
+#ifdef PYBIND11_NUMPY_1_ONLY
char flags() const { return detail::array_descriptor_proxy(m_ptr)->flags; }
+#else
+ std::uint64_t flags() const {
+ if (detail::npy_api::get().PyArray_RUNTIME_VERSION_ < 0x12) {
+ return (unsigned char) detail::array_descriptor1_proxy(m_ptr)->flags;
+ }
+ return detail::array_descriptor2_proxy(m_ptr)->flags;
+ }
+#endif
private:
- static object _dtype_from_pep3118() {
- static PyObject *obj = module_::import("numpy.core._internal")
- .attr("_dtype_from_pep3118")
- .cast<object>()
- .release()
- .ptr();
- return reinterpret_borrow<object>(obj);
+ static object &_dtype_from_pep3118() {
+ PYBIND11_CONSTINIT static gil_safe_call_once_and_store<object> storage;
+ return storage
+ .call_once_and_store_result([]() {
+ return detail::import_numpy_core_submodule("_internal")
+ .attr("_dtype_from_pep3118");
+ })
+ .get_stored();
}
dtype strip_padding(ssize_t itemsize) {
@@ -792,9 +929,7 @@ public:
}
/// Byte size of a single element
- ssize_t itemsize() const {
- return detail::array_descriptor_proxy(detail::array_proxy(m_ptr)->descr)->elsize;
- }
+ ssize_t itemsize() const { return dtype().itemsize(); }
/// Total number of bytes
ssize_t nbytes() const { return size() * itemsize(); }
@@ -1012,7 +1147,7 @@ protected:
/// Create array from any object -- always returns a new reference
static PyObject *raw_array(PyObject *ptr, int ExtraFlags = 0) {
if (ptr == nullptr) {
- PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array from a nullptr");
+ set_error(PyExc_ValueError, "cannot create a pybind11::array from a nullptr");
return nullptr;
}
return detail::npy_api::get().PyArray_FromAny_(
@@ -1159,7 +1294,7 @@ protected:
/// Create array from any object -- always returns a new reference
static PyObject *raw_array_t(PyObject *ptr) {
if (ptr == nullptr) {
- PyErr_SetString(PyExc_ValueError, "cannot create a pybind11::array_t from a nullptr");
+ set_error(PyExc_ValueError, "cannot create a pybind11::array_t from a nullptr");
return nullptr;
}
return detail::npy_api::get().PyArray_FromAny_(ptr,
diff --git a/contrib/libs/pybind11/include/pybind11/pybind11.h b/contrib/libs/pybind11/include/pybind11/pybind11.h
index cd30063303..ffbf4db39a 100644
--- a/contrib/libs/pybind11/include/pybind11/pybind11.h
+++ b/contrib/libs/pybind11/include/pybind11/pybind11.h
@@ -14,7 +14,9 @@
#include "detail/init.h"
#include "attr.h"
#include "gil.h"
+#include "gil_safe_call_once.h"
#include "options.h"
+#include "typing.h"
#include <cstdlib>
#include <cstring>
@@ -52,6 +54,47 @@ PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail)
+inline std::string replace_newlines_and_squash(const char *text) {
+ const char *whitespaces = " \t\n\r\f\v";
+ std::string result(text);
+ bool previous_is_whitespace = false;
+
+ if (result.size() >= 2) {
+ // Do not modify string representations
+ char first_char = result[0];
+ char last_char = result[result.size() - 1];
+ if (first_char == last_char && first_char == '\'') {
+ return result;
+ }
+ }
+ result.clear();
+
+ // Replace characters in whitespaces array with spaces and squash consecutive spaces
+ while (*text != '\0') {
+ if (std::strchr(whitespaces, *text)) {
+ if (!previous_is_whitespace) {
+ result += ' ';
+ previous_is_whitespace = true;
+ }
+ } else {
+ result += *text;
+ previous_is_whitespace = false;
+ }
+ ++text;
+ }
+
+ // Strip leading and trailing whitespaces
+ const size_t str_begin = result.find_first_not_of(whitespaces);
+ if (str_begin == std::string::npos) {
+ return "";
+ }
+
+ const size_t str_end = result.find_last_not_of(whitespaces);
+ const size_t str_range = str_end - str_begin + 1;
+
+ return result.substr(str_begin, str_range);
+}
+
// Apply all the extensions translators from a list
// Return true if one of the translators completed without raising an exception
// itself. Return of false indicates that if there are other translators
@@ -424,7 +467,7 @@ protected:
// Write default value if available.
if (!is_starred && arg_index < rec->args.size() && rec->args[arg_index].descr) {
signature += " = ";
- signature += rec->args[arg_index].descr;
+ signature += detail::replace_newlines_and_squash(rec->args[arg_index].descr);
}
// Separator for positional-only arguments (placed after the
// argument, rather than before like *
@@ -449,9 +492,7 @@ protected:
signature += rec->scope.attr("__module__").cast<std::string>() + "."
+ rec->scope.attr("__qualname__").cast<std::string>();
} else {
- std::string tname(t->name());
- detail::clean_type_id(tname);
- signature += tname;
+ signature += detail::quote_cpp_type_name(detail::clean_type_id(t->name()));
}
} else {
signature += c;
@@ -689,7 +730,7 @@ protected:
/* Iterator over the list of potentially admissible overloads */
const function_record *overloads = reinterpret_cast<function_record *>(
PyCapsule_GetPointer(self, get_function_record_capsule_name())),
- *it = overloads;
+ *current_overload = overloads;
assert(overloads != nullptr);
/* Need to know how many arguments + keyword arguments there are to pick the right
@@ -703,9 +744,8 @@ protected:
if (overloads->is_constructor) {
if (!parent
|| !PyObject_TypeCheck(parent.ptr(), (PyTypeObject *) overloads->scope.ptr())) {
- PyErr_SetString(
- PyExc_TypeError,
- "__init__(self, ...) called with invalid or missing `self` argument");
+ set_error(PyExc_TypeError,
+ "__init__(self, ...) called with invalid or missing `self` argument");
return nullptr;
}
@@ -728,9 +768,10 @@ protected:
std::vector<function_call> second_pass;
// However, if there are no overloads, we can just skip the no-convert pass entirely
- const bool overloaded = it != nullptr && it->next != nullptr;
+ const bool overloaded
+ = current_overload != nullptr && current_overload->next != nullptr;
- for (; it != nullptr; it = it->next) {
+ for (; current_overload != nullptr; current_overload = current_overload->next) {
/* For each overload:
1. Copy all positional arguments we were given, also checking to make sure that
@@ -751,7 +792,7 @@ protected:
a result other than PYBIND11_TRY_NEXT_OVERLOAD.
*/
- const function_record &func = *it;
+ const function_record &func = *current_overload;
size_t num_args = func.nargs; // Number of positional arguments that we need
if (func.has_args) {
--num_args; // (but don't count py::args
@@ -989,10 +1030,10 @@ protected:
}
if (result.ptr() != PYBIND11_TRY_NEXT_OVERLOAD) {
- // The error reporting logic below expects 'it' to be valid, as it would be
- // if we'd encountered this failure in the first-pass loop.
+ // The error reporting logic below expects 'current_overload' to be valid,
+ // as it would be if we'd encountered this failure in the first-pass loop.
if (!result) {
- it = &call.func;
+ current_overload = &call.func;
}
break;
}
@@ -1016,7 +1057,7 @@ protected:
A translator may choose to do one of the following:
- - catch the exception and call PyErr_SetString or PyErr_SetObject
+ - catch the exception and call py::set_error()
to set a standard (or custom) Python exception, or
- do nothing and let the exception fall through to the next translator, or
- delegate translation to the next translator by throwing a new type of exception.
@@ -1032,8 +1073,7 @@ protected:
return nullptr;
}
- PyErr_SetString(PyExc_SystemError,
- "Exception escaped from default exception translator!");
+ set_error(PyExc_SystemError, "Exception escaped from default exception translator!");
return nullptr;
}
@@ -1111,7 +1151,7 @@ protected:
}
msg += "kwargs: ";
bool first = true;
- for (auto kwarg : kwargs) {
+ for (const auto &kwarg : kwargs) {
if (first) {
first = false;
} else {
@@ -1136,13 +1176,14 @@ protected:
return nullptr;
}
#endif
- PyErr_SetString(PyExc_TypeError, msg.c_str());
+ set_error(PyExc_TypeError, msg.c_str());
return nullptr;
}
if (!result) {
std::string msg = "Unable to convert function return value to a "
"Python type! The signature was\n\t";
- msg += it->signature;
+ assert(current_overload != nullptr);
+ msg += current_overload->signature;
append_note_if_missing_header_is_suspected(msg);
#if PY_VERSION_HEX >= 0x03030000
// Attach additional error info to the exception if supported
@@ -1151,7 +1192,7 @@ protected:
return nullptr;
}
#endif
- PyErr_SetString(PyExc_TypeError, msg.c_str());
+ set_error(PyExc_TypeError, msg.c_str());
return nullptr;
}
if (overloads->is_constructor && !self_value_and_holder.holder_constructed()) {
@@ -1162,6 +1203,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
class module_ : public object {
public:
@@ -1305,6 +1355,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),
// 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.
@@ -2008,7 +2067,7 @@ struct enum_base {
object type_name = type::handle_of(arg).attr("__name__");
return pybind11::str("{}.{}").format(std::move(type_name), enum_name(arg));
},
- name("name"),
+ name("__str__"),
is_method(m_base));
if (options::show_enum_members_docstring()) {
@@ -2429,7 +2488,7 @@ iterator make_iterator_impl(Iterator first, Sentinel last, Extra &&...extra) {
Policy);
}
- return cast(state{first, last, true});
+ return cast(state{std::forward<Iterator>(first), std::forward<Sentinel>(last), true});
}
PYBIND11_NAMESPACE_END(detail)
@@ -2440,13 +2499,15 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
typename Sentinel,
typename ValueType = typename detail::iterator_access<Iterator>::result_type,
typename... Extra>
-iterator make_iterator(Iterator first, Sentinel last, Extra &&...extra) {
+typing::Iterator<ValueType> make_iterator(Iterator first, Sentinel last, Extra &&...extra) {
return detail::make_iterator_impl<detail::iterator_access<Iterator>,
Policy,
Iterator,
Sentinel,
ValueType,
- Extra...>(first, last, std::forward<Extra>(extra)...);
+ Extra...>(std::forward<Iterator>(first),
+ std::forward<Sentinel>(last),
+ std::forward<Extra>(extra)...);
}
/// Makes a python iterator over the keys (`.first`) of a iterator over pairs from a
@@ -2456,13 +2517,15 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
typename Sentinel,
typename KeyType = typename detail::iterator_key_access<Iterator>::result_type,
typename... Extra>
-iterator make_key_iterator(Iterator first, Sentinel last, Extra &&...extra) {
+typing::Iterator<KeyType> make_key_iterator(Iterator first, Sentinel last, Extra &&...extra) {
return detail::make_iterator_impl<detail::iterator_key_access<Iterator>,
Policy,
Iterator,
Sentinel,
KeyType,
- Extra...>(first, last, std::forward<Extra>(extra)...);
+ Extra...>(std::forward<Iterator>(first),
+ std::forward<Sentinel>(last),
+ std::forward<Extra>(extra)...);
}
/// Makes a python iterator over the values (`.second`) of a iterator over pairs from a
@@ -2472,21 +2535,25 @@ template <return_value_policy Policy = return_value_policy::reference_internal,
typename Sentinel,
typename ValueType = typename detail::iterator_value_access<Iterator>::result_type,
typename... Extra>
-iterator make_value_iterator(Iterator first, Sentinel last, Extra &&...extra) {
+typing::Iterator<ValueType> make_value_iterator(Iterator first, Sentinel last, Extra &&...extra) {
return detail::make_iterator_impl<detail::iterator_value_access<Iterator>,
Policy,
Iterator,
Sentinel,
ValueType,
- Extra...>(first, last, std::forward<Extra>(extra)...);
+ Extra...>(std::forward<Iterator>(first),
+ std::forward<Sentinel>(last),
+ std::forward<Extra>(extra)...);
}
/// Makes an iterator over values of an stl container or other container supporting
/// `std::begin()`/`std::end()`
template <return_value_policy Policy = return_value_policy::reference_internal,
typename Type,
+ typename ValueType = typename detail::iterator_access<
+ decltype(std::begin(std::declval<Type &>()))>::result_type,
typename... Extra>
-iterator make_iterator(Type &value, Extra &&...extra) {
+typing::Iterator<ValueType> make_iterator(Type &value, Extra &&...extra) {
return make_iterator<Policy>(
std::begin(value), std::end(value), std::forward<Extra>(extra)...);
}
@@ -2495,8 +2562,10 @@ iterator make_iterator(Type &value, Extra &&...extra) {
/// `std::begin()`/`std::end()`
template <return_value_policy Policy = return_value_policy::reference_internal,
typename Type,
+ typename KeyType = typename detail::iterator_key_access<
+ decltype(std::begin(std::declval<Type &>()))>::result_type,
typename... Extra>
-iterator make_key_iterator(Type &value, Extra &&...extra) {
+typing::Iterator<KeyType> make_key_iterator(Type &value, Extra &&...extra) {
return make_key_iterator<Policy>(
std::begin(value), std::end(value), std::forward<Extra>(extra)...);
}
@@ -2505,8 +2574,10 @@ iterator make_key_iterator(Type &value, Extra &&...extra) {
/// `std::begin()`/`std::end()`
template <return_value_policy Policy = return_value_policy::reference_internal,
typename Type,
+ typename ValueType = typename detail::iterator_value_access<
+ decltype(std::begin(std::declval<Type &>()))>::result_type,
typename... Extra>
-iterator make_value_iterator(Type &value, Extra &&...extra) {
+typing::Iterator<ValueType> make_value_iterator(Type &value, Extra &&...extra) {
return make_value_iterator<Policy>(
std::begin(value), std::end(value), std::forward<Extra>(extra)...);
}
@@ -2562,7 +2633,7 @@ inline void register_local_exception_translator(ExceptionTranslator &&translator
/**
* Wrapper to generate a new Python exception type.
*
- * This should only be used with PyErr_SetString for now.
+ * This should only be used with py::set_error() for now.
* It is not (yet) possible to use as a py::base.
* Template type argument is reserved for future use.
*/
@@ -2583,27 +2654,25 @@ public:
}
// Sets the current python exception to this exception object with the given message
- void operator()(const char *message) { PyErr_SetString(m_ptr, message); }
+ PYBIND11_DEPRECATED("Please use py::set_error() instead "
+ "(https://github.com/pybind/pybind11/pull/4772)")
+ void operator()(const char *message) const { set_error(*this, message); }
};
PYBIND11_NAMESPACE_BEGIN(detail)
-// Returns a reference to a function-local static exception object used in the simple
-// register_exception approach below. (It would be simpler to have the static local variable
-// directly in register_exception, but that makes clang <3.5 segfault - issue #1349).
-template <typename CppException>
-exception<CppException> &get_exception_object() {
- static exception<CppException> ex;
- return ex;
-}
+
+template <>
+struct handle_type_name<exception<void>> {
+ static constexpr auto name = const_name("Exception");
+};
// Helper function for register_exception and register_local_exception
template <typename CppException>
exception<CppException> &
register_exception_impl(handle scope, const char *name, handle base, bool isLocal) {
- auto &ex = detail::get_exception_object<CppException>();
- if (!ex) {
- ex = exception<CppException>(scope, name, base);
- }
+ PYBIND11_CONSTINIT static gil_safe_call_once_and_store<exception<CppException>> exc_storage;
+ exc_storage.call_once_and_store_result(
+ [&]() { return exception<CppException>(scope, name, base); });
auto register_func
= isLocal ? &register_local_exception_translator : &register_exception_translator;
@@ -2615,10 +2684,10 @@ register_exception_impl(handle scope, const char *name, handle base, bool isLoca
try {
std::rethrow_exception(p);
} catch (const CppException &e) {
- detail::get_exception_object<CppException>()(e.what());
+ set_error(exc_storage.get_stored(), e.what());
}
});
- return ex;
+ return exc_storage.get_stored();
}
PYBIND11_NAMESPACE_END(detail)
@@ -2737,7 +2806,11 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) {
PyObject *locals = PyEval_GetLocals();
if (locals != nullptr) {
+# if PY_VERSION_HEX >= 0x030b0000
+ PyObject *co_varnames = PyCode_GetVarnames(f_code);
+# else
PyObject *co_varnames = PyObject_GetAttrString((PyObject *) f_code, "co_varnames");
+# endif
PyObject *self_arg = PyTuple_GET_ITEM(co_varnames, 0);
Py_DECREF(co_varnames);
PyObject *self_caller = dict_getitem(locals, self_arg);
diff --git a/contrib/libs/pybind11/include/pybind11/pytypes.h b/contrib/libs/pybind11/include/pybind11/pytypes.h
index 6c255c6cde..e48ecf676f 100644
--- a/contrib/libs/pybind11/include/pybind11/pytypes.h
+++ b/contrib/libs/pybind11/include/pybind11/pytypes.h
@@ -59,6 +59,7 @@ struct sequence_item;
struct list_item;
struct tuple_item;
} // namespace accessor_policies
+// PLEASE KEEP handle_type_name SPECIALIZATIONS IN SYNC.
using obj_attr_accessor = accessor<accessor_policies::obj_attr>;
using str_attr_accessor = accessor<accessor_policies::str_attr>;
using item_accessor = accessor<accessor_policies::generic_item>;
@@ -310,19 +311,19 @@ private:
"https://pybind11.readthedocs.io/en/stable/advanced/"
"misc.html#common-sources-of-global-interpreter-lock-errors for debugging advice.\n"
"If you are convinced there is no bug in your code, you can #define "
- "PYBIND11_NO_ASSERT_GIL_HELD_INCREF_DECREF"
+ "PYBIND11_NO_ASSERT_GIL_HELD_INCREF_DECREF "
"to disable this check. In that case you have to ensure this #define is consistently "
"used for all translation units linked into a given pybind11 extension, otherwise "
"there will be ODR violations.",
function_name.c_str());
- fflush(stderr);
if (Py_TYPE(m_ptr)->tp_name != nullptr) {
fprintf(stderr,
- "The failing %s call was triggered on a %s object.\n",
+ " The failing %s call was triggered on a %s object.",
function_name.c_str(),
Py_TYPE(m_ptr)->tp_name);
- fflush(stderr);
}
+ fprintf(stderr, "\n");
+ fflush(stderr);
throw std::runtime_error(function_name + " PyGILState_Check() failure.");
}
#endif
@@ -339,6 +340,14 @@ public:
#endif
};
+inline void set_error(const handle &type, const char *message) {
+ PyErr_SetString(type.ptr(), message);
+}
+
+inline void set_error(const handle &type, const handle &value) {
+ PyErr_SetObject(type.ptr(), value.ptr());
+}
+
/** \rst
Holds a reference to a Python object (with reference counting)
@@ -1639,7 +1648,15 @@ inline namespace literals {
/** \rst
String literal version of `str`
\endrst */
-inline str operator"" _s(const char *s, size_t size) { return {s, size}; }
+inline str
+#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5
+operator"" _s // gcc 4.8.5 insists on having a space (hard error).
+#else
+operator""_s // clang 17 generates a deprecation warning if there is a space.
+#endif
+ (const char *s, size_t size) {
+ return {s, size};
+}
} // namespace literals
/// \addtogroup pytypes
diff --git a/contrib/libs/pybind11/include/pybind11/typing.h b/contrib/libs/pybind11/include/pybind11/typing.h
new file mode 100644
index 0000000000..bc275fc50b
--- /dev/null
+++ b/contrib/libs/pybind11/include/pybind11/typing.h
@@ -0,0 +1,125 @@
+/*
+ pybind11/typing.h: Convenience wrapper classes for basic Python types
+ with more explicit annotations.
+
+ Copyright (c) 2023 Dustin Spicuzza <dustin@virtualroadside.com>
+
+ 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"
+
+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 <typename... Types>
+class Tuple : public tuple {
+ using tuple::tuple;
+};
+
+template <typename K, typename V>
+class Dict : public dict {
+ using dict::dict;
+};
+
+template <typename T>
+class List : public list {
+ using list::list;
+};
+
+template <typename T>
+class Set : public set {
+ using set::set;
+};
+
+template <typename T>
+class Iterable : public iterable {
+ using iterable::iterable;
+};
+
+template <typename T>
+class Iterator : public iterator {
+ using iterator::iterator;
+};
+
+template <typename Signature>
+class Callable;
+
+template <typename Return, typename... Args>
+class Callable<Return(Args...)> : public function {
+ using function::function;
+};
+
+PYBIND11_NAMESPACE_END(typing)
+
+PYBIND11_NAMESPACE_BEGIN(detail)
+
+template <typename... Types>
+struct handle_type_name<typing::Tuple<Types...>> {
+ static constexpr auto name = const_name("tuple[")
+ + ::pybind11::detail::concat(make_caster<Types>::name...)
+ + const_name("]");
+};
+
+template <>
+struct handle_type_name<typing::Tuple<>> {
+ // PEP 484 specifies this syntax for an empty tuple
+ static constexpr auto name = const_name("tuple[()]");
+};
+
+template <typename T>
+struct handle_type_name<typing::Tuple<T, ellipsis>> {
+ // PEP 484 specifies this syntax for a variable-length tuple
+ static constexpr auto name
+ = const_name("tuple[") + make_caster<T>::name + const_name(", ...]");
+};
+
+template <typename K, typename V>
+struct handle_type_name<typing::Dict<K, V>> {
+ static constexpr auto name = const_name("dict[") + make_caster<K>::name + const_name(", ")
+ + make_caster<V>::name + const_name("]");
+};
+
+template <typename T>
+struct handle_type_name<typing::List<T>> {
+ static constexpr auto name = const_name("list[") + make_caster<T>::name + const_name("]");
+};
+
+template <typename T>
+struct handle_type_name<typing::Set<T>> {
+ static constexpr auto name = const_name("set[") + make_caster<T>::name + const_name("]");
+};
+
+template <typename T>
+struct handle_type_name<typing::Iterable<T>> {
+ static constexpr auto name = const_name("Iterable[") + make_caster<T>::name + const_name("]");
+};
+
+template <typename T>
+struct handle_type_name<typing::Iterator<T>> {
+ static constexpr auto name = const_name("Iterator[") + make_caster<T>::name + const_name("]");
+};
+
+template <typename Return, typename... Args>
+struct handle_type_name<typing::Callable<Return(Args...)>> {
+ using retval_type = conditional_t<std::is_same<Return, void>::value, void_type, Return>;
+ static constexpr auto name
+ = const_name("Callable[[") + ::pybind11::detail::concat(make_caster<Args>::name...)
+ + const_name("], ") + make_caster<retval_type>::name + const_name("]");
+};
+
+PYBIND11_NAMESPACE_END(detail)
+PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
diff --git a/contrib/libs/pybind11/ya.make b/contrib/libs/pybind11/ya.make
index 95a7f21ea3..8e7f534a2c 100644
--- a/contrib/libs/pybind11/ya.make
+++ b/contrib/libs/pybind11/ya.make
@@ -6,9 +6,9 @@ LICENSE(BSD-3-Clause)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(2.11.1)
+VERSION(2.12.0)
-ORIGINAL_SOURCE(https://github.com/pybind/pybind11/archive/v2.11.1.tar.gz)
+ORIGINAL_SOURCE(https://github.com/pybind/pybind11/archive/v2.12.0.tar.gz)
ADDINCL(
GLOBAL contrib/libs/pybind11/include
diff --git a/contrib/python/matplotlib/py3/matplotlib/backends/backend_webagg.py b/contrib/python/matplotlib/py3/matplotlib/backends/backend_webagg.py
index 14c0b525fb..030ab8519b 100644
--- a/contrib/python/matplotlib/py3/matplotlib/backends/backend_webagg.py
+++ b/contrib/python/matplotlib/py3/matplotlib/backends/backend_webagg.py
@@ -19,6 +19,10 @@ import random
import sys
import signal
import threading
+import tempfile
+import os
+
+from library.python.resource import iteritems
try:
import tornado
@@ -177,12 +181,14 @@ class WebAggApplication(tornado.web.Application):
assert url_prefix[0] == '/' and url_prefix[-1] != '/', \
'url_prefix must start with a "/" and not end with one.'
+ self._store_resources()
+ package_resources_abspath = os.path.join(self._stored_package_path, core.FigureManagerWebAgg.get_static_file_path())
super().__init__(
[
# Static files for the CSS and JS
(url_prefix + r'/_static/(.*)',
tornado.web.StaticFileHandler,
- {'path': core.FigureManagerWebAgg.get_static_file_path()}),
+ {'path': package_resources_abspath}),
# Static images for the toolbar
(url_prefix + r'/_images/(.*)',
@@ -210,7 +216,19 @@ class WebAggApplication(tornado.web.Application):
(url_prefix + r'/([0-9]+)/download.([a-z0-9.]+)',
self.Download),
],
- template_path=core.FigureManagerWebAgg.get_static_file_path())
+ template_path=package_resources_abspath)
+
+ def _store_resources(self):
+ self._stored_package_dir = tempfile.TemporaryDirectory()
+ self._stored_package_path = self._stored_package_dir.name
+ package_path = os.path.join(*"contrib/python/matplotlib/py3/".split("/"))
+ for key, data in iteritems(prefix="resfs/file/" + package_path, strip_prefix=True):
+ path = os.path.join(self._stored_package_path, *os.path.split(package_path), *os.path.split(key))
+ dir = os.path.dirname(path)
+ if not os.path.exists(dir):
+ os.makedirs(dir)
+ with open(path, "wb") as file:
+ file.write(data)
@classmethod
def initialize(cls, url_prefix='', port=None, address=None):