diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e1946da99..7aead4570 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,10 +72,9 @@ jobs: - uses: actions/checkout@v4 - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - allow-prereleases: true - name: Setup Boost (Linux) # Can't use boost + define _ @@ -209,7 +208,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 }} @@ -739,7 +738,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.x" @@ -792,7 +791,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} architecture: x86 @@ -845,7 +844,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} architecture: x86 @@ -893,7 +892,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} @@ -973,7 +972,10 @@ jobs: - name: Configure C++11 # LTO leads to many undefined reference like # `pybind11::detail::function_call::function_call(pybind11::detail::function_call&&) - run: cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=11 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -S . -B build + run: >- + cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=11 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON + -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") + -S . -B build - name: Build C++11 run: cmake --build build -j 2 @@ -991,7 +993,10 @@ jobs: run: git clean -fdx - name: Configure C++14 - run: cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=14 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -S . -B build2 + run: >- + cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=14 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON + -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") + -S . -B build2 - name: Build C++14 run: cmake --build build2 -j 2 @@ -1009,7 +1014,10 @@ jobs: run: git clean -fdx - name: Configure C++17 - run: cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=17 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON -S . -B build3 + run: >- + cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=17 -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON + -DPYTHON_EXECUTABLE=$(python -c "import sys; print(sys.executable)") + -S . -B build3 - name: Build C++17 run: cmake --build build3 -j 2 @@ -1045,7 +1053,7 @@ jobs: uses: egor-tensin/setup-clang@v1 - name: Setup Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index a49d8d252..7fd320fef 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -52,7 +52,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Python 3.7 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.7 architecture: ${{ matrix.arch }} diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 9b2da5944..2a520d6f4 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.x" - name: Add matchers diff --git a/.github/workflows/pip.yml b/.github/workflows/pip.yml index 5bc7c4b9c..19baf57d9 100644 --- a/.github/workflows/pip.yml +++ b/.github/workflows/pip.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup 🐍 3.6 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.6 @@ -53,7 +53,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup 🐍 3.8 - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.8 @@ -73,13 +73,13 @@ jobs: run: twine check dist/* - name: Save standard package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: standard path: dist/pybind11-* - name: Save global package - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: global path: dist/pybind11_global-* @@ -94,12 +94,12 @@ jobs: needs: [packaging] steps: - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.x" # Downloads all to directories matching the artifact names - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 - name: Publish standard package uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml index 5d893cd85..1a5c3e4bd 100644 --- a/.github/workflows/upstream.yml +++ b/.github/workflows/upstream.yml @@ -13,13 +13,12 @@ concurrency: env: PIP_BREAK_SYSTEM_PACKAGES: 1 - PIP_ONLY_BINARY: ":all:" # For cmake: VERBOSE: 1 jobs: standard: - name: "🐍 3.12 latest • ubuntu-latest • x64" + name: "🐍 3.13 latest • ubuntu-latest • x64" runs-on: ubuntu-latest # Only runs when the 'python dev' label is selected if: "contains(github.event.pull_request.labels.*.name, 'python dev')" @@ -27,10 +26,11 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Setup Python 3.12 - uses: actions/setup-python@v4 + - name: Setup Python 3.13 + uses: actions/setup-python@v5 with: - python-version: "3.12-dev" + python-version: "3.13" + allow-prereleases: true - name: Setup Boost run: sudo apt-get install libboost-dev diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1c1531bb5..53f1a5ea1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,14 +25,14 @@ repos: # Clang format the codebase automatically - repo: https://github.com/pre-commit/mirrors-clang-format - rev: "v17.0.4" + rev: "v17.0.6" 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.1.4 + rev: v0.1.6 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.6.1" + rev: "v1.7.1" hooks: - id: mypy args: [] @@ -93,7 +93,7 @@ repos: # Avoid directional quotes - repo: https://github.com/sirosen/texthooks - rev: "0.6.2" + rev: "0.6.3" hooks: - id: fix-ligatures - id: fix-smartquotes diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a1199dd2..1e75e99eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,13 +12,13 @@ endif() cmake_minimum_required(VERSION 3.5) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() if(_pybind11_cmp0148) @@ -92,9 +92,15 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set(pybind11_system "") set_property(GLOBAL PROPERTY USE_FOLDERS ON) + if(CMAKE_VERSION VERSION_LESS "3.18") + set(_pybind11_findpython_default OFF) + else() + set(_pybind11_findpython_default ON) + endif() else() set(PYBIND11_MASTER_PROJECT OFF) set(pybind11_system SYSTEM) + set(_pybind11_findpython_default OFF) endif() # Options @@ -116,9 +122,18 @@ cmake_dependent_option( "Install pybind11 headers in Python include directory instead of default installation prefix" OFF "PYBIND11_INSTALL" OFF) -cmake_dependent_option(PYBIND11_FINDPYTHON "Force new FindPython" OFF +cmake_dependent_option(PYBIND11_FINDPYTHON "Force new FindPython" ${_pybind11_findpython_default} "NOT CMAKE_VERSION VERSION_LESS 3.12" OFF) +# Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests +# (makes transition easier while we support both modes). +if(PYBIND11_MASTER_PROJECT + AND PYBIND11_FINDPYTHON + AND DEFINED PYTHON_EXECUTABLE + AND NOT DEFINED Python_EXECUTABLE) + set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}") +endif() + # NB: when adding a header don't forget to also add it to setup.py set(PYBIND11_HEADERS include/pybind11/detail/class.h diff --git a/docs/advanced/embedding.rst b/docs/advanced/embedding.rst index e6a1686f8..4cb6ebc68 100644 --- a/docs/advanced/embedding.rst +++ b/docs/advanced/embedding.rst @@ -18,7 +18,7 @@ information, see :doc:`/compiling`. .. code-block:: cmake - cmake_minimum_required(VERSION 3.5...3.26) + cmake_minimum_required(VERSION 3.5...3.27) project(example) find_package(pybind11 REQUIRED) # or `add_subdirectory(pybind11)` diff --git a/docs/compiling.rst b/docs/compiling.rst index 9d53904c4..f6a21691d 100644 --- a/docs/compiling.rst +++ b/docs/compiling.rst @@ -241,7 +241,7 @@ extension module can be created with just a few lines of code: .. code-block:: cmake - cmake_minimum_required(VERSION 3.5...3.26) + cmake_minimum_required(VERSION 3.5...3.27) project(example LANGUAGES CXX) add_subdirectory(pybind11) @@ -498,7 +498,7 @@ You can use these targets to build complex applications. For example, the .. code-block:: cmake - cmake_minimum_required(VERSION 3.5...3.26) + cmake_minimum_required(VERSION 3.5...3.27) project(example LANGUAGES CXX) find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11) @@ -556,7 +556,7 @@ information about usage in C++, see :doc:`/advanced/embedding`. .. code-block:: cmake - cmake_minimum_required(VERSION 3.5...3.26) + cmake_minimum_required(VERSION 3.5...3.27) project(example LANGUAGES CXX) find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11) diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index b31727167..0b9ea42db 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -86,17 +86,16 @@ inline PyTypeObject *make_static_property_type() { type->tp_descr_get = pybind11_static_get; type->tp_descr_set = pybind11_static_set; - if (PyType_Ready(type) < 0) { - pybind11_fail("make_static_property_type(): failure in PyType_Ready()!"); - } - # if PY_VERSION_HEX >= 0x030C0000 - // PRE 3.12 FEATURE FREEZE. PLEASE REVIEW AFTER FREEZE. // Since Python-3.12 property-derived types are required to // have dynamic attributes (to set `__doc__`) enable_dynamic_attributes(heap_type); # endif + if (PyType_Ready(type) < 0) { + pybind11_fail("make_static_property_type(): failure in PyType_Ready()!"); + } + setattr((PyObject *) type, "__module__", str("pybind11_builtins")); PYBIND11_SET_OLDPY_QUALNAME(type, name_obj); @@ -520,8 +519,12 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) { /// dynamic_attr: Allow the garbage collector to traverse the internal instance `__dict__`. extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) { +#if PY_VERSION_HEX >= 0x030D0000 + PyObject_VisitManagedDict(self, visit, arg); +#else PyObject *&dict = *_PyObject_GetDictPtr(self); Py_VISIT(dict); +#endif // https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse #if PY_VERSION_HEX >= 0x03090000 Py_VISIT(Py_TYPE(self)); @@ -531,8 +534,12 @@ extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *a /// dynamic_attr: Allow the GC to clear the dictionary. extern "C" inline int pybind11_clear(PyObject *self) { +#if PY_VERSION_HEX >= 0x030D0000 + PyObject_ClearManagedDict(self); +#else PyObject *&dict = *_PyObject_GetDictPtr(self); Py_CLEAR(dict); +#endif return 0; } 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/CMakeLists.txt b/tests/CMakeLists.txt index 3632194ee..ab1975742 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,13 +7,13 @@ cmake_minimum_required(VERSION 3.5) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() # Filter out items; print an optional message if any items filtered. This ignores extensions. diff --git a/tests/requirements.txt b/tests/requirements.txt index 83a3690ad..e056c6fa8 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -7,9 +7,9 @@ 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" +numpy~=1.26.0; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13" pytest~=7.0 pytest-timeout 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" +scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13" diff --git a/tests/test_cmake_build/CMakeLists.txt b/tests/test_cmake_build/CMakeLists.txt index e5aa975cf..f28bde08e 100644 --- a/tests/test_cmake_build/CMakeLists.txt +++ b/tests/test_cmake_build/CMakeLists.txt @@ -5,9 +5,8 @@ function(pybind11_add_build_test name) set(build_options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}") + list(APPEND build_options "-DPYBIND11_FINDPYTHON=${PYBIND11_FINDPYTHON}") if(PYBIND11_FINDPYTHON) - list(APPEND build_options "-DPYBIND11_FINDPYTHON=${PYBIND11_FINDPYTHON}") - if(DEFINED Python_ROOT_DIR) list(APPEND build_options "-DPython_ROOT_DIR=${Python_ROOT_DIR}") endif() diff --git a/tests/test_cmake_build/installed_embed/CMakeLists.txt b/tests/test_cmake_build/installed_embed/CMakeLists.txt index d9dcb45e4..89207a36d 100644 --- a/tests/test_cmake_build/installed_embed/CMakeLists.txt +++ b/tests/test_cmake_build/installed_embed/CMakeLists.txt @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 3.5) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() project(test_installed_embed CXX) diff --git a/tests/test_cmake_build/installed_function/CMakeLists.txt b/tests/test_cmake_build/installed_function/CMakeLists.txt index 2f4f64275..e752494e6 100644 --- a/tests/test_cmake_build/installed_function/CMakeLists.txt +++ b/tests/test_cmake_build/installed_function/CMakeLists.txt @@ -1,13 +1,13 @@ cmake_minimum_required(VERSION 3.5) project(test_installed_module CXX) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() project(test_installed_function CXX) diff --git a/tests/test_cmake_build/installed_target/CMakeLists.txt b/tests/test_cmake_build/installed_target/CMakeLists.txt index a981e236f..3f7eb514e 100644 --- a/tests/test_cmake_build/installed_target/CMakeLists.txt +++ b/tests/test_cmake_build/installed_target/CMakeLists.txt @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 3.5) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() project(test_installed_target CXX) diff --git a/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt b/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt index f286746b9..7e7133435 100644 --- a/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt +++ b/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 3.5) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() project(test_subdirectory_embed CXX) @@ -16,6 +16,12 @@ set(PYBIND11_INSTALL CACHE BOOL "") set(PYBIND11_EXPORT_NAME test_export) +# Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests +# (makes transition easier while we support both modes). +if(DEFINED PYTHON_EXECUTABLE AND NOT DEFINED Python_EXECUTABLE) + set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}") +endif() + add_subdirectory("${pybind11_SOURCE_DIR}" pybind11) # Test basic target functionality diff --git a/tests/test_cmake_build/subdirectory_function/CMakeLists.txt b/tests/test_cmake_build/subdirectory_function/CMakeLists.txt index 275a75c0b..56b8b3d98 100644 --- a/tests/test_cmake_build/subdirectory_function/CMakeLists.txt +++ b/tests/test_cmake_build/subdirectory_function/CMakeLists.txt @@ -1,16 +1,22 @@ cmake_minimum_required(VERSION 3.5) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() project(test_subdirectory_function CXX) +# Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests +# (makes transition easier while we support both modes). +if(DEFINED PYTHON_EXECUTABLE AND NOT DEFINED Python_EXECUTABLE) + set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}") +endif() + add_subdirectory("${pybind11_SOURCE_DIR}" pybind11) pybind11_add_module(test_subdirectory_function ../main.cpp) set_target_properties(test_subdirectory_function PROPERTIES OUTPUT_NAME test_cmake_build) diff --git a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt index 37bb2c56e..72d880b37 100644 --- a/tests/test_cmake_build/subdirectory_target/CMakeLists.txt +++ b/tests/test_cmake_build/subdirectory_target/CMakeLists.txt @@ -1,16 +1,22 @@ cmake_minimum_required(VERSION 3.5) -# The `cmake_minimum_required(VERSION 3.5...3.26)` syntax does not work with +# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with # some versions of VS that have a patched CMake 3.11. This forces us to emulate # the behavior using the following workaround: -if(${CMAKE_VERSION} VERSION_LESS 3.26) +if(${CMAKE_VERSION} VERSION_LESS 3.27) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) else() - cmake_policy(VERSION 3.26) + cmake_policy(VERSION 3.27) endif() project(test_subdirectory_target CXX) +# Allow PYTHON_EXECUTABLE if in FINDPYTHON mode and building pybind11's tests +# (makes transition easier while we support both modes). +if(DEFINED PYTHON_EXECUTABLE AND NOT DEFINED Python_EXECUTABLE) + set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}") +endif() + add_subdirectory("${pybind11_SOURCE_DIR}" pybind11) add_library(test_subdirectory_target MODULE ../main.cpp) 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 diff --git a/tools/pybind11NewTools.cmake b/tools/pybind11NewTools.cmake index 4b6948631..cd88a6450 100644 --- a/tools/pybind11NewTools.cmake +++ b/tools/pybind11NewTools.cmake @@ -54,7 +54,7 @@ if(NOT Python_FOUND AND NOT Python3_FOUND) # 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 - AND NOT Python_ARTIFACTS_INTERACTIVE + AND Python_ARTIFACTS_INTERACTIVE AND _pybind11_global_keyword STREQUAL "") if(TARGET Python::Python) set_property(TARGET Python::Python PROPERTY IMPORTED_GLOBAL TRUE)