diff options
author | robot-piglet <robot-piglet@yandex-team.com> | 2024-08-28 10:13:37 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2024-08-28 10:56:21 +0300 |
commit | 5d69584883acf76288028d9eda6f5154bad71f03 (patch) | |
tree | b4497ba6497373d6b65846161ff807c653231db7 | |
parent | b6ed4760624656bf72a40cf703fadf564d5a5a37 (diff) | |
download | ydb-5d69584883acf76288028d9eda6f5154bad71f03.tar.gz |
Intermediate changes
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/cast.h | 11 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/detail/common.h | 20 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/detail/init.h | 6 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/detail/internals.h | 29 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h | 64 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/detail/value_and_holder.h | 77 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h | 11 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/numpy.h | 8 | ||||
-rw-r--r-- | contrib/libs/pybind11/include/pybind11/typing.h | 9 | ||||
-rw-r--r-- | contrib/libs/pybind11/ya.make | 4 | ||||
-rw-r--r-- | yt/python/yt/common.py | 22 |
11 files changed, 172 insertions, 89 deletions
diff --git a/contrib/libs/pybind11/include/pybind11/cast.h b/contrib/libs/pybind11/include/pybind11/cast.h index b66b8dbf94..81c355f2e2 100644 --- a/contrib/libs/pybind11/include/pybind11/cast.h +++ b/contrib/libs/pybind11/include/pybind11/cast.h @@ -767,6 +767,13 @@ class type_caster<std::pair<T1, T2>> : public tuple_caster<std::pair, T1, T2> {} template <typename... Ts> class type_caster<std::tuple<Ts...>> : public tuple_caster<std::tuple, Ts...> {}; +template <> +class type_caster<std::tuple<>> : public tuple_caster<std::tuple> { +public: + // PEP 484 specifies this syntax for an empty tuple + static constexpr auto name = const_name("tuple[()]"); +}; + /// Helper class which abstracts away certain actions. Users can provide specializations for /// custom holders, but it's only necessary if the type has a non-standard interface. template <typename T> @@ -814,11 +821,11 @@ protected: } } - bool load_value(value_and_holder &&v_h) { + void load_value(value_and_holder &&v_h) { if (v_h.holder_constructed()) { value = v_h.value_ptr(); holder = v_h.template holder<holder_type>(); - return true; + return; } throw cast_error("Unable to cast from non-held to held instance (T& to Holder<T>) " #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) diff --git a/contrib/libs/pybind11/include/pybind11/detail/common.h b/contrib/libs/pybind11/include/pybind11/detail/common.h index e111ed73ba..66c9d3b578 100644 --- a/contrib/libs/pybind11/include/pybind11/detail/common.h +++ b/contrib/libs/pybind11/include/pybind11/detail/common.h @@ -11,11 +11,11 @@ #define PYBIND11_VERSION_MAJOR 2 #define PYBIND11_VERSION_MINOR 13 -#define PYBIND11_VERSION_PATCH 1 +#define PYBIND11_VERSION_PATCH 3 // Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html // Additional convention: 0xD = dev -#define PYBIND11_VERSION_HEX 0x020D0100 +#define PYBIND11_VERSION_HEX 0x020D0300 // Define some generic pybind11 helper macros for warning management. // @@ -510,6 +510,22 @@ PYBIND11_WARNING_POP return "Hello, World!"; }); } + + The third macro argument is optional (available since 2.13.0), and can be used to + mark the extension module as safe to run without the GIL under a free-threaded CPython + interpreter. Passing this argument has no effect on other interpreters. + + .. code-block:: cpp + + PYBIND11_MODULE(example, m, py::mod_gil_not_used()) { + m.doc() = "pybind11 example module safe to run without the GIL"; + + // Add bindings here + m.def("foo", []() { + return "Hello, Free-threaded World!"; + }); + } + \endrst */ #define PYBIND11_MODULE(name, variable, ...) \ static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name) \ diff --git a/contrib/libs/pybind11/include/pybind11/detail/init.h b/contrib/libs/pybind11/include/pybind11/detail/init.h index 89a471f5b4..27834669bb 100644 --- a/contrib/libs/pybind11/include/pybind11/detail/init.h +++ b/contrib/libs/pybind11/include/pybind11/detail/init.h @@ -128,11 +128,13 @@ void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) { // the holder and destruction happens when we leave the C++ scope, and the holder // class gets to handle the destruction however it likes. v_h.value_ptr() = ptr; - v_h.set_instance_registered(true); // To prevent init_instance from registering it - v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder + v_h.set_instance_registered(true); // Trick to prevent init_instance from registering it + // DANGER ZONE BEGIN: exceptions will leave v_h in an invalid state. + v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null v_h.set_instance_registered(false); + // DANGER ZONE END. construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(*ptr)); } else { diff --git a/contrib/libs/pybind11/include/pybind11/detail/internals.h b/contrib/libs/pybind11/include/pybind11/detail/internals.h index f6f15b6494..6a04bb2194 100644 --- a/contrib/libs/pybind11/include/pybind11/detail/internals.h +++ b/contrib/libs/pybind11/include/pybind11/detail/internals.h @@ -168,20 +168,35 @@ struct override_hash { using instance_map = std::unordered_multimap<const void *, instance *>; +#ifdef Py_GIL_DISABLED +// Wrapper around PyMutex to provide BasicLockable semantics +class pymutex { + PyMutex mutex; + +public: + pymutex() : mutex({}) {} + void lock() { PyMutex_Lock(&mutex); } + void unlock() { PyMutex_Unlock(&mutex); } +}; + // Instance map shards are used to reduce mutex contention in free-threaded Python. struct instance_map_shard { - std::mutex mutex; instance_map registered_instances; + pymutex mutex; // alignas(64) would be better, but causes compile errors in macOS before 10.14 (see #5200) - char padding[64 - (sizeof(std::mutex) + sizeof(instance_map)) % 64]; + char padding[64 - (sizeof(instance_map) + sizeof(pymutex)) % 64]; }; +static_assert(sizeof(instance_map_shard) % 64 == 0, + "instance_map_shard size is not a multiple of 64 bytes"); +#endif + /// Internal data structure used to track registered instances and types. /// Whenever binary incompatible changes are made to this structure, /// `PYBIND11_INTERNALS_VERSION` must be incremented. struct internals { #ifdef Py_GIL_DISABLED - std::mutex mutex; + pymutex mutex; #endif // std::type_index -> pybind11's type information type_map<type_info *> registered_types_cpp; @@ -578,7 +593,7 @@ PYBIND11_NOINLINE internals &get_internals() { } #endif internals_ptr->istate = tstate->interp; - state_dict[PYBIND11_INTERNALS_ID] = capsule(internals_pp); + state_dict[PYBIND11_INTERNALS_ID] = capsule(reinterpret_cast<void *>(internals_pp)); internals_ptr->registered_exception_translators.push_front(&translate_exception); internals_ptr->static_property_type = make_static_property_type(); internals_ptr->default_metaclass = make_default_metaclass(); @@ -654,7 +669,7 @@ inline local_internals &get_local_internals() { } #ifdef Py_GIL_DISABLED -# define PYBIND11_LOCK_INTERNALS(internals) std::unique_lock<std::mutex> lock((internals).mutex) +# define PYBIND11_LOCK_INTERNALS(internals) std::unique_lock<pymutex> lock((internals).mutex) #else # define PYBIND11_LOCK_INTERNALS(internals) #endif @@ -691,7 +706,7 @@ inline auto with_instance_map(const void *ptr, auto idx = static_cast<size_t>(hash & internals.instance_shards_mask); auto &shard = internals.instance_shards[idx]; - std::unique_lock<std::mutex> lock(shard.mutex); + std::unique_lock<pymutex> lock(shard.mutex); return cb(shard.registered_instances); #else (void) ptr; @@ -707,7 +722,7 @@ inline size_t num_registered_instances() { size_t count = 0; for (size_t i = 0; i <= internals.instance_shards_mask; ++i) { auto &shard = internals.instance_shards[i]; - std::unique_lock<std::mutex> lock(shard.mutex); + std::unique_lock<pymutex> lock(shard.mutex); count += shard.registered_instances.size(); } return count; 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 1dbc5eed1e..53366edbe4 100644 --- a/contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h +++ b/contrib/libs/pybind11/include/pybind11/detail/type_caster_base.h @@ -14,6 +14,7 @@ #include "descr.h" #include "internals.h" #include "typeid.h" +#include "value_and_holder.h" #include <cstdint> #include <iterator> @@ -260,67 +261,6 @@ PYBIND11_NOINLINE handle find_registered_python_instance(void *src, }); } -struct value_and_holder { - instance *inst = nullptr; - size_t index = 0u; - const detail::type_info *type = nullptr; - void **vh = nullptr; - - // Main constructor for a found value/holder: - value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index) - : inst{i}, index{index}, type{type}, - vh{inst->simple_layout ? inst->simple_value_holder - : &inst->nonsimple.values_and_holders[vpos]} {} - - // Default constructor (used to signal a value-and-holder not found by get_value_and_holder()) - value_and_holder() = default; - - // Used for past-the-end iterator - explicit value_and_holder(size_t index) : index{index} {} - - template <typename V = void> - V *&value_ptr() const { - return reinterpret_cast<V *&>(vh[0]); - } - // True if this `value_and_holder` has a non-null value pointer - explicit operator bool() const { return value_ptr() != nullptr; } - - template <typename H> - H &holder() const { - return reinterpret_cast<H &>(vh[1]); - } - bool holder_constructed() const { - return inst->simple_layout - ? inst->simple_holder_constructed - : (inst->nonsimple.status[index] & instance::status_holder_constructed) != 0u; - } - // NOLINTNEXTLINE(readability-make-member-function-const) - void set_holder_constructed(bool v = true) { - if (inst->simple_layout) { - inst->simple_holder_constructed = v; - } else if (v) { - inst->nonsimple.status[index] |= instance::status_holder_constructed; - } else { - inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_holder_constructed; - } - } - bool instance_registered() const { - return inst->simple_layout - ? inst->simple_instance_registered - : ((inst->nonsimple.status[index] & instance::status_instance_registered) != 0); - } - // NOLINTNEXTLINE(readability-make-member-function-const) - void set_instance_registered(bool v = true) { - if (inst->simple_layout) { - inst->simple_instance_registered = v; - } else if (v) { - inst->nonsimple.status[index] |= instance::status_instance_registered; - } else { - inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_instance_registered; - } - } -}; - // Container for accessing and iterating over an instance's values/holders struct values_and_holders { private: @@ -496,7 +436,7 @@ PYBIND11_NOINLINE void instance::allocate_layout() { // NOLINTNEXTLINE(readability-make-member-function-const) PYBIND11_NOINLINE void instance::deallocate_layout() { if (!simple_layout) { - PyMem_Free(nonsimple.values_and_holders); + PyMem_Free(reinterpret_cast<void *>(nonsimple.values_and_holders)); } } diff --git a/contrib/libs/pybind11/include/pybind11/detail/value_and_holder.h b/contrib/libs/pybind11/include/pybind11/detail/value_and_holder.h new file mode 100644 index 0000000000..ca37d70ad2 --- /dev/null +++ b/contrib/libs/pybind11/include/pybind11/detail/value_and_holder.h @@ -0,0 +1,77 @@ +// Copyright (c) 2016-2024 The Pybind Development Team. +// 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 "common.h" + +#include <cstddef> +#include <typeinfo> + +PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +PYBIND11_NAMESPACE_BEGIN(detail) + +struct value_and_holder { + instance *inst = nullptr; + size_t index = 0u; + const detail::type_info *type = nullptr; + void **vh = nullptr; + + // Main constructor for a found value/holder: + value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index) + : inst{i}, index{index}, type{type}, + vh{inst->simple_layout ? inst->simple_value_holder + : &inst->nonsimple.values_and_holders[vpos]} {} + + // Default constructor (used to signal a value-and-holder not found by get_value_and_holder()) + value_and_holder() = default; + + // Used for past-the-end iterator + explicit value_and_holder(size_t index) : index{index} {} + + template <typename V = void> + V *&value_ptr() const { + return reinterpret_cast<V *&>(vh[0]); + } + // True if this `value_and_holder` has a non-null value pointer + explicit operator bool() const { return value_ptr() != nullptr; } + + template <typename H> + H &holder() const { + return reinterpret_cast<H &>(vh[1]); + } + bool holder_constructed() const { + return inst->simple_layout + ? inst->simple_holder_constructed + : (inst->nonsimple.status[index] & instance::status_holder_constructed) != 0u; + } + // NOLINTNEXTLINE(readability-make-member-function-const) + void set_holder_constructed(bool v = true) { + if (inst->simple_layout) { + inst->simple_holder_constructed = v; + } else if (v) { + inst->nonsimple.status[index] |= instance::status_holder_constructed; + } else { + inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_holder_constructed; + } + } + bool instance_registered() const { + return inst->simple_layout + ? inst->simple_instance_registered + : ((inst->nonsimple.status[index] & instance::status_instance_registered) != 0); + } + // NOLINTNEXTLINE(readability-make-member-function-const) + void set_instance_registered(bool v = true) { + if (inst->simple_layout) { + inst->simple_instance_registered = v; + } else if (v) { + inst->nonsimple.status[index] |= instance::status_instance_registered; + } else { + inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_instance_registered; + } + } +}; + +PYBIND11_NAMESPACE_END(detail) +PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h b/contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h index eaf84d16e8..5f9e1b03c6 100644 --- a/contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h +++ b/contrib/libs/pybind11/include/pybind11/gil_safe_call_once.h @@ -8,6 +8,10 @@ #include <cassert> #include <mutex> +#ifdef Py_GIL_DISABLED +# include <atomic> +#endif + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) // Use the `gil_safe_call_once_and_store` class below instead of the naive @@ -82,7 +86,12 @@ public: private: alignas(T) char storage_[sizeof(T)] = {}; std::once_flag once_flag_ = {}; - bool is_initialized_ = false; +#ifdef Py_GIL_DISABLED + std::atomic_bool +#else + bool +#endif + 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. diff --git a/contrib/libs/pybind11/include/pybind11/numpy.h b/contrib/libs/pybind11/include/pybind11/numpy.h index 67c9a017b9..9892ff56a6 100644 --- a/contrib/libs/pybind11/include/pybind11/numpy.h +++ b/contrib/libs/pybind11/include/pybind11/numpy.h @@ -905,7 +905,11 @@ public: template <typename T> array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle()) - : array(pybind11::dtype::of<T>(), std::move(shape), std::move(strides), ptr, base) {} + : array(pybind11::dtype::of<T>(), + std::move(shape), + std::move(strides), + reinterpret_cast<const void *>(ptr), + base) {} template <typename T> array(ShapeContainer shape, const T *ptr, handle base = handle()) @@ -1990,7 +1994,7 @@ private: // Pointers to values the function was called with; the vectorized ones set here will start // out as array_t<T> pointers, but they will be changed them to T pointers before we make // call the wrapped function. Non-vectorized pointers are left as-is. - std::array<void *, N> params{{&args...}}; + std::array<void *, N> params{{reinterpret_cast<void *>(&args)...}}; // The array of `buffer_info`s of vectorized arguments: std::array<buffer_info, NVectorized> buffers{ diff --git a/contrib/libs/pybind11/include/pybind11/typing.h b/contrib/libs/pybind11/include/pybind11/typing.h index 1442cdc7f1..b0feb9464a 100644 --- a/contrib/libs/pybind11/include/pybind11/typing.h +++ b/contrib/libs/pybind11/include/pybind11/typing.h @@ -14,6 +14,8 @@ #include "cast.h" #include "pytypes.h" +#include <algorithm> + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(typing) @@ -98,7 +100,10 @@ class Never : public none { using none::none; }; -#if defined(__cpp_nontype_template_parameter_class) +#if defined(__cpp_nontype_template_parameter_class) \ + && (/* See #5201 */ !defined(__GNUC__) \ + || (__GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 3))) +# define PYBIND11_TYPING_H_HAS_STRING_LITERAL template <size_t N> struct StringLiteral { constexpr StringLiteral(const char (&str)[N]) { std::copy_n(str, N, name); } @@ -222,7 +227,7 @@ struct handle_type_name<typing::Never> { static constexpr auto name = const_name("Never"); }; -#if defined(__cpp_nontype_template_parameter_class) +#if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL) template <typing::StringLiteral... Literals> struct handle_type_name<typing::Literal<Literals...>> { static constexpr auto name = const_name("Literal[") diff --git a/contrib/libs/pybind11/ya.make b/contrib/libs/pybind11/ya.make index dfc608e618..d690d7c3e0 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.13.1) +VERSION(2.13.3) -ORIGINAL_SOURCE(https://github.com/pybind/pybind11/archive/v2.13.1.tar.gz) +ORIGINAL_SOURCE(https://github.com/pybind/pybind11/archive/v2.13.3.tar.gz) ADDINCL( GLOBAL contrib/libs/pybind11/include diff --git a/yt/python/yt/common.py b/yt/python/yt/common.py index e2c96a80ff..a3c2969125 100644 --- a/yt/python/yt/common.py +++ b/yt/python/yt/common.py @@ -834,30 +834,34 @@ def wait(predicate, error_message=None, iter=None, sleep_backoff=None, timeout=N if sleep_backoff is None: sleep_backoff = 0.3 + last_exception = None if ignore_exceptions: def check_predicate(): try: - return predicate() + return predicate(), None # Do not catch BaseException because pytest exceptions are inherited from it # pytest.fail raises exception inherited from BaseException. - except Exception: - return False + except Exception as ex: + return False, ex else: - check_predicate = predicate + def check_predicate(): + return predicate(), None if timeout is None: if iter is None: iter = 100 index = 0 while index < iter: - if check_predicate(): + result, last_exception = check_predicate() + if result: return index += 1 time.sleep(sleep_backoff) else: start_time = datetime.datetime.now() while datetime.datetime.now() - start_time < datetime.timedelta(seconds=timeout): - if check_predicate(): + result, last_exception = check_predicate() + if result: return time.sleep(sleep_backoff) @@ -865,5 +869,9 @@ def wait(predicate, error_message=None, iter=None, sleep_backoff=None, timeout=N error_message = error_message() if error_message is None: error_message = "Wait failed" - error_message += " (timeout = {0})".format(timeout if timeout is not None else iter * sleep_backoff) + + error_message += f" (timeout = {timeout if timeout is not None else iter * sleep_backoff}" + if last_exception is not None: + error_message += f", exception = {last_exception}" + error_message += ")" raise WaitFailed(error_message) |