From b389ae77cb8a872d62e96d5f38ce020480140033 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Wed, 15 Nov 2023 18:59:07 -0500 Subject: [PATCH 1/7] chore: update changelog script for categories (#4942) --- tools/make_changelog.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tools/make_changelog.py b/tools/make_changelog.py index b5bd83294..3cdf47e88 100755 --- a/tools/make_changelog.py +++ b/tools/make_changelog.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +from __future__ import annotations import re @@ -29,6 +30,18 @@ issues_pages = ghapi.page.paged( ) issues = (issue for page in issues_pages for issue in page) missing = [] +cats_descr = { + "feat": "New Features", + "fix": "Bug fixes", + "fix(types)": "", + "fix(cmake)": "", + "docs": "Documentation", + "tests": "Tests", + "ci": "CI", + "chore": "Other", + "unknown": "Uncategorised", +} +cats: dict[str, list[str]] = {c: [] for c in cats_descr} for issue in issues: changelog = ENTRY.findall(issue.body or "") @@ -36,14 +49,27 @@ for issue in issues: missing.append(issue) else: (msg,) = changelog + if msg.startswith("- "): + msg = msg[2:] if not msg.startswith("* "): msg = "* " + msg if not msg.endswith("."): msg += "." msg += f"\n `#{issue.number} <{issue.html_url}>`_" + for cat in cats: + if issue.title.lower().startswith(f"{cat}:"): + cats[cat].append(msg) + break + else: + cats["unknown"].append(msg) - print(Syntax(msg, "rst", theme="ansi_light", word_wrap=True)) +for cat, msgs in cats.items(): + if msgs: + desc = cats_descr[cat] + print(f"[bold]{desc}:\n" if desc else "") + for msg in msgs: + print(Syntax(msg, "rst", theme="ansi_light", word_wrap=True)) print() if missing: From 6cf90e7286cf423be72b98efd0f949463a0ea007 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Thu, 16 Nov 2023 00:50:15 -0500 Subject: [PATCH 2/7] fix(cmake): avoid really slow compile on emscripten (#4642) * fix: avoid really slow compile on emscripten Signed-off-by: Henry Schreiner * Update tools/pybind11Common.cmake --------- Signed-off-by: Henry Schreiner --- tools/pybind11Common.cmake | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake index 308d1b70d..f921970b6 100644 --- a/tools/pybind11Common.cmake +++ b/tools/pybind11Common.cmake @@ -300,21 +300,24 @@ function(_pybind11_generate_lto target prefer_thin_lto) set(cxx_append ";-fno-fat-lto-objects") endif() - if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "mips64") - set(NO_FLTO_ARCH TRUE) + if(prefer_thin_lto) + set(thin "=thin") else() - set(NO_FLTO_ARCH FALSE) + set(thin "") endif() - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" - AND prefer_thin_lto - AND NOT NO_FLTO_ARCH) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "mips64") + # Do nothing + elseif(CMAKE_SYSTEM_PROCESSOR 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 AND NOT NO_FLTO_ARCH) + if(NOT HAS_FLTO_THIN) _pybind11_return_if_cxx_and_linker_flags_work( HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) From 6831666f5c3b2b06035187342567a1dd544115ab Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Thu, 16 Nov 2023 00:52:05 -0500 Subject: [PATCH 3/7] ci: add more versions of numpy/scipy/pypy (#4714) * ci: add more versions of numpy/scipy/pypy Signed-off-by: Henry Schreiner * Apply suggestions from code review * style: pre-commit fixes * Update requirements.txt * Update requirements.txt * Apply suggestions from code review --------- Signed-off-by: Henry Schreiner Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- noxfile.py | 2 +- tests/requirements.txt | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/noxfile.py b/noxfile.py index 021ced245..f95b64912 100644 --- a/noxfile.py +++ b/noxfile.py @@ -57,7 +57,7 @@ def tests_packaging(session: nox.Session) -> None: Run the packaging tests. """ - session.install("-r", "tests/requirements.txt", "--prefer-binary") + session.install("-r", "tests/requirements.txt") session.run("pytest", "tests/extra_python_package", *session.posargs) diff --git a/tests/requirements.txt b/tests/requirements.txt index 09063e768..83a3690ad 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,10 +1,15 @@ -build==0.8.0 -numpy==1.21.5; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7" -numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6" -numpy==1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10" -numpy==1.22.2; platform_python_implementation!="PyPy" and python_version>="3.10" and python_version<"3.11" -pytest==7.0.0; platform_python_implementation!="PyPy" and python_version=="3.6" -pytest==7.2.0; platform_python_implementation!="PyPy" and python_version>="3.7" +--only-binary=:all: +build~=0.9; python_version=="3.6" +build~=1.0; python_version>="3.7" +numpy~=1.20.0; python_version=="3.7" and platform_python_implementation=="PyPy" +numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy" +numpy~=1.25.0; python_version=="3.9" and platform_python_implementation=='PyPy' +numpy~=1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6" +numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10" +numpy~=1.22.2; platform_python_implementation!="PyPy" and python_version=="3.10" +numpy~=1.26.0; platform_python_implementation!="PyPy" and python_version>="3.11" +pytest~=7.0 pytest-timeout -scipy==1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10" -scipy==1.10.0; platform_python_implementation!="PyPy" and python_version=="3.10" +scipy~=1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10" +scipy~=1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10" +scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" From 9591cfb0b8dcf2aa213c8a44ac2c8b7eefa95342 Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Thu, 16 Nov 2023 00:54:47 -0500 Subject: [PATCH 4/7] fix(cmake): findpython issues and 3.12 support for pybind11_find_import (#4941) * fix(cmake): findpython issues and 3.12 support for pybind11_find_import Signed-off-by: Henry Schreiner * Update pybind11NewTools.cmake --------- Signed-off-by: Henry Schreiner --- tools/pybind11Common.cmake | 11 +++++++++-- tools/pybind11NewTools.cmake | 31 +++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake index f921970b6..50b15e11b 100644 --- a/tools/pybind11Common.cmake +++ b/tools/pybind11Common.cmake @@ -218,8 +218,15 @@ if(NOT _pybind11_nopython) execute_process( COMMAND - ${${_Python}_EXECUTABLE} -c - "from pkg_resources import get_distribution; print(get_distribution('${PYPI_NAME}').version)" + ${${_Python}_EXECUTABLE} -c " +try: + from importlib.metadata import version +except ImportError: + from pkg_resources import get_distribution + def version(s): + return get_distribution(s).version +print(version('${PYPI_NAME}')) + " RESULT_VARIABLE RESULT_PRESENT OUTPUT_VARIABLE PKG_VERSION ERROR_QUIET) diff --git a/tools/pybind11NewTools.cmake b/tools/pybind11NewTools.cmake index 9106762fc..4b6948631 100644 --- a/tools/pybind11NewTools.cmake +++ b/tools/pybind11NewTools.cmake @@ -39,12 +39,23 @@ if(NOT Python_FOUND AND NOT Python3_FOUND) set(_pybind11_dev_component Development.Module OPTIONAL_COMPONENTS Development.Embed) endif() + # Callers need to be able to access Python_EXECUTABLE + set(_pybind11_global_keyword "") + if(NOT is_config AND NOT DEFINED Python_ARTIFACTS_INTERACTIVE) + set(Python_ARTIFACTS_INTERACTIVE TRUE) + if(NOT CMAKE_VERSION VERSION_LESS 3.24) + set(_pybind11_global_keyword "GLOBAL") + endif() + endif() + find_package(Python 3.6 REQUIRED COMPONENTS Interpreter ${_pybind11_dev_component} - ${_pybind11_quiet}) + ${_pybind11_quiet} ${_pybind11_global_keyword}) # If we are in submodule mode, export the Python targets to global targets. # If this behavior is not desired, FindPython _before_ pybind11. - if(NOT is_config) + if(NOT is_config + AND NOT Python_ARTIFACTS_INTERACTIVE + AND _pybind11_global_keyword STREQUAL "") if(TARGET Python::Python) set_property(TARGET Python::Python PROPERTY IMPORTED_GLOBAL TRUE) endif() @@ -53,6 +64,22 @@ if(NOT Python_FOUND AND NOT Python3_FOUND) set_property(TARGET Python::Module PROPERTY IMPORTED_GLOBAL TRUE) endif() endif() + + # Explicitly export version for callers (including our own functions) + if(NOT is_config AND Python_ARTIFACTS_INTERACTIVE) + set(Python_VERSION + "${Python_VERSION}" + CACHE INTERNAL "") + set(Python_VERSION_MAJOR + "${Python_VERSION_MAJOR}" + CACHE INTERNAL "") + set(Python_VERSION_MINOR + "${Python_VERSION_MINOR}" + CACHE INTERNAL "") + set(Python_VERSION_PATCH + "${Python_VERSION_PATCH}" + CACHE INTERNAL "") + endif() endif() if(Python_FOUND) From dc9b39596d986aeb061bd3debe52d30e2467dc48 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 16 Nov 2023 05:55:14 +0000 Subject: [PATCH 5/7] pybind11.pc: use pcfiledir for relative destinations (#4830) * pybind11.pc: use pcfiledir for relative destinations If the datarootdir is absolute, just use the absolute path directly. However, if it is relative, we can compute the prefix from the location of the `.pc` file itself. This allows the install to be relocatable. * chore: use 3.20's cmake_path if available * style: pre-commit fixes * Update CMakeLists.txt --------- Co-authored-by: Henry Schreiner Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CMakeLists.txt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d2c44dc40..7a1199dd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,7 +289,21 @@ if(PYBIND11_INSTALL) # pkg-config support if(NOT prefix_for_pc_file) - set(prefix_for_pc_file "${CMAKE_INSTALL_PREFIX}") + if(IS_ABSOLUTE "${CMAKE_INSTALL_DATAROOTDIR}") + set(prefix_for_pc_file "${CMAKE_INSTALL_PREFIX}") + else() + set(pc_datarootdir "${CMAKE_INSTALL_DATAROOTDIR}") + if(CMAKE_VERSION VERSION_LESS 3.20) + set(prefix_for_pc_file "\${pcfiledir}/..") + while(pc_datarootdir) + get_filename_component(pc_datarootdir "${pc_datarootdir}" DIRECTORY) + string(APPEND prefix_for_pc_file "/..") + endwhile() + else() + cmake_path(RELATIVE_PATH CMAKE_INSTALL_PREFIX BASE_DIRECTORY CMAKE_INSTALL_DATAROOTDIR + OUTPUT_VARIABLE prefix_for_pc_file) + endif() + endif() endif() join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11.pc.in" From 4bb6163b4fc1299e6dc85f9436bd18a523dd099f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 15:37:43 -0800 Subject: [PATCH 6/7] chore(deps): bump deadsnakes/action from 3.0.1 to 3.1.0 (#4951) Bumps [deadsnakes/action](https://github.com/deadsnakes/action) from 3.0.1 to 3.1.0. - [Release notes](https://github.com/deadsnakes/action/releases) - [Commits](https://github.com/deadsnakes/action/compare/v3.0.1...v3.1.0) --- updated-dependencies: - dependency-name: deadsnakes/action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1946da99..407db89cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -209,7 +209,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Python ${{ matrix.python-version }} (deadsnakes) - uses: deadsnakes/action@v3.0.1 + uses: deadsnakes/action@v3.1.0 with: python-version: ${{ matrix.python-version }} debug: ${{ matrix.python-debug }} From a67d786571cc6d2c2ecec33985e00e6d22dc68e5 Mon Sep 17 00:00:00 2001 From: Antoine Prouvost Date: Wed, 29 Nov 2023 21:56:25 +0100 Subject: [PATCH 7/7] fix(stl_bind): Enable `bind_map` with `using` declarations. (#4952) * Enable `bind_map` with `using` declarations. * style: pre-commit fixes * Enable directives in bind_vector * Add tests for bind_ and using directives * style: pre-commit fixes * Remove C++17 functions * Fix test comment * Add minimal user like map py test --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- include/pybind11/stl_bind.h | 5 +-- tests/test_stl_binders.cpp | 70 +++++++++++++++++++++++++++++++++++++ tests/test_stl_binders.py | 14 ++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/include/pybind11/stl_bind.h b/include/pybind11/stl_bind.h index 49f1b7782..4d0854f6a 100644 --- a/include/pybind11/stl_bind.h +++ b/include/pybind11/stl_bind.h @@ -525,7 +525,7 @@ class_ bind_vector(handle scope, std::string const &name, A [](const Vector &v) -> bool { return !v.empty(); }, "Check whether the list is nonempty"); - cl.def("__len__", &Vector::size); + cl.def("__len__", [](const Vector &vec) { return vec.size(); }); #if 0 // C++ style functions deprecated, leaving it here as an example @@ -843,7 +843,8 @@ class_ bind_map(handle scope, const std::string &name, Args && m.erase(it); }); - cl.def("__len__", &Map::size); + // Always use a lambda in case of `using` declaration + cl.def("__len__", [](const Map &m) { return m.size(); }); return cl; } diff --git a/tests/test_stl_binders.cpp b/tests/test_stl_binders.cpp index 1681760aa..e52a03b6d 100644 --- a/tests/test_stl_binders.cpp +++ b/tests/test_stl_binders.cpp @@ -15,6 +15,7 @@ #include #include #include +#include class El { public: @@ -83,6 +84,71 @@ struct RecursiveMap : std::map { using Parent::Parent; }; +class UserVectorLike : private std::vector { +public: + // This is only a subset of the member functions, as needed at the time. + using Base = std::vector; + using typename Base::const_iterator; + using typename Base::difference_type; + using typename Base::iterator; + using typename Base::size_type; + using typename Base::value_type; + + using Base::at; + using Base::back; + using Base::Base; + using Base::begin; + using Base::cbegin; + using Base::cend; + using Base::clear; + using Base::empty; + using Base::end; + using Base::erase; + using Base::front; + using Base::insert; + using Base::pop_back; + using Base::push_back; + using Base::reserve; + using Base::shrink_to_fit; + using Base::swap; + using Base::operator[]; + using Base::capacity; + using Base::size; +}; + +bool operator==(UserVectorLike const &, UserVectorLike const &) { return true; } +bool operator!=(UserVectorLike const &, UserVectorLike const &) { return false; } + +class UserMapLike : private std::map { +public: + // This is only a subset of the member functions, as needed at the time. + using Base = std::map; + using typename Base::const_iterator; + using typename Base::iterator; + using typename Base::key_type; + using typename Base::mapped_type; + using typename Base::size_type; + using typename Base::value_type; + + using Base::at; + using Base::Base; + using Base::begin; + using Base::cbegin; + using Base::cend; + using Base::clear; + using Base::emplace; + using Base::emplace_hint; + using Base::empty; + using Base::end; + using Base::erase; + using Base::find; + using Base::insert; + using Base::max_size; + using Base::swap; + using Base::operator[]; + using Base::size; +}; + /* * Pybind11 does not catch more complicated recursion schemes, such as mutual * recursion. @@ -173,6 +239,10 @@ TEST_SUBMODULE(stl_binders, m) { py::bind_map(m, "MutuallyRecursiveContainerPairMV"); py::bind_vector(m, "MutuallyRecursiveContainerPairVM"); + // Bind with private inheritance + `using` directives. + py::bind_vector(m, "UserVectorLike"); + py::bind_map(m, "UserMapLike"); + // The rest depends on numpy: try { py::module_::import("numpy"); diff --git a/tests/test_stl_binders.py b/tests/test_stl_binders.py index 79923f482..c00d45b92 100644 --- a/tests/test_stl_binders.py +++ b/tests/test_stl_binders.py @@ -353,3 +353,17 @@ def test_recursive_map(): recursive_map[100][101] = m.RecursiveMap() recursive_map[100][102] = m.RecursiveMap() assert list(recursive_map[100].keys()) == [101, 102] + + +def test_user_vector_like(): + vec = m.UserVectorLike() + vec.append(2) + assert vec[0] == 2 + assert len(vec) == 1 + + +def test_user_like_map(): + map = m.UserMapLike() + map[33] = 44 + assert map[33] == 44 + assert len(map) == 1