mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-24 14:15:11 +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
|
# Clang format the codebase automatically
|
||||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
rev: "v18.1.8"
|
rev: "v19.1.3"
|
||||||
hooks:
|
hooks:
|
||||||
- id: clang-format
|
- id: clang-format
|
||||||
types_or: [c++, c, cuda]
|
types_or: [c++, c, cuda]
|
||||||
|
|
||||||
# Ruff, the Python auto-correcting linter/formatter written in Rust
|
# Ruff, the Python auto-correcting linter/formatter written in Rust
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.6.3
|
rev: v0.7.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
args: ["--fix", "--show-fixes"]
|
args: ["--fix", "--show-fixes"]
|
||||||
@ -40,7 +40,7 @@ repos:
|
|||||||
|
|
||||||
# Check static types with mypy
|
# Check static types with mypy
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: "v1.11.2"
|
rev: "v1.13.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
args: []
|
args: []
|
||||||
@ -62,7 +62,7 @@ repos:
|
|||||||
|
|
||||||
# Standard hooks
|
# Standard hooks
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: "v4.6.0"
|
rev: "v5.0.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- id: check-case-conflict
|
- id: check-case-conflict
|
||||||
@ -80,7 +80,7 @@ repos:
|
|||||||
|
|
||||||
# Also code format the docs
|
# Also code format the docs
|
||||||
- repo: https://github.com/adamchainz/blacken-docs
|
- repo: https://github.com/adamchainz/blacken-docs
|
||||||
rev: "1.18.0"
|
rev: "1.19.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: blacken-docs
|
- id: blacken-docs
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
@ -110,7 +110,7 @@ repos:
|
|||||||
|
|
||||||
# Checks the manifest for missing files (native support)
|
# Checks the manifest for missing files (native support)
|
||||||
- repo: https://github.com/mgedmin/check-manifest
|
- repo: https://github.com/mgedmin/check-manifest
|
||||||
rev: "0.49"
|
rev: "0.50"
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-manifest
|
- id: check-manifest
|
||||||
# This is a slow hook, so only run this if --hook-stage manual is passed
|
# 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
|
# PyLint has native support - not always usable, but works for us
|
||||||
- repo: https://github.com/PyCQA/pylint
|
- repo: https://github.com/PyCQA/pylint
|
||||||
rev: "v3.2.7"
|
rev: "v3.3.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: pylint
|
- id: pylint
|
||||||
files: ^pybind11
|
files: ^pybind11
|
||||||
|
|
||||||
# Check schemas on some of our YAML files
|
# Check schemas on some of our YAML files
|
||||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||||
rev: 0.29.2
|
rev: 0.29.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-readthedocs
|
- id: check-readthedocs
|
||||||
- id: check-github-workflows
|
- id: check-github-workflows
|
||||||
|
@ -24,7 +24,8 @@ changes are that:
|
|||||||
function is not available anymore.
|
function is not available anymore.
|
||||||
|
|
||||||
Due to NumPy changes, you may experience difficulties updating to NumPy 2.
|
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_"``
|
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).
|
(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>
|
template <typename Return, typename Class>
|
||||||
constexpr auto operator()(Return (Class::*pmf)(Args...),
|
constexpr auto operator()(Return (Class::*pmf)(Args...), std::false_type = {}) const noexcept
|
||||||
std::false_type = {}) const noexcept -> decltype(pmf) {
|
-> decltype(pmf) {
|
||||||
return pmf;
|
return pmf;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Return, typename Class>
|
template <typename Return, typename Class>
|
||||||
constexpr auto operator()(Return (Class::*pmf)(Args...) const,
|
constexpr auto operator()(Return (Class::*pmf)(Args...) const, std::true_type) const noexcept
|
||||||
std::true_type) const noexcept -> decltype(pmf) {
|
-> decltype(pmf) {
|
||||||
return pmf;
|
return pmf;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -156,9 +156,8 @@ constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
template <size_t N, typename... Ts, typename... Args>
|
template <size_t N, typename... Ts, typename... Args>
|
||||||
constexpr auto concat(const descr<N, Ts...> &d,
|
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
|
||||||
const Args &...args) -> decltype(std::declval<descr<N + 2, Ts...>>()
|
-> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
|
||||||
+ concat(args...)) {
|
|
||||||
return d + const_name(", ") + concat(args...);
|
return d + const_name(", ") + concat(args...);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -697,8 +697,8 @@ inline std::uint64_t mix64(std::uint64_t z) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
inline auto with_instance_map(const void *ptr,
|
inline auto with_instance_map(const void *ptr, const F &cb)
|
||||||
const F &cb) -> decltype(cb(std::declval<instance_map &>())) {
|
-> decltype(cb(std::declval<instance_map &>())) {
|
||||||
auto &internals = get_internals();
|
auto &internals = get_internals();
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#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)) {
|
for (handle parent : reinterpret_borrow<tuple>(t->tp_bases)) {
|
||||||
check.push_back((PyTypeObject *) parent.ptr());
|
check.push_back((PyTypeObject *) parent.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const &type_dict = get_internals().registered_types_py;
|
auto const &type_dict = get_internals().registered_types_py;
|
||||||
for (size_t i = 0; i < check.size(); i++) {
|
for (size_t i = 0; i < check.size(); i++) {
|
||||||
auto *type = check[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.
|
* The value is cached for the lifetime of the Python type.
|
||||||
*/
|
*/
|
||||||
inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type) {
|
inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type) {
|
||||||
auto ins = all_type_info_get_cache(type);
|
return all_type_info_get_cache(type).first->second;
|
||||||
if (ins.second) {
|
|
||||||
// New cache entry: populate it
|
|
||||||
all_type_info_populate(type, ins.first->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ins.first->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1535,14 +1528,14 @@ protected:
|
|||||||
does not have a private operator new implementation. A comma operator is used in the
|
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.*/
|
decltype argument to apply SFINAE to the public copy/move constructors.*/
|
||||||
template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
|
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>()),
|
static auto make_copy_constructor(const T *)
|
||||||
Constructor{}) {
|
-> decltype(new T(std::declval<const T>()), Constructor{}) {
|
||||||
return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
|
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>>
|
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 &&>()),
|
static auto make_move_constructor(const T *)
|
||||||
Constructor{}) {
|
-> decltype(new T(std::declval<T &&>()), Constructor{}) {
|
||||||
return [](const void *arg) -> void * {
|
return [](const void *arg) -> void * {
|
||||||
return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
|
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>
|
template <typename Type, bool ShowDetails, bool NeedsWriteable = false>
|
||||||
struct get_tensor_descriptor {
|
struct get_tensor_descriptor {
|
||||||
static constexpr auto details
|
static constexpr auto details
|
||||||
= const_name<NeedsWriteable>(", flags.writeable", "")
|
= const_name<NeedsWriteable>(", flags.writeable", "") + const_name
|
||||||
+ const_name<static_cast<int>(Type::Layout) == static_cast<int>(Eigen::RowMajor)>(
|
< static_cast<int>(Type::Layout)
|
||||||
", flags.c_contiguous", ", flags.f_contiguous");
|
== static_cast<int>(Eigen::RowMajor) > (", flags.c_contiguous", ", flags.f_contiguous");
|
||||||
static constexpr auto value
|
static constexpr auto value
|
||||||
= const_name("numpy.ndarray[") + npy_format_descriptor<typename Type::Scalar>::name
|
= const_name("numpy.ndarray[") + npy_format_descriptor<typename Type::Scalar>::name
|
||||||
+ const_name("[") + eigen_tensor_helper<remove_cv_t<Type>>::dimensions_descriptor
|
+ 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>
|
inline std::pair<decltype(internals::registered_types_py)::iterator, bool>
|
||||||
all_type_info_get_cache(PyTypeObject *type) {
|
all_type_info_get_cache(PyTypeObject *type) {
|
||||||
auto res = with_internals([type](internals &internals) {
|
auto res = with_internals([type](internals &internals) {
|
||||||
return internals
|
auto ins = internals
|
||||||
.registered_types_py
|
.registered_types_py
|
||||||
#ifdef __cpp_lib_unordered_map_try_emplace
|
#ifdef __cpp_lib_unordered_map_try_emplace
|
||||||
.try_emplace(type);
|
.try_emplace(type);
|
||||||
#else
|
#else
|
||||||
.emplace(type, std::vector<detail::type_info *>());
|
.emplace(type, std::vector<detail::type_info *>());
|
||||||
#endif
|
#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) {
|
if (res.second) {
|
||||||
// New cache entry created; set up a weak reference to automatically remove it if the type
|
// 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()) {
|
for (const auto &initializer : initializers()) {
|
||||||
initializer(m);
|
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)));
|
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
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sys
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
@ -520,3 +521,31 @@ def test_pr4220_tripped_over_this():
|
|||||||
m.Empty0().get_msg()
|
m.Empty0().get_msg()
|
||||||
== "This is really only meant to exercise successful compilation."
|
== "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