Skip to content

Commit

Permalink
Merge branch 'master' into sh_merge_master
Browse files Browse the repository at this point in the history
  • Loading branch information
rwgk committed Nov 7, 2024
2 parents 3b35ce4 + ce2f005 commit dca5623
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 37 deletions.
16 changes: 8 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ 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"]
- id: ruff-format

# 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: []
Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion docs/upgrade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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).

Expand Down
8 changes: 4 additions & 4 deletions include/pybind11/detail/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
};
Expand Down
5 changes: 2 additions & 3 deletions include/pybind11/detail/descr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions include/pybind11/detail/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 5 additions & 12 deletions include/pybind11/detail/type_caster_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -1535,14 +1528,14 @@ class type_caster_base : public type_caster_generic {
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))));
};
Expand Down
6 changes: 3 additions & 3 deletions include/pybind11/eigen/tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 11 additions & 4 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions tests/pybind11_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
21 changes: 21 additions & 0 deletions tests/pybind11_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
29 changes: 29 additions & 0 deletions tests/test_class.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import sys
from unittest import mock

import pytest
Expand Down Expand Up @@ -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()

0 comments on commit dca5623

Please sign in to comment.