mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-28 08:02:00 +00:00
Merge branch 'master' into sh_merge_master
This commit is contained in:
commit
dca5623226
@ -25,14 +25,14 @@ repos:
|
||||
|
||||
# Clang format the codebase automatically
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: "v18.1.8"
|
||||
rev: "v19.1.3"
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types_or: [c++, c, cuda]
|
||||
|
||||
# Ruff, the Python auto-correcting linter/formatter written in Rust
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.6.3
|
||||
rev: v0.7.2
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix", "--show-fixes"]
|
||||
@ -40,7 +40,7 @@ repos:
|
||||
|
||||
# Check static types with mypy
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: "v1.11.2"
|
||||
rev: "v1.13.0"
|
||||
hooks:
|
||||
- id: mypy
|
||||
args: []
|
||||
@ -62,7 +62,7 @@ repos:
|
||||
|
||||
# Standard hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: "v4.6.0"
|
||||
rev: "v5.0.0"
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
@ -80,7 +80,7 @@ repos:
|
||||
|
||||
# Also code format the docs
|
||||
- repo: https://github.com/adamchainz/blacken-docs
|
||||
rev: "1.18.0"
|
||||
rev: "1.19.1"
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies:
|
||||
@ -110,7 +110,7 @@ repos:
|
||||
|
||||
# Checks the manifest for missing files (native support)
|
||||
- repo: https://github.com/mgedmin/check-manifest
|
||||
rev: "0.49"
|
||||
rev: "0.50"
|
||||
hooks:
|
||||
- id: check-manifest
|
||||
# This is a slow hook, so only run this if --hook-stage manual is passed
|
||||
@ -144,14 +144,14 @@ repos:
|
||||
|
||||
# PyLint has native support - not always usable, but works for us
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: "v3.2.7"
|
||||
rev: "v3.3.1"
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^pybind11
|
||||
|
||||
# Check schemas on some of our YAML files
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.29.2
|
||||
rev: 0.29.4
|
||||
hooks:
|
||||
- id: check-readthedocs
|
||||
- id: check-github-workflows
|
||||
|
@ -24,7 +24,8 @@ changes are that:
|
||||
function is not available anymore.
|
||||
|
||||
Due to NumPy changes, you may experience difficulties updating to NumPy 2.
|
||||
Please see the [NumPy 2 migration guide](https://numpy.org/devdocs/numpy_2_0_migration_guide.html) for details.
|
||||
Please see the `NumPy 2 migration guide <https://numpy.org/devdocs/numpy_2_0_migration_guide.html>`_
|
||||
for details.
|
||||
For example, a more direct change could be that the default integer ``"int_"``
|
||||
(and ``"uint"``) is now ``ssize_t`` and not ``long`` (affects 64bit windows).
|
||||
|
||||
|
@ -1150,14 +1150,14 @@ struct overload_cast_impl {
|
||||
}
|
||||
|
||||
template <typename Return, typename Class>
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...),
|
||||
std::false_type = {}) const noexcept -> decltype(pmf) {
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...), std::false_type = {}) const noexcept
|
||||
-> decltype(pmf) {
|
||||
return pmf;
|
||||
}
|
||||
|
||||
template <typename Return, typename Class>
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...) const,
|
||||
std::true_type) const noexcept -> decltype(pmf) {
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...) const, std::true_type) const noexcept
|
||||
-> decltype(pmf) {
|
||||
return pmf;
|
||||
}
|
||||
};
|
||||
|
@ -156,9 +156,8 @@ constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) {
|
||||
}
|
||||
#else
|
||||
template <size_t N, typename... Ts, typename... Args>
|
||||
constexpr auto concat(const descr<N, Ts...> &d,
|
||||
const Args &...args) -> decltype(std::declval<descr<N + 2, Ts...>>()
|
||||
+ concat(args...)) {
|
||||
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
|
||||
-> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
|
||||
return d + const_name(", ") + concat(args...);
|
||||
}
|
||||
#endif
|
||||
|
@ -697,8 +697,8 @@ inline std::uint64_t mix64(std::uint64_t z) {
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline auto with_instance_map(const void *ptr,
|
||||
const F &cb) -> decltype(cb(std::declval<instance_map &>())) {
|
||||
inline auto with_instance_map(const void *ptr, const F &cb)
|
||||
-> decltype(cb(std::declval<instance_map &>())) {
|
||||
auto &internals = get_internals();
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
|
@ -121,7 +121,6 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
|
||||
for (handle parent : reinterpret_borrow<tuple>(t->tp_bases)) {
|
||||
check.push_back((PyTypeObject *) parent.ptr());
|
||||
}
|
||||
|
||||
auto const &type_dict = get_internals().registered_types_py;
|
||||
for (size_t i = 0; i < check.size(); i++) {
|
||||
auto *type = check[i];
|
||||
@ -180,13 +179,7 @@ PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_
|
||||
* The value is cached for the lifetime of the Python type.
|
||||
*/
|
||||
inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type) {
|
||||
auto ins = all_type_info_get_cache(type);
|
||||
if (ins.second) {
|
||||
// New cache entry: populate it
|
||||
all_type_info_populate(type, ins.first->second);
|
||||
}
|
||||
|
||||
return ins.first->second;
|
||||
return all_type_info_get_cache(type).first->second;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1535,14 +1528,14 @@ protected:
|
||||
does not have a private operator new implementation. A comma operator is used in the
|
||||
decltype argument to apply SFINAE to the public copy/move constructors.*/
|
||||
template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
|
||||
static auto make_copy_constructor(const T *) -> decltype(new T(std::declval<const T>()),
|
||||
Constructor{}) {
|
||||
static auto make_copy_constructor(const T *)
|
||||
-> decltype(new T(std::declval<const T>()), Constructor{}) {
|
||||
return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
|
||||
}
|
||||
|
||||
template <typename T, typename = enable_if_t<is_move_constructible<T>::value>>
|
||||
static auto make_move_constructor(const T *) -> decltype(new T(std::declval<T &&>()),
|
||||
Constructor{}) {
|
||||
static auto make_move_constructor(const T *)
|
||||
-> decltype(new T(std::declval<T &&>()), Constructor{}) {
|
||||
return [](const void *arg) -> void * {
|
||||
return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
|
||||
};
|
||||
|
@ -124,9 +124,9 @@ struct eigen_tensor_helper<
|
||||
template <typename Type, bool ShowDetails, bool NeedsWriteable = false>
|
||||
struct get_tensor_descriptor {
|
||||
static constexpr auto details
|
||||
= const_name<NeedsWriteable>(", flags.writeable", "")
|
||||
+ const_name<static_cast<int>(Type::Layout) == static_cast<int>(Eigen::RowMajor)>(
|
||||
", flags.c_contiguous", ", flags.f_contiguous");
|
||||
= const_name<NeedsWriteable>(", flags.writeable", "") + const_name
|
||||
< static_cast<int>(Type::Layout)
|
||||
== static_cast<int>(Eigen::RowMajor) > (", flags.c_contiguous", ", flags.f_contiguous");
|
||||
static constexpr auto value
|
||||
= const_name("numpy.ndarray[") + npy_format_descriptor<typename Type::Scalar>::name
|
||||
+ const_name("[") + eigen_tensor_helper<remove_cv_t<Type>>::dimensions_descriptor
|
||||
|
@ -2665,13 +2665,20 @@ keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret) {
|
||||
inline std::pair<decltype(internals::registered_types_py)::iterator, bool>
|
||||
all_type_info_get_cache(PyTypeObject *type) {
|
||||
auto res = with_internals([type](internals &internals) {
|
||||
return internals
|
||||
.registered_types_py
|
||||
auto ins = internals
|
||||
.registered_types_py
|
||||
#ifdef __cpp_lib_unordered_map_try_emplace
|
||||
.try_emplace(type);
|
||||
.try_emplace(type);
|
||||
#else
|
||||
.emplace(type, std::vector<detail::type_info *>());
|
||||
.emplace(type, std::vector<detail::type_info *>());
|
||||
#endif
|
||||
if (ins.second) {
|
||||
// For free-threading mode, this call must be under
|
||||
// the with_internals() mutex lock, to avoid that other threads
|
||||
// continue running with the empty ins.first->second.
|
||||
all_type_info_populate(type, ins.first->second);
|
||||
}
|
||||
return ins;
|
||||
});
|
||||
if (res.second) {
|
||||
// New cache entry created; set up a weak reference to automatically remove it if the type
|
||||
|
@ -128,4 +128,9 @@ PYBIND11_MODULE(pybind11_tests, m, py::mod_gil_not_used()) {
|
||||
for (const auto &initializer : initializers()) {
|
||||
initializer(m);
|
||||
}
|
||||
|
||||
py::class_<TestContext>(m, "TestContext")
|
||||
.def(py::init<>(&TestContext::createNewContextForInit))
|
||||
.def("__enter__", &TestContext::contextEnter)
|
||||
.def("__exit__", &TestContext::contextExit);
|
||||
}
|
||||
|
@ -96,3 +96,24 @@ void ignoreOldStyleInitWarnings(F &&body) {
|
||||
)",
|
||||
py::dict(py::arg("body") = py::cpp_function(body)));
|
||||
}
|
||||
|
||||
// See PR #5419 for background.
|
||||
class TestContext {
|
||||
public:
|
||||
TestContext() = delete;
|
||||
TestContext(const TestContext &) = delete;
|
||||
TestContext(TestContext &&) = delete;
|
||||
static TestContext *createNewContextForInit() { return new TestContext("new-context"); }
|
||||
|
||||
pybind11::object contextEnter() {
|
||||
py::object contextObj = py::cast(*this);
|
||||
return contextObj;
|
||||
}
|
||||
void contextExit(const pybind11::object & /*excType*/,
|
||||
const pybind11::object & /*excVal*/,
|
||||
const pybind11::object & /*excTb*/) {}
|
||||
|
||||
private:
|
||||
explicit TestContext(const std::string &context) : context(context) {}
|
||||
std::string context;
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
@ -520,3 +521,31 @@ def test_pr4220_tripped_over_this():
|
||||
m.Empty0().get_msg()
|
||||
== "This is really only meant to exercise successful compilation."
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("emscripten"), reason="Requires threads")
|
||||
def test_all_type_info_multithreaded():
|
||||
# See PR #5419 for background.
|
||||
import threading
|
||||
|
||||
from pybind11_tests import TestContext
|
||||
|
||||
class Context(TestContext):
|
||||
pass
|
||||
|
||||
num_runs = 10
|
||||
num_threads = 4
|
||||
barrier = threading.Barrier(num_threads)
|
||||
|
||||
def func():
|
||||
barrier.wait()
|
||||
with Context():
|
||||
pass
|
||||
|
||||
for _ in range(num_runs):
|
||||
threads = [threading.Thread(target=func) for _ in range(num_threads)]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
Loading…
Reference in New Issue
Block a user