From 7ff6997d5445348b10ac402991541456882ae07d Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Thu, 24 Apr 2025 12:57:01 +0700 Subject: [PATCH 1/6] Switch Dockerfile to manylinux_2_28 (AlmaLinux-8 based) --- docker/Dockerfile | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index ebad24b3..8800dcf3 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,11 +1,11 @@ -ARG POLICY="manylinux2014" +ARG POLICY="manylinux_2_28" ARG ARCH="x86_64" ARG PLATFORM="${POLICY}_${ARCH}" FROM quay.io/pypa/$PLATFORM -ARG DEVTOOLSET_VERSION="10" -ENV PATH="/opt/rh/devtoolset-$DEVTOOLSET_VERSION/root/usr/bin:$PATH" +ARG GCC_TOOLSET_VERSION="12" +ENV PATH="/opt/rh/devtoolset-$GCC_TOOLSET_VERSION/root/usr/bin:$PATH" ARG PYTHON_VERSION @@ -13,5 +13,10 @@ ADD set-python-version.sh /set-python-version.sh RUN bash /set-python-version.sh ${PYTHON_VERSION} \ && rm /set-python-version.sh -RUN yum install -y devtoolset-$DEVTOOLSET_VERSION-toolchain \ +RUN yum install -y gcc-toolset-$GCC_TOOLSET_VERSION \ + gcc-toolset-$GCC_TOOLSET_VERSION-runtime \ + gcc-toolset-$GCC_TOOLSET_VERSION-binutils \ + gcc-toolset-$GCC_TOOLSET_VERSION-gcc \ + gcc-toolset-$GCC_TOOLSET_VERSION-gcc-c++ \ + gcc-toolset-$GCC_TOOLSET_VERSION-libstdc++-devel \ && g++ --version From e6d1e39d35bfb58678b79eda524c0ea5f0554f0b Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Thu, 24 Apr 2025 12:57:21 +0700 Subject: [PATCH 2/6] Unused --- scripts/teamcity/10.build.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/teamcity/10.build.sh b/scripts/teamcity/10.build.sh index 0a105933..94d56644 100755 --- a/scripts/teamcity/10.build.sh +++ b/scripts/teamcity/10.build.sh @@ -33,12 +33,6 @@ function relabel_wheel { DIST_DIR=dist - -PLATFORM='' -if [[ "$OSTYPE" == "darwin"* ]] ; then - PLATFORM='-p macosx-10.14-x86_64' -fi - rm -r -f build/ ${DIST_DIR}/ if [[ "$OSTYPE" == "darwin"* && $PYTHON == "python3.9"* ]]; then From 8c3735e9db6f3b21d0b0837193d1c2dcd4cf1798 Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Thu, 24 Apr 2025 13:23:14 +0700 Subject: [PATCH 3/6] Upgrade pybind to 2.13.6 to address GCC14 bug --- docker/Dockerfile.manylinux_2_28 | 22 ---- thirdparty/pybind11/.clang-tidy | 2 + thirdparty/pybind11/.github/workflows/ci.yml | 10 +- .../.github/workflows/emscripten.yaml | 30 +++++ .../pybind11/.github/workflows/format.yml | 2 +- thirdparty/pybind11/.github/workflows/pip.yml | 9 +- thirdparty/pybind11/.pre-commit-config.yaml | 14 +-- thirdparty/pybind11/CMakeLists.txt | 3 + thirdparty/pybind11/include/pybind11/cast.h | 11 +- .../pybind11/include/pybind11/detail/class.h | 19 +++- .../pybind11/include/pybind11/detail/common.h | 25 +++- .../include/pybind11/detail/cpp_conduit.h | 77 +++++++++++++ .../pybind11/detail/exception_translation.h | 71 ++++++++++++ .../pybind11/include/pybind11/detail/init.h | 6 +- .../include/pybind11/detail/internals.h | 43 ++++--- .../pybind11/detail/type_caster_base.h | 107 +++++++----------- .../pybind11/detail/value_and_holder.h | 77 +++++++++++++ .../pybind11/include/pybind11/eigen/matrix.h | 3 +- .../pybind11/include/pybind11/eigen/tensor.h | 6 +- .../pybind11/include/pybind11/functional.h | 79 +++++++------ .../include/pybind11/gil_safe_call_once.h | 11 +- thirdparty/pybind11/include/pybind11/numpy.h | 30 ++--- .../pybind11/include/pybind11/pybind11.h | 62 ++-------- .../pybind11/include/pybind11/pytypes.h | 2 + .../include/pybind11/stl/filesystem.h | 23 ++-- .../pybind11/include/pybind11/stl_bind.h | 2 +- thirdparty/pybind11/include/pybind11/typing.h | 7 +- thirdparty/pybind11/pybind11/__main__.py | 29 ++++- thirdparty/pybind11/pybind11/_version.py | 2 +- .../pybind11/tools/pybind11Common.cmake | 32 +++++- .../pybind11/tools/pybind11Config.cmake.in | 2 +- 31 files changed, 567 insertions(+), 251 deletions(-) delete mode 100644 docker/Dockerfile.manylinux_2_28 create mode 100644 thirdparty/pybind11/.github/workflows/emscripten.yaml create mode 100644 thirdparty/pybind11/include/pybind11/detail/cpp_conduit.h create mode 100644 thirdparty/pybind11/include/pybind11/detail/exception_translation.h create mode 100644 thirdparty/pybind11/include/pybind11/detail/value_and_holder.h diff --git a/docker/Dockerfile.manylinux_2_28 b/docker/Dockerfile.manylinux_2_28 deleted file mode 100644 index 9ca5f3b0..00000000 --- a/docker/Dockerfile.manylinux_2_28 +++ /dev/null @@ -1,22 +0,0 @@ -ARG POLICY="manylinux_2_28" -ARG ARCH="x86_64" -ARG PLATFORM="${POLICY}_${ARCH}" - -FROM quay.io/pypa/$PLATFORM - -ARG GCC_TOOLSET_VERSION="12" -ENV PATH="/opt/rh/devtoolset-$DEVTOOLSET_VERSION/root/usr/bin:$PATH" - -ARG PYTHON_VERSION - -ADD set-python-version.sh /set-python-version.sh -RUN bash /set-python-version.sh ${PYTHON_VERSION} \ - && rm /set-python-version.sh - -RUN yum install -y gcc-toolset-$GCC_TOOLSET_VERSION \ - gcc-toolset-$GCC_TOOLSET_VERSION-runtime \ - gcc-toolset-$GCC_TOOLSET_VERSION-binutils \ - gcc-toolset-$GCC_TOOLSET_VERSION-gcc \ - gcc-toolset-$GCC_TOOLSET_VERSION-gcc-c++ \ - gcc-toolset-$GCC_TOOLSET_VERSION-libstdc++-devel \ - && g++ --version diff --git a/thirdparty/pybind11/.clang-tidy b/thirdparty/pybind11/.clang-tidy index 23018386..96cb6f58 100644 --- a/thirdparty/pybind11/.clang-tidy +++ b/thirdparty/pybind11/.clang-tidy @@ -57,10 +57,12 @@ Checks: | readability-string-compare, readability-suspicious-call-argument, readability-uniqueptr-delete-release, + -bugprone-chained-comparison, -bugprone-easily-swappable-parameters, -bugprone-exception-escape, -bugprone-reserved-identifier, -bugprone-unused-raii, + -performance-enum-size, CheckOptions: - key: modernize-use-equals-default.IgnoreMacros diff --git a/thirdparty/pybind11/.github/workflows/ci.yml b/thirdparty/pybind11/.github/workflows/ci.yml index 3054d842..3f7e8a6c 100644 --- a/thirdparty/pybind11/.github/workflows/ci.yml +++ b/thirdparty/pybind11/.github/workflows/ci.yml @@ -243,7 +243,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Python ${{ matrix.python-version }} (deadsnakes) - uses: deadsnakes/action@v3.1.0 + uses: deadsnakes/action@v3.2.0 with: python-version: ${{ matrix.python-version }} debug: ${{ matrix.python-debug }} @@ -340,6 +340,12 @@ jobs: - clang: 16 std: 20 container_suffix: "-bullseye" + - clang: 17 + std: 20 + container_suffix: "-bookworm" + - clang: 18 + std: 20 + container_suffix: "-bookworm" name: "🐍 3 • Clang ${{ matrix.clang }} • C++${{ matrix.std }} • x64" container: "silkeh/clang:${{ matrix.clang }}${{ matrix.container_suffix }}" @@ -501,7 +507,9 @@ jobs: - { gcc: 7, std: 17 } - { gcc: 8, std: 14 } - { gcc: 8, std: 17 } + - { gcc: 9, std: 20 } - { gcc: 10, std: 17 } + - { gcc: 10, std: 20 } - { gcc: 11, std: 20 } - { gcc: 12, std: 20 } - { gcc: 13, std: 20 } diff --git a/thirdparty/pybind11/.github/workflows/emscripten.yaml b/thirdparty/pybind11/.github/workflows/emscripten.yaml new file mode 100644 index 00000000..14b2b9dc --- /dev/null +++ b/thirdparty/pybind11/.github/workflows/emscripten.yaml @@ -0,0 +1,30 @@ +name: WASM + +on: + workflow_dispatch: + pull_request: + branches: + - master + - stable + - v* + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-wasm-emscripten: + name: Pyodide wheel + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + + - uses: pypa/cibuildwheel@v2.20 + env: + PYODIDE_BUILD_EXPORTS: whole_archive + with: + package-dir: tests + only: cp312-pyodide_wasm32 diff --git a/thirdparty/pybind11/.github/workflows/format.yml b/thirdparty/pybind11/.github/workflows/format.yml index 1eaa56e1..e50dc0bb 100644 --- a/thirdparty/pybind11/.github/workflows/format.yml +++ b/thirdparty/pybind11/.github/workflows/format.yml @@ -41,7 +41,7 @@ jobs: # in .github/CONTRIBUTING.md and update as needed. name: Clang-Tidy runs-on: ubuntu-latest - container: silkeh/clang:15-bullseye + container: silkeh/clang:18-bookworm steps: - uses: actions/checkout@v4 diff --git a/thirdparty/pybind11/.github/workflows/pip.yml b/thirdparty/pybind11/.github/workflows/pip.yml index a054ce69..37135373 100644 --- a/thirdparty/pybind11/.github/workflows/pip.yml +++ b/thirdparty/pybind11/.github/workflows/pip.yml @@ -91,18 +91,19 @@ jobs: runs-on: ubuntu-latest if: github.event_name == 'release' && github.event.action == 'published' needs: [packaging] - environment: pypi + environment: + name: pypi + url: https://pypi.org/p/pybind11 permissions: id-token: write attestations: write - contents: read steps: # Downloads all to directories matching the artifact names - uses: actions/download-artifact@v4 - name: Generate artifact attestation for sdist and wheel - uses: actions/attest-build-provenance@173725a1209d09b31f9d30a3890cf2757ebbff0d # v1.1.2 + uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3 with: subject-path: "*/pybind11*" @@ -110,8 +111,10 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: standard/ + attestations: true - name: Publish global package uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: global/ + attestations: true diff --git a/thirdparty/pybind11/.pre-commit-config.yaml b/thirdparty/pybind11/.pre-commit-config.yaml index 3cec1ebe..a8190df4 100644 --- a/thirdparty/pybind11/.pre-commit-config.yaml +++ b/thirdparty/pybind11/.pre-commit-config.yaml @@ -25,14 +25,14 @@ repos: # Clang format the codebase automatically - repo: https://github.com/pre-commit/mirrors-clang-format - rev: "v18.1.5" + rev: "v18.1.8" 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.4.7 + rev: v0.6.3 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.10.0" + rev: "v1.11.2" hooks: - id: mypy args: [] @@ -79,7 +79,7 @@ repos: # Also code format the docs - repo: https://github.com/adamchainz/blacken-docs - rev: "1.16.0" + rev: "1.18.0" hooks: - id: blacken-docs additional_dependencies: @@ -93,7 +93,7 @@ repos: # Avoid directional quotes - repo: https://github.com/sirosen/texthooks - rev: "0.6.6" + rev: "0.6.7" hooks: - id: fix-ligatures - id: fix-smartquotes @@ -142,14 +142,14 @@ repos: # PyLint has native support - not always usable, but works for us - repo: https://github.com/PyCQA/pylint - rev: "v3.2.2" + rev: "v3.2.7" hooks: - id: pylint files: ^pybind11 # Check schemas on some of our YAML files - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.28.4 + rev: 0.29.2 hooks: - id: check-readthedocs - id: check-github-workflows diff --git a/thirdparty/pybind11/CMakeLists.txt b/thirdparty/pybind11/CMakeLists.txt index 3526a1a6..f53aa209 100644 --- a/thirdparty/pybind11/CMakeLists.txt +++ b/thirdparty/pybind11/CMakeLists.txt @@ -149,11 +149,14 @@ endif() set(PYBIND11_HEADERS include/pybind11/detail/class.h include/pybind11/detail/common.h + include/pybind11/detail/cpp_conduit.h include/pybind11/detail/descr.h include/pybind11/detail/init.h include/pybind11/detail/internals.h include/pybind11/detail/type_caster_base.h include/pybind11/detail/typeid.h + include/pybind11/detail/value_and_holder.h + include/pybind11/detail/exception_translation.h include/pybind11/attr.h include/pybind11/buffer_info.h include/pybind11/cast.h diff --git a/thirdparty/pybind11/include/pybind11/cast.h b/thirdparty/pybind11/include/pybind11/cast.h index 624b8eba..0f3091f6 100644 --- a/thirdparty/pybind11/include/pybind11/cast.h +++ b/thirdparty/pybind11/include/pybind11/cast.h @@ -740,6 +740,13 @@ class type_caster> : public tuple_caster {} template class type_caster> : public tuple_caster {}; +template <> +class type_caster> : public tuple_caster { +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 @@ -787,11 +794,11 @@ struct copyable_holder_caster : public type_caster_base { } } - 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(); - return true; + return; } throw cast_error("Unable to cast from non-held to held instance (T& to Holder) " #if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) diff --git a/thirdparty/pybind11/include/pybind11/detail/class.h b/thirdparty/pybind11/include/pybind11/detail/class.h index d30621c8..b990507d 100644 --- a/thirdparty/pybind11/include/pybind11/detail/class.h +++ b/thirdparty/pybind11/include/pybind11/detail/class.h @@ -9,8 +9,10 @@ #pragma once -#include "../attr.h" -#include "../options.h" +#include +#include + +#include "exception_translation.h" PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) @@ -591,7 +593,18 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla return -1; } std::memset(view, 0, sizeof(Py_buffer)); - buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data); + buffer_info *info = nullptr; + try { + info = tinfo->get_buffer(obj, tinfo->get_buffer_data); + } catch (...) { + try_translate_exceptions(); + raise_from(PyExc_BufferError, "Error getting buffer"); + return -1; + } + if (info == nullptr) { + pybind11_fail("FATAL UNEXPECTED SITUATION: tinfo->get_buffer() returned nullptr."); + } + if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly) { delete info; // view->obj = nullptr; // Was just memset to 0, so not necessary diff --git a/thirdparty/pybind11/include/pybind11/detail/common.h b/thirdparty/pybind11/include/pybind11/detail/common.h index e37152a9..c51d1d60 100644 --- a/thirdparty/pybind11/include/pybind11/detail/common.h +++ b/thirdparty/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 6 // 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 0x020D0600 // Define some generic pybind11 helper macros for warning management. // @@ -462,7 +462,25 @@ 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 */ +PYBIND11_WARNING_PUSH +PYBIND11_WARNING_DISABLE_CLANG("-Wgnu-zero-variadic-macro-arguments") #define PYBIND11_MODULE(name, variable, ...) \ static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name) \ PYBIND11_MAYBE_UNUSED; \ @@ -483,6 +501,7 @@ PYBIND11_WARNING_POP PYBIND11_CATCH_INIT_EXCEPTIONS \ } \ void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ & (variable)) +PYBIND11_WARNING_POP PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) @@ -538,7 +557,7 @@ enum class return_value_policy : uint8_t { object without taking ownership similar to the above return_value_policy::reference policy. In contrast to that policy, the function or property's implicit this argument (called the parent) is - considered to be the the owner of the return value (the child). + considered to be the owner of the return value (the child). pybind11 then couples the lifetime of the parent to the child via a reference relationship that ensures that the parent cannot be garbage collected while Python is still using the child. More advanced diff --git a/thirdparty/pybind11/include/pybind11/detail/cpp_conduit.h b/thirdparty/pybind11/include/pybind11/detail/cpp_conduit.h new file mode 100644 index 00000000..b66c2d39 --- /dev/null +++ b/thirdparty/pybind11/include/pybind11/detail/cpp_conduit.h @@ -0,0 +1,77 @@ +// Copyright (c) 2024 The pybind Community. + +#pragma once + +#include + +#include "common.h" +#include "internals.h" + +#include + +PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +PYBIND11_NAMESPACE_BEGIN(detail) + +// Forward declaration needed here: Refactoring opportunity. +extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *); + +inline bool type_is_managed_by_our_internals(PyTypeObject *type_obj) { +#if defined(PYPY_VERSION) + auto &internals = get_internals(); + return bool(internals.registered_types_py.find(type_obj) + != internals.registered_types_py.end()); +#else + return bool(type_obj->tp_new == pybind11_object_new); +#endif +} + +inline bool is_instance_method_of_type(PyTypeObject *type_obj, PyObject *attr_name) { + PyObject *descr = _PyType_Lookup(type_obj, attr_name); + return bool((descr != nullptr) && PyInstanceMethod_Check(descr)); +} + +inline object try_get_cpp_conduit_method(PyObject *obj) { + if (PyType_Check(obj)) { + return object(); + } + PyTypeObject *type_obj = Py_TYPE(obj); + str attr_name("_pybind11_conduit_v1_"); + bool assumed_to_be_callable = false; + if (type_is_managed_by_our_internals(type_obj)) { + if (!is_instance_method_of_type(type_obj, attr_name.ptr())) { + return object(); + } + assumed_to_be_callable = true; + } + PyObject *method = PyObject_GetAttr(obj, attr_name.ptr()); + if (method == nullptr) { + PyErr_Clear(); + return object(); + } + if (!assumed_to_be_callable && PyCallable_Check(method) == 0) { + Py_DECREF(method); + return object(); + } + return reinterpret_steal(method); +} + +inline void *try_raw_pointer_ephemeral_from_cpp_conduit(handle src, + const std::type_info *cpp_type_info) { + object method = try_get_cpp_conduit_method(src.ptr()); + if (method) { + capsule cpp_type_info_capsule(const_cast(static_cast(cpp_type_info)), + typeid(std::type_info).name()); + object cpp_conduit = method(bytes(PYBIND11_PLATFORM_ABI_ID), + cpp_type_info_capsule, + bytes("raw_pointer_ephemeral")); + if (isinstance(cpp_conduit)) { + return reinterpret_borrow(cpp_conduit).get_pointer(); + } + } + return nullptr; +} + +#define PYBIND11_HAS_CPP_CONDUIT 1 + +PYBIND11_NAMESPACE_END(detail) +PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/thirdparty/pybind11/include/pybind11/detail/exception_translation.h b/thirdparty/pybind11/include/pybind11/detail/exception_translation.h new file mode 100644 index 00000000..2764180b --- /dev/null +++ b/thirdparty/pybind11/include/pybind11/detail/exception_translation.h @@ -0,0 +1,71 @@ +/* + pybind11/detail/exception_translation.h: means to translate C++ exceptions to Python exceptions + + Copyright (c) 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 "internals.h" + +PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +PYBIND11_NAMESPACE_BEGIN(detail) + +// 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 +// available, they should be tried. +inline bool apply_exception_translators(std::forward_list &translators) { + auto last_exception = std::current_exception(); + + for (auto &translator : translators) { + try { + translator(last_exception); + return true; + } catch (...) { + last_exception = std::current_exception(); + } + } + return false; +} + +inline void try_translate_exceptions() { + /* When an exception is caught, give each registered exception + translator a chance to translate it to a Python exception. First + all module-local translators will be tried in reverse order of + registration. If none of the module-locale translators handle + the exception (or there are no module-locale translators) then + the global translators will be tried, also in reverse order of + registration. + + A translator may choose to do one of the following: + + - 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. + */ + + bool handled = with_internals([&](internals &internals) { + auto &local_exception_translators = get_local_internals().registered_exception_translators; + if (detail::apply_exception_translators(local_exception_translators)) { + return true; + } + auto &exception_translators = internals.registered_exception_translators; + if (detail::apply_exception_translators(exception_translators)) { + return true; + } + return false; + }); + + if (!handled) { + set_error(PyExc_SystemError, "Exception escaped from default exception translator!"); + } +} + +PYBIND11_NAMESPACE_END(detail) +PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/thirdparty/pybind11/include/pybind11/detail/init.h b/thirdparty/pybind11/include/pybind11/detail/init.h index 4509bd13..79cc930c 100644 --- a/thirdparty/pybind11/include/pybind11/detail/init.h +++ b/thirdparty/pybind11/include/pybind11/detail/init.h @@ -128,11 +128,13 @@ void construct(value_and_holder &v_h, Cpp *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 temp_holder(std::move(v_h.holder>())); // 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(is_alias_constructible{}, v_h, std::move(*ptr)); } else { diff --git a/thirdparty/pybind11/include/pybind11/detail/internals.h b/thirdparty/pybind11/include/pybind11/detail/internals.h index e61c1687..232bc32d 100644 --- a/thirdparty/pybind11/include/pybind11/detail/internals.h +++ b/thirdparty/pybind11/include/pybind11/detail/internals.h @@ -12,10 +12,10 @@ #include "common.h" #if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT) -# include "../gil.h" +# include #endif -#include "../pytypes.h" +#include #include #include @@ -148,20 +148,35 @@ struct override_hash { using instance_map = std::unordered_multimap; +#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 registered_types_cpp; @@ -306,15 +321,17 @@ struct type_info { # define PYBIND11_INTERNALS_KIND "" #endif +#define PYBIND11_PLATFORM_ABI_ID \ + PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB PYBIND11_BUILD_ABI \ + PYBIND11_BUILD_TYPE + #define PYBIND11_INTERNALS_ID \ "__pybind11_internals_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \ - PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB \ - PYBIND11_BUILD_ABI PYBIND11_BUILD_TYPE "__" + PYBIND11_PLATFORM_ABI_ID "__" #define PYBIND11_MODULE_LOCAL_ID \ "__pybind11_module_local_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \ - PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB \ - PYBIND11_BUILD_ABI PYBIND11_BUILD_TYPE "__" + PYBIND11_PLATFORM_ABI_ID "__" /// Each module locally stores a pointer to the `internals` data. The data /// itself is shared among modules with the same `PYBIND11_INTERNALS_ID`. @@ -538,7 +555,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(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(); @@ -614,7 +631,7 @@ inline local_internals &get_local_internals() { } #ifdef Py_GIL_DISABLED -# define PYBIND11_LOCK_INTERNALS(internals) std::unique_lock lock((internals).mutex) +# define PYBIND11_LOCK_INTERNALS(internals) std::unique_lock lock((internals).mutex) #else # define PYBIND11_LOCK_INTERNALS(internals) #endif @@ -651,7 +668,7 @@ inline auto with_instance_map(const void *ptr, auto idx = static_cast(hash & internals.instance_shards_mask); auto &shard = internals.instance_shards[idx]; - std::unique_lock lock(shard.mutex); + std::unique_lock lock(shard.mutex); return cb(shard.registered_instances); #else (void) ptr; @@ -667,7 +684,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 lock(shard.mutex); + std::unique_lock lock(shard.mutex); count += shard.registered_instances.size(); } return count; diff --git a/thirdparty/pybind11/include/pybind11/detail/type_caster_base.h b/thirdparty/pybind11/include/pybind11/detail/type_caster_base.h index fd8c81b9..e40e44ba 100644 --- a/thirdparty/pybind11/include/pybind11/detail/type_caster_base.h +++ b/thirdparty/pybind11/include/pybind11/detail/type_caster_base.h @@ -9,15 +9,20 @@ #pragma once -#include "../pytypes.h" +#include + #include "common.h" +#include "cpp_conduit.h" #include "descr.h" #include "internals.h" #include "typeid.h" +#include "value_and_holder.h" #include +#include #include #include +#include #include #include #include @@ -259,67 +264,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 - V *&value_ptr() const { - return reinterpret_cast(vh[0]); - } - // True if this `value_and_holder` has a non-null value pointer - explicit operator bool() const { return value_ptr() != nullptr; } - - template - H &holder() const { - return reinterpret_cast(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: @@ -488,7 +432,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(nonsimple.values_and_holders)); } } @@ -670,6 +614,13 @@ class type_caster_generic { } return false; } + bool try_cpp_conduit(handle src) { + value = try_raw_pointer_ephemeral_from_cpp_conduit(src, cpptype); + if (value != nullptr) { + return true; + } + return false; + } void check_holder_compat() {} PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) { @@ -801,6 +752,10 @@ class type_caster_generic { return true; } + if (convert && cpptype && this_.try_cpp_conduit(src)) { + return true; + } + return false; } @@ -828,6 +783,32 @@ class type_caster_generic { void *value = nullptr; }; +inline object cpp_conduit_method(handle self, + const bytes &pybind11_platform_abi_id, + const capsule &cpp_type_info_capsule, + const bytes &pointer_kind) { +#ifdef PYBIND11_HAS_STRING_VIEW + using cpp_str = std::string_view; +#else + using cpp_str = std::string; +#endif + if (cpp_str(pybind11_platform_abi_id) != PYBIND11_PLATFORM_ABI_ID) { + return none(); + } + if (std::strcmp(cpp_type_info_capsule.name(), typeid(std::type_info).name()) != 0) { + return none(); + } + if (cpp_str(pointer_kind) != "raw_pointer_ephemeral") { + throw std::runtime_error("Invalid pointer_kind: \"" + std::string(pointer_kind) + "\""); + } + const auto *cpp_type_info = cpp_type_info_capsule.get_pointer(); + type_caster_generic caster(*cpp_type_info); + if (!caster.load(self, false)) { + return none(); + } + return capsule(caster.value, cpp_type_info->name()); +} + /** * Determine suitable casting operator for pointer-or-lvalue-casting type casters. The type caster * needs to provide `operator T*()` and `operator T&()` operators. diff --git a/thirdparty/pybind11/include/pybind11/detail/value_and_holder.h b/thirdparty/pybind11/include/pybind11/detail/value_and_holder.h new file mode 100644 index 00000000..ca37d70a --- /dev/null +++ b/thirdparty/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 +#include + +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 + V *&value_ptr() const { + return reinterpret_cast(vh[0]); + } + // True if this `value_and_holder` has a non-null value pointer + explicit operator bool() const { return value_ptr() != nullptr; } + + template + H &holder() const { + return reinterpret_cast(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/thirdparty/pybind11/include/pybind11/eigen/matrix.h b/thirdparty/pybind11/include/pybind11/eigen/matrix.h index 8d4342f8..5cf1f0a2 100644 --- a/thirdparty/pybind11/include/pybind11/eigen/matrix.h +++ b/thirdparty/pybind11/include/pybind11/eigen/matrix.h @@ -9,7 +9,8 @@ #pragma once -#include "../numpy.h" +#include + #include "common.h" /* HINT: To suppress warnings originating from the Eigen headers, use -isystem. diff --git a/thirdparty/pybind11/include/pybind11/eigen/tensor.h b/thirdparty/pybind11/include/pybind11/eigen/tensor.h index d4ed6c0c..0a9d7c25 100644 --- a/thirdparty/pybind11/include/pybind11/eigen/tensor.h +++ b/thirdparty/pybind11/include/pybind11/eigen/tensor.h @@ -7,7 +7,8 @@ #pragma once -#include "../numpy.h" +#include + #include "common.h" #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) @@ -469,9 +470,6 @@ struct type_caster, parent_object = reinterpret_borrow(parent); break; - case return_value_policy::take_ownership: - delete src; - // fallthrough default: // move, take_ownership don't make any sense for a ref/map: pybind11_fail("Invalid return_value_policy for Eigen Map type, must be either " diff --git a/thirdparty/pybind11/include/pybind11/functional.h b/thirdparty/pybind11/include/pybind11/functional.h index 6856119c..4b361011 100644 --- a/thirdparty/pybind11/include/pybind11/functional.h +++ b/thirdparty/pybind11/include/pybind11/functional.h @@ -9,12 +9,55 @@ #pragma once +#define PYBIND11_HAS_TYPE_CASTER_STD_FUNCTION_SPECIALIZATIONS + #include "pybind11.h" #include PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) +PYBIND11_NAMESPACE_BEGIN(type_caster_std_function_specializations) + +// ensure GIL is held during functor destruction +struct func_handle { + function f; +#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17)) + // This triggers a syntax error under very special conditions (very weird indeed). + explicit +#endif + func_handle(function &&f_) noexcept + : f(std::move(f_)) { + } + func_handle(const func_handle &f_) { operator=(f_); } + func_handle &operator=(const func_handle &f_) { + gil_scoped_acquire acq; + f = f_.f; + return *this; + } + ~func_handle() { + gil_scoped_acquire acq; + function kill_f(std::move(f)); + } +}; + +// to emulate 'move initialization capture' in C++11 +struct func_wrapper_base { + func_handle hfunc; + explicit func_wrapper_base(func_handle &&hf) noexcept : hfunc(hf) {} +}; + +template +struct func_wrapper : func_wrapper_base { + using func_wrapper_base::func_wrapper_base; + Return operator()(Args... args) const { + gil_scoped_acquire acq; + // casts the returned object as a rvalue to the return type + return hfunc.f(std::forward(args)...).template cast(); + } +}; + +PYBIND11_NAMESPACE_END(type_caster_std_function_specializations) template struct type_caster> { @@ -77,40 +120,8 @@ struct type_caster> { // See PR #1413 for full details } - // ensure GIL is held during functor destruction - struct func_handle { - function f; -#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17)) - // This triggers a syntax error under very special conditions (very weird indeed). - explicit -#endif - func_handle(function &&f_) noexcept - : f(std::move(f_)) { - } - func_handle(const func_handle &f_) { operator=(f_); } - func_handle &operator=(const func_handle &f_) { - gil_scoped_acquire acq; - f = f_.f; - return *this; - } - ~func_handle() { - gil_scoped_acquire acq; - function kill_f(std::move(f)); - } - }; - - // to emulate 'move initialization capture' in C++11 - struct func_wrapper { - func_handle hfunc; - explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {} - Return operator()(Args... args) const { - gil_scoped_acquire acq; - // casts the returned object as a rvalue to the return type - return hfunc.f(std::forward(args)...).template cast(); - } - }; - - value = func_wrapper(func_handle(std::move(func))); + value = type_caster_std_function_specializations::func_wrapper( + type_caster_std_function_specializations::func_handle(std::move(func))); return true; } diff --git a/thirdparty/pybind11/include/pybind11/gil_safe_call_once.h b/thirdparty/pybind11/include/pybind11/gil_safe_call_once.h index eaf84d16..5f9e1b03 100644 --- a/thirdparty/pybind11/include/pybind11/gil_safe_call_once.h +++ b/thirdparty/pybind11/include/pybind11/gil_safe_call_once.h @@ -8,6 +8,10 @@ #include #include +#ifdef Py_GIL_DISABLED +# include +#endif + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) // Use the `gil_safe_call_once_and_store` class below instead of the naive @@ -82,7 +86,12 @@ class gil_safe_call_once_and_store { 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/thirdparty/pybind11/include/pybind11/numpy.h b/thirdparty/pybind11/include/pybind11/numpy.h index a3938ed6..219eb6ba 100644 --- a/thirdparty/pybind11/include/pybind11/numpy.h +++ b/thirdparty/pybind11/include/pybind11/numpy.h @@ -261,7 +261,7 @@ struct npy_api { /** * End modification */ - + // `npy_common.h` defines the integer aliases. In order, it checks: // NPY_BITSOF_LONG, NPY_BITSOF_LONGLONG, NPY_BITSOF_INT, NPY_BITSOF_SHORT, NPY_BITSOF_CHAR // and assigns the alias to the first matching size, so we should check in this order. @@ -343,7 +343,7 @@ struct npy_api { /** * End modification */ - + private: enum functions { API_PyArray_GetNDArrayCFeatureVersion = 211, @@ -374,9 +374,10 @@ struct npy_api { */ API_PyDatetimeArrType = 215, - /** - * End modification - */ + + /** + * End modification + */ #ifdef PYBIND11_NUMPY_1_ONLY API_PyArray_GetArrayParamsFromObject = 278, @@ -420,17 +421,6 @@ struct npy_api { #endif DECL_NPY_API(PyArray_SetBaseObject); - /** - * Begin modification by Leon Mergen, 2019-02-20, for PyDatetimeScalarObject - * support. - */ - - DECL_NPY_API(PyDatetimeArrType); - - /** - * End modification - */ - #undef DECL_NPY_API return api; } @@ -953,7 +943,11 @@ class array : public buffer { template array(ShapeContainer shape, StridesContainer strides, const T *ptr, handle base = handle()) - : array(pybind11::dtype::of(), std::move(shape), std::move(strides), ptr, base) {} + : array(pybind11::dtype::of(), + std::move(shape), + std::move(strides), + reinterpret_cast(ptr), + base) {} template array(ShapeContainer shape, const T *ptr, handle base = handle()) @@ -2038,7 +2032,7 @@ struct vectorize_helper { // Pointers to values the function was called with; the vectorized ones set here will start // out as array_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 params{{&args...}}; + std::array params{{reinterpret_cast(&args)...}}; // The array of `buffer_info`s of vectorized arguments: std::array buffers{ diff --git a/thirdparty/pybind11/include/pybind11/pybind11.h b/thirdparty/pybind11/include/pybind11/pybind11.h index 74919a7d..5219c0ff 100644 --- a/thirdparty/pybind11/include/pybind11/pybind11.h +++ b/thirdparty/pybind11/include/pybind11/pybind11.h @@ -9,8 +9,8 @@ */ #pragma once - #include "detail/class.h" +#include "detail/exception_translation.h" #include "detail/init.h" #include "attr.h" #include "gil.h" @@ -95,24 +95,6 @@ inline std::string replace_newlines_and_squash(const char *text) { 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 -// available, they should be tried. -inline bool apply_exception_translators(std::forward_list &translators) { - auto last_exception = std::current_exception(); - - for (auto &translator : translators) { - try { - translator(last_exception); - return true; - } catch (...) { - last_exception = std::current_exception(); - } - } - return false; -} - #if defined(_MSC_VER) # define PYBIND11_COMPAT_STRDUP _strdup #else @@ -610,7 +592,8 @@ class cpp_function : public function { int index = 0; /* Create a nice pydoc rec including all signatures and docstrings of the functions in the overload chain */ - if (chain && options::show_function_signatures()) { + if (chain && options::show_function_signatures() + && std::strcmp(rec->name, "_pybind11_conduit_v1_") != 0) { // First a generic signature signatures += rec->name; signatures += "(*args, **kwargs)\n"; @@ -619,7 +602,8 @@ class cpp_function : public function { // Then specific overload signatures bool first_user_def = true; for (auto *it = chain_start; it != nullptr; it = it->next) { - if (options::show_function_signatures()) { + if (options::show_function_signatures() + && std::strcmp(rec->name, "_pybind11_conduit_v1_") != 0) { if (index > 0) { signatures += '\n'; } @@ -1038,40 +1022,7 @@ class cpp_function : public function { throw; #endif } catch (...) { - /* When an exception is caught, give each registered exception - translator a chance to translate it to a Python exception. First - all module-local translators will be tried in reverse order of - registration. If none of the module-locale translators handle - the exception (or there are no module-locale translators) then - the global translators will be tried, also in reverse order of - registration. - - A translator may choose to do one of the following: - - - 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. - */ - - bool handled = with_internals([&](internals &internals) { - auto &local_exception_translators - = get_local_internals().registered_exception_translators; - if (detail::apply_exception_translators(local_exception_translators)) { - return true; - } - auto &exception_translators = internals.registered_exception_translators; - if (detail::apply_exception_translators(exception_translators)) { - return true; - } - return false; - }); - - if (handled) { - return nullptr; - } - - set_error(PyExc_SystemError, "Exception escaped from default exception translator!"); + try_translate_exceptions(); return nullptr; } @@ -1652,6 +1603,7 @@ class class_ : public detail::generic_type { = instances[std::type_index(typeid(type))]; }); } + def("_pybind11_conduit_v1_", cpp_conduit_method); } template ::value, int> = 0> diff --git a/thirdparty/pybind11/include/pybind11/pytypes.h b/thirdparty/pybind11/include/pybind11/pytypes.h index f26c307a..1e76d7bc 100644 --- a/thirdparty/pybind11/include/pybind11/pytypes.h +++ b/thirdparty/pybind11/include/pybind11/pytypes.h @@ -1259,6 +1259,7 @@ class sequence_fast_readonly { using pointer = arrow_proxy; sequence_fast_readonly(handle obj, ssize_t n) : ptr(PySequence_Fast_ITEMS(obj.ptr()) + n) {} + sequence_fast_readonly() = default; // NOLINTNEXTLINE(readability-const-return-type) // PR #3263 reference dereference() const { return *ptr; } @@ -1281,6 +1282,7 @@ class sequence_slow_readwrite { using pointer = arrow_proxy; sequence_slow_readwrite(handle obj, ssize_t index) : obj(obj), index(index) {} + sequence_slow_readwrite() = default; reference dereference() const { return {obj, static_cast(index)}; } void increment() { ++index; } diff --git a/thirdparty/pybind11/include/pybind11/stl/filesystem.h b/thirdparty/pybind11/include/pybind11/stl/filesystem.h index 85c131ef..c16a9ae5 100644 --- a/thirdparty/pybind11/include/pybind11/stl/filesystem.h +++ b/thirdparty/pybind11/include/pybind11/stl/filesystem.h @@ -4,11 +4,11 @@ #pragma once -#include "../pybind11.h" -#include "../detail/common.h" -#include "../detail/descr.h" -#include "../cast.h" -#include "../pytypes.h" +#include +#include +#include +#include +#include #include @@ -33,6 +33,13 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(detail) +#ifdef PYPY_VERSION +# define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...) (__VA_ARGS__) +#else +# define PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(...) \ + (reinterpret_cast(__VA_ARGS__)) +#endif + #if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM) template struct path_caster { @@ -72,7 +79,8 @@ struct path_caster { } PyObject *native = nullptr; if constexpr (std::is_same_v) { - if (PyUnicode_FSConverter(buf, &native) != 0) { + if (PyUnicode_FSConverter(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native)) + != 0) { if (auto *c_str = PyBytes_AsString(native)) { // AsString returns a pointer to the internal buffer, which // must not be free'd. @@ -80,7 +88,8 @@ struct path_caster { } } } else if constexpr (std::is_same_v) { - if (PyUnicode_FSDecoder(buf, &native) != 0) { + if (PyUnicode_FSDecoder(buf, PYBIND11_REINTERPRET_CAST_VOID_PTR_IF_NOT_PYPY(&native)) + != 0) { if (auto *c_str = PyUnicode_AsWideCharString(native, nullptr)) { // AsWideCharString returns a new string that must be free'd. value = c_str; // Copies the string. diff --git a/thirdparty/pybind11/include/pybind11/stl_bind.h b/thirdparty/pybind11/include/pybind11/stl_bind.h index 66c452ea..fcb48dea 100644 --- a/thirdparty/pybind11/include/pybind11/stl_bind.h +++ b/thirdparty/pybind11/include/pybind11/stl_bind.h @@ -180,7 +180,7 @@ void vector_modifiers( v.end()); try { v.shrink_to_fit(); - } catch (const std::exception &) { + } catch (const std::exception &) { // NOLINT(bugprone-empty-catch) // Do nothing } throw; diff --git a/thirdparty/pybind11/include/pybind11/typing.h b/thirdparty/pybind11/include/pybind11/typing.h index 1442cdc7..84aaf9f7 100644 --- a/thirdparty/pybind11/include/pybind11/typing.h +++ b/thirdparty/pybind11/include/pybind11/typing.h @@ -14,6 +14,8 @@ #include "cast.h" #include "pytypes.h" +#include + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(typing) @@ -98,7 +100,8 @@ class Never : public none { using none::none; }; -#if defined(__cpp_nontype_template_parameter_class) +#if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L +# define PYBIND11_TYPING_H_HAS_STRING_LITERAL template struct StringLiteral { constexpr StringLiteral(const char (&str)[N]) { std::copy_n(str, N, name); } @@ -222,7 +225,7 @@ struct handle_type_name { static constexpr auto name = const_name("Never"); }; -#if defined(__cpp_nontype_template_parameter_class) +#if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL) template struct handle_type_name> { static constexpr auto name = const_name("Literal[") diff --git a/thirdparty/pybind11/pybind11/__main__.py b/thirdparty/pybind11/pybind11/__main__.py index b656ce6f..0abc7e21 100644 --- a/thirdparty/pybind11/pybind11/__main__.py +++ b/thirdparty/pybind11/pybind11/__main__.py @@ -2,12 +2,35 @@ from __future__ import annotations import argparse +import re import sys import sysconfig from ._version import __version__ from .commands import get_cmake_dir, get_include, get_pkgconfig_dir +# This is the conditional used for os.path being posixpath +if "posix" in sys.builtin_module_names: + from shlex import quote +elif "nt" in sys.builtin_module_names: + # See https://github.com/mesonbuild/meson/blob/db22551ed9d2dd7889abea01cc1c7bba02bf1c75/mesonbuild/utils/universal.py#L1092-L1121 + # and the original documents: + # https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments and + # https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ + UNSAFE = re.compile("[ \t\n\r]") + + def quote(s: str) -> str: + if s and not UNSAFE.search(s): + return s + + # Paths cannot contain a '"' on Windows, so we don't need to worry + # about nuanced counting here. + return f'"{s}\\"' if s.endswith("\\") else f'"{s}"' +else: + + def quote(s: str) -> str: + return s + def print_includes() -> None: dirs = [ @@ -22,7 +45,7 @@ def print_includes() -> None: if d and d not in unique_dirs: unique_dirs.append(d) - print(" ".join("-I" + d for d in unique_dirs)) + print(" ".join(quote(f"-I{d}") for d in unique_dirs)) def main() -> None: @@ -54,9 +77,9 @@ def main() -> None: if args.includes: print_includes() if args.cmakedir: - print(get_cmake_dir()) + print(quote(get_cmake_dir())) if args.pkgconfigdir: - print(get_pkgconfig_dir()) + print(quote(get_pkgconfig_dir())) if __name__ == "__main__": diff --git a/thirdparty/pybind11/pybind11/_version.py b/thirdparty/pybind11/pybind11/_version.py index 18b72c07..c298836b 100644 --- a/thirdparty/pybind11/pybind11/_version.py +++ b/thirdparty/pybind11/pybind11/_version.py @@ -8,5 +8,5 @@ def _to_int(s: str) -> int | str: return s -__version__ = "2.13.1" +__version__ = "2.13.6" version_info = tuple(_to_int(s) for s in __version__.split(".")) diff --git a/thirdparty/pybind11/tools/pybind11Common.cmake b/thirdparty/pybind11/tools/pybind11Common.cmake index d8e18e67..7d8d94b1 100644 --- a/thirdparty/pybind11/tools/pybind11Common.cmake +++ b/thirdparty/pybind11/tools/pybind11Common.cmake @@ -2,7 +2,7 @@ Adds the following targets:: - pybind11::pybind11 - link to headers and pybind11 + pybind11::pybind11 - link to Python headers and pybind11::headers pybind11::module - Adds module links pybind11::embed - Adds embed links pybind11::lto - Link time optimizations (only if CMAKE_INTERPROCEDURAL_OPTIMIZATION is not set) @@ -75,6 +75,32 @@ set_property( APPEND PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11) +# -------------- emscripten requires exceptions enabled ------------- +# _pybind11_no_exceptions is a private mechanism to disable this addition. +# Please open an issue if you need to use it; it will be removed if no one +# needs it. +if(CMAKE_SYSTEM_NAME MATCHES Emscripten AND NOT _pybind11_no_exceptions) + if(CMAKE_VERSION VERSION_LESS 3.13) + message(WARNING "CMake 3.13+ is required to build for Emscripten. Some flags will be missing") + else() + if(is_config) + set(_tmp_config_target pybind11::pybind11_headers) + else() + set(_tmp_config_target pybind11_headers) + endif() + + set_property( + TARGET ${_tmp_config_target} + APPEND + PROPERTY INTERFACE_LINK_OPTIONS -fexceptions) + set_property( + TARGET ${_tmp_config_target} + APPEND + PROPERTY INTERFACE_COMPILE_OPTIONS -fexceptions) + unset(_tmp_config_target) + endif() +endif() + # --------------------------- link helper --------------------------- add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global}) @@ -329,13 +355,13 @@ function(_pybind11_generate_lto target prefer_thin_lto) if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "mips64") # Do nothing - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES emscripten) + elseif(CMAKE_SYSTEM_NAME MATCHES Emscripten) # This compile is very costly when cross-compiling, so set this without checking set(PYBIND11_LTO_CXX_FLAGS "-flto${thin}${cxx_append}") set(PYBIND11_LTO_LINKER_FLAGS "-flto${thin}${linker_append}") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") _pybind11_return_if_cxx_and_linker_flags_work( - HAS_FLTO_THIN "-flto${thin}${cxx_append}" "-flto=${thin}${linker_append}" + HAS_FLTO_THIN "-flto${thin}${cxx_append}" "-flto${thin}${linker_append}" PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) endif() if(NOT HAS_FLTO_THIN) diff --git a/thirdparty/pybind11/tools/pybind11Config.cmake.in b/thirdparty/pybind11/tools/pybind11Config.cmake.in index 304f1d90..2d9fa94f 100644 --- a/thirdparty/pybind11/tools/pybind11Config.cmake.in +++ b/thirdparty/pybind11/tools/pybind11Config.cmake.in @@ -84,7 +84,7 @@ you can either use the basic targets, or use the FindPython tools: # Python method: Python_add_library(MyModule2 src2.cpp) - target_link_libraries(MyModule2 pybind11::headers) + target_link_libraries(MyModule2 PUBLIC pybind11::headers) set_target_properties(MyModule2 PROPERTIES INTERPROCEDURAL_OPTIMIZATION ON CXX_VISIBILITY_PRESET ON From c839b9ca19403f1530cabb691b543de3682a1fb3 Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Thu, 24 Apr 2025 16:23:18 +0700 Subject: [PATCH 4/6] Merge --- docker/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 8800dcf3..c84bbf4e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,9 +4,6 @@ ARG PLATFORM="${POLICY}_${ARCH}" FROM quay.io/pypa/$PLATFORM -ARG GCC_TOOLSET_VERSION="12" -ENV PATH="/opt/rh/devtoolset-$GCC_TOOLSET_VERSION/root/usr/bin:$PATH" - ARG PYTHON_VERSION ADD set-python-version.sh /set-python-version.sh From 043aee88f0c16894c2fc2cb4d83be50c5dc0554b Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Thu, 24 Apr 2025 16:29:22 +0700 Subject: [PATCH 5/6] Fix --- thirdparty/pybind11/include/pybind11/numpy.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/thirdparty/pybind11/include/pybind11/numpy.h b/thirdparty/pybind11/include/pybind11/numpy.h index 219eb6ba..c3c35cb2 100644 --- a/thirdparty/pybind11/include/pybind11/numpy.h +++ b/thirdparty/pybind11/include/pybind11/numpy.h @@ -421,6 +421,17 @@ struct npy_api { #endif DECL_NPY_API(PyArray_SetBaseObject); + /** + * Begin modification by Leon Mergen, 2019-02-20, for PyDatetimeScalarObject + * support. + */ + + DECL_NPY_API(PyDatetimeArrType); + + /** + * End modification + */ + #undef DECL_NPY_API return api; } From af6f5202cb5199cf181bb597a52c24fe6028533c Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Thu, 24 Apr 2025 16:30:56 +0700 Subject: [PATCH 6/6] Don't install custom dev toolset version, it already defaults to GCC14 --- docker/Dockerfile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c84bbf4e..e7ef8bb4 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -9,11 +9,3 @@ ARG PYTHON_VERSION ADD set-python-version.sh /set-python-version.sh RUN bash /set-python-version.sh ${PYTHON_VERSION} \ && rm /set-python-version.sh - -RUN yum install -y gcc-toolset-$GCC_TOOLSET_VERSION \ - gcc-toolset-$GCC_TOOLSET_VERSION-runtime \ - gcc-toolset-$GCC_TOOLSET_VERSION-binutils \ - gcc-toolset-$GCC_TOOLSET_VERSION-gcc \ - gcc-toolset-$GCC_TOOLSET_VERSION-gcc-c++ \ - gcc-toolset-$GCC_TOOLSET_VERSION-libstdc++-devel \ - && g++ --version