feat: remove Python 3.7 support (#5191)

* First pass updating misc files, informed by https://github.com/pybind/pybind11/pull/5177/commits

* Remove jobs using silkeh/clang and gcc docker containers that come with Python 3.7

* Add silkeh/clang:17-bookworm

* Add job using GCC 7

* Revert "Add job using GCC 7"

This reverts commit 518515a761.

* Try running in ubuntu-18.04 container under ubuntu-latest (to get GCC 7)

* Fix `-` vs `:` mixup.

* This reverts commit b1c4304475.

Revert "Try running in ubuntu:18.04 container under ubuntu-latest (to get GCC 7)"

This reverts commit b203a294bb.

* `git grep 0x03080000` cleanup.

* `git grep -I -E '3\.7'` cleanup.

Removes two changes made under pybind/pybind11#3702

* Revert "`git grep -I -E '3\.7'` cleanup."

This reverts commit bb5b9d187b.

* Remove comments that are evidently incorrect:

```
...
-- The CXX compiler identification is Clang 15.0.7
...
- Found Python: /usr/bin/python3.9 (found suitable version "3.9.2", minimum required is "3.7") found components: Interpreter Development.Module Development.Embed
...
/__w/pybind11/pybind11/include/pybind11/gil.h:150:13: error: 'auto key' can be declared as 'auto *key' [readability-qualified-auto,-warnings-as-errors]
            auto key = internals.tstate;
            ^~~~~
            auto *
/__w/pybind11/pybind11/include/pybind11/gil.h:174:13: error: 'auto key' can be declared as 'auto *key' [readability-qualified-auto,-warnings-as-errors]
            auto key = detail::get_internals().tstate;
            ^~~~~
            auto *
```

* .github/workflows/configure.yml: Change from Python 3.7 to 3.8

* Misc cleanup pass

* Miscellaneous changes based on manual review of the `git grep` matches below:

```
git_grep_37_38.sh |& sort | uniq -c
```

With git_grep_37_38.sh:

```
set -x
git grep 0x0307
git grep 0x0308
git grep PY_MINOR_VERSION
git grep PYPY_VERSION
git grep -I -E '3\.7'
git grep -I -E '3\.8'
git grep -I -E '\(3, 7'
git grep -I -E '\(3, 8'
git grep -I -E '3[^A-Za-z0-9.]+7'
git grep -I -E '3[^A-Za-z0-9.]+8'
```

Output:

```
      1 .appveyor.yml:    $env:CMAKE_INCLUDE_PATH = "eigen-3.3.7;$env:CMAKE_INCLUDE_PATH"
      1 .appveyor.yml:    7z x eigen-3.3.7.zip -y > $null
      1 .appveyor.yml:    Start-FileDownload 'https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.zip'
      1 CMakeLists.txt:    # Bug in macOS CMake < 3.7 is unable to download catch
      1 CMakeLists.txt:  elseif(WINDOWS AND CMAKE_VERSION VERSION_LESS 3.8)
      1 CMakeLists.txt:  if(OSX AND CMAKE_VERSION VERSION_LESS 3.7)
      1 CMakeLists.txt:    message(WARNING "CMAKE 3.7+ needed on macOS to download catch, and newer HIGHLY recommended")
      1 CMakeLists.txt:    message(WARNING "CMAKE 3.8+ tested on Windows, previous versions untested")
      1 CMakeLists.txt:    # Only tested with 3.8+ in CI.
      1 docs/advanced/functions.rst:Python 3.8 introduced a new positional-only argument syntax, using ``/`` in the
      1 docs/changelog.rst:* Adapt pybind11 to a C API convention change in Python 3.8. `#1950
      1 docs/changelog.rst:* Allow thread termination to be avoided during shutdown for CPython 3.7+ via
      1 docs/changelog.rst:  considered as conversion, consistent with Python 3.8+.
      1 docs/changelog.rst:  CPython 3.8 and 3.9 debug builds.
      1 docs/changelog.rst:* Enum now has an ``__index__`` method on Python <3.8 too.
      1 docs/changelog.rst:  on Python 3.8. `#1780 <https://github.com/pybind/pybind11/pull/1780>`_.
      1 docs/changelog.rst:* PyPy 3.10 support was added, PyPy 3.7 support was dropped.
      2 docs/changelog.rst:* Support PyPy 7.3.7 and the PyPy3.8 beta. Test python-3.11 on PRs with the
      1 docs/changelog.rst:* Use ``macos-13`` (Intel) for CI jobs for now (will drop Python 3.7 soon).
      1 docs/changelog.rst:* Use new Python 3.7 Thread Specific Storage (TSS) implementation if available.
      1 docs/compiling.rst:    cmake -DPYBIND11_PYTHON_VERSION=3.8 ..
      1 docs/compiling.rst:    find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED)
      1 docs/limitations.rst:- PyPy3 7.3.1 and 7.3.2 have issues with several tests on 32-bit Windows.
      1 docs/requirements.txt:idna==3.7 \
      1 + git grep 0x0307
      1 + git grep 0x0308
      1 + git grep -I -E '\(3, 7'
      1 + git grep -I -E '3\.7'
      1 + git grep -I -E '\(3, 8'
      1 + git grep -I -E '3\.8'
      1 + git grep -I -E '3[^A-Za-z0-9.]+7'
      1 + git grep -I -E '3[^A-Za-z0-9.]+8'
      1 + git grep PY_MINOR_VERSION
      1 + git grep PYPY_VERSION
      2 .github/workflows/ci.yml:        - '3.8'
      1 .github/workflows/ci.yml:        - 3.8
      1 .github/workflows/ci.yml:    - name: Add Python 3.8
      1 .github/workflows/ci.yml:        - 'pypy-3.8'
      2 .github/workflows/ci.yml:            python: '3.8'
      1 .github/workflows/ci.yml:          - python: '3.8'
      1 .github/workflows/ci.yml:          - python: 3.8
      1 .github/workflows/ci.yml:            python: 'pypy-3.8'
      1 .github/workflows/configure.yml:          cmake: "3.8"
      1 .github/workflows/configure.yml:    name: 🐍 3.8 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }}
      1 .github/workflows/configure.yml:    - name: Setup Python 3.8
      1 .github/workflows/configure.yml:        python-version: 3.8
      1 .github/workflows/pip.yml:    name: 🐍 3.8 • 📦 & 📦 tests • ubuntu-latest
      1 .github/workflows/pip.yml:    name: 🐍 3.8 • 📦 tests • windows-latest
      2 .github/workflows/pip.yml:    - name: Setup 🐍 3.8
      2 .github/workflows/pip.yml:        python-version: 3.8
      2 include/pybind11/cast.h:#if !defined(PYPY_VERSION)
      2 include/pybind11/cast.h:#if defined(PYPY_VERSION)
      2 include/pybind11/cast.h:            // PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
      5 include/pybind11/detail/class.h:#if !defined(PYPY_VERSION)
      1 include/pybind11/detail/class.h:#if defined(PYPY_VERSION)
      1 include/pybind11/detail/class.h:    // This was not needed before Python 3.8 (Python issue 35810)
      1 include/pybind11/detail/common.h:    && !defined(PYPY_VERSION) && !defined(PYBIND11_ASSERT_GIL_HELD_INCREF_DECREF)
      2 include/pybind11/detail/common.h:#    error "PYTHON < 3.8 IS UNSUPPORTED. pybind11 v2.13 was the last to support Python 3.7."
      1 include/pybind11/detail/common.h:#if defined(PYPY_VERSION) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
      1 include/pybind11/detail/common.h:#if PY_VERSION_HEX < 0x03080000
      1 include/pybind11/detail/common.h:            = PYBIND11_TOSTRING(PY_MAJOR_VERSION) "." PYBIND11_TOSTRING(PY_MINOR_VERSION);        \
      1 include/pybind11/detail/internals.h:        // called. PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does
      1 include/pybind11/detail/internals.h:#if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION)
      1 include/pybind11/detail/internals.h:// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
      1 include/pybind11/detail/type_caster_base.h:#if defined(PYPY_VERSION)
      1 include/pybind11/embed.h:#    define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
      1 include/pybind11/embed.h:#if defined(PYPY_VERSION)
      1 include/pybind11/eval.h:    // globals if not yet present.  Python 3.8 made PyRun_String behave
      2 include/pybind11/eval.h:#if defined(PYPY_VERSION)
      2 include/pybind11/eval.h:    // was missing from PyPy3.8 7.3.7.
      2 include/pybind11/gil.h:    /// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
      1 include/pybind11/pybind11.h:#if !defined(PYPY_VERSION)
      4 include/pybind11/pybind11.h:#if !defined(PYPY_VERSION) && PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 9
      1 include/pybind11/pytypes.h:#endif //! defined(PYPY_VERSION)
      2 include/pybind11/pytypes.h:#if !defined(PYPY_VERSION)
      1 include/pybind11/pytypes.h:#    if defined(PYPY_VERSION_NUM) && PYPY_VERSION_NUM < 0x07030a00
      1 include/pybind11/pytypes.h:#ifdef PYPY_VERSION
      1 include/pybind11/stl/filesystem.h:#    if !defined(PYPY_VERSION)
      2 pybind11/__init__.py:if sys.version_info < (3, 8):
      2 pybind11/__init__.py:    msg = "pybind11 does not support Python < 3.8. v2.13 was the last release supporting Python 3.7."
      1 pyproject.toml:master.py-version = "3.8"
      1 pyproject.toml:python_version = "3.8"
      1 README.rst:lines of code and depend on Python (3.8+, or PyPy) and the C++
      2 README.rst:- Python 3.8+, and PyPy3 7.3 are supported with an implementation-agnostic
      1 setup.cfg:    Programming Language :: Python :: 3.8
      1 setup.cfg:python_requires = >=3.8
      1 setup.py:# TODO: use literals & overload (typing extensions or Python 3.8)
      1 tests/CMakeLists.txt:if(NOT CMAKE_VERSION VERSION_LESS 3.8)
      2 tests/constructor_stats.h:#if defined(PYPY_VERSION)
      1 tests/env.py:    doesn't work on CPython 3.8.0 with pytest==3.3.2 on Ubuntu 18.04 (#2922).
      1 tests/requirements.txt:build~=1.0; python_version>="3.8"
      1 tests/requirements.txt:numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.8" and python_version<"3.10"
      1 tests/requirements.txt:numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy"
      1 tests/test_buffers.py:    env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
      1 tests/test_builtin_casters.py:    # Before Python 3.8, `PyLong_AsLong` does not pick up on `obj.__index__`,
      2 tests/test_builtin_casters.py:    if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
      4 tests/test_builtin_casters.py:    # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
      1 tests/test_callbacks.py:    assert m.test_callback3(z.double) == "func(43) = 86"
      2 tests/test_call_policies.cpp:#if !defined(PYPY_VERSION)
      1 tests/test_chrono.py:    diff = m.test_chrono_float_diff(43.789012, 1.123456)
      1 tests/test_constants_and_functions.py:    assert m.f3(86) == 89
      1 tests/test_eigen_matrix.py:    a_copy3[8, 1] = 11
      1 tests/test_eigen_matrix.py:    assert np.all(cornersc == np.array([[1.0, 3], [7, 9]]))
      1 tests/test_eigen_matrix.py:    assert np.all(cornersr == np.array([[1.0, 3], [7, 9]]))
      1 tests/test_eigen_matrix.py:        mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
      1 tests/test_exceptions.py:    if hasattr(pytest, unraisable):  # Python >= 3.8 and pytest >= 6
      2 tests/test_exceptions.py:@pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
      1 tests/test_factory_constructors.py:    assert [i.alive() for i in cstats] == [13, 7]
      1 tests/test_kwargs_and_defaults.cpp:#ifdef PYPY_VERSION
      1 tests/test_local_bindings.py:    assert i1.get3() == 8
      1 tests/test_methods_and_attributes.cpp:#if !defined(PYPY_VERSION)
      1 tests/test_numpy_array.py:    a = np.arange(3 * 7 * 2) + 1
      1 tests/test_numpy_array.py:    assert str(excinfo.value) == "cannot reshape array of size 42 into shape (3,7,1)"
      2 tests/test_numpy_array.py:    assert x.shape == (3, 7, 2)
      2 tests/test_numpy_array.py:        m.reshape_tuple(a, (3, 7, 1))
      2 tests/test_numpy_array.py:    x = m.reshape_tuple(a, (3, 7, 2))
      1 tests/test_numpy_vectorize.py:    assert np.isclose(m.vectorized_func3(np.array(3 + 7j)), [6 + 14j])
      1 tests/test_pickling.cpp:#if !defined(PYPY_VERSION)
      1 tests/test_pytypes.cpp:#if (defined(__APPLE__) && defined(__clang__)) || defined(PYPY_VERSION)
      1 tests/test_smart_ptr.cpp:    m.def("make_myobject3_1", []() { return new MyObject3(8); });
      1 tests/test_smart_ptr.py:    assert cstats.values() == ["MyObject3[9]", "MyObject3[8]", "MyObject3[9]"]
      1 tests/test_stl_binders.py:    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88])
      1 tests/test_stl_binders.py:    assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 88, 4])
      1 tests/test_type_caster_pyobject_ptr.cpp:#if !defined(PYPY_VERSION) // It is not worth the trouble doing something special for PyPy.
      1 tools/FindPythonLibsNew.cmake:  set(PythonLibsNew_FIND_VERSION "3.8")
      1 tools/JoinPaths.cmake:# https://docs.python.org/3.7/library/os.path.html#os.path.join
      1 tools/pybind11NewTools.cmake:    Python 3.8 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component}
      1 tools/pybind11NewTools.cmake:# Python debug libraries expose slightly different objects before 3.8
      1 tools/pybind11Tools.cmake:    "3.12;3.11;3.10;3.9;3.8"
      1 tools/pybind11Tools.cmake:    if(NOT DEFINED PYPY_VERSION)
      1 tools/pybind11Tools.cmake:    message(STATUS "PYPY ${PYPY_VERSION} (Py ${PYTHON_VERSION})")
      1 tools/pybind11Tools.cmake:# Python debug libraries expose slightly different objects before 3.8
      1 tools/pybind11Tools.cmake:      set(PYPY_VERSION
```

* Change `[tool.ruff]` `target-version` to `"py38"`, as suggested by @Skylion007
This commit is contained in:
Ralf W. Grosse-Kunstleve 2024-07-30 23:18:35 +07:00 committed by GitHub
parent 2e260b067f
commit 723307283e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 45 additions and 91 deletions

View File

@ -311,11 +311,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
clang: clang:
- 3.6
- 3.7
- 3.9
- 7
- 9
- dev - dev
std: std:
- 11 - 11
@ -324,8 +319,6 @@ jobs:
include: include:
- clang: 5 - clang: 5
std: 14 std: 14
- clang: 10
std: 17
- clang: 11 - clang: 11
std: 20 std: 20
- clang: 12 - clang: 12
@ -503,10 +496,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- { gcc: 7, std: 11 }
- { gcc: 7, std: 17 }
- { gcc: 8, std: 14 }
- { gcc: 8, std: 17 }
- { gcc: 9, std: 20 } - { gcc: 9, std: 20 }
- { gcc: 10, std: 17 } - { gcc: 10, std: 17 }
- { gcc: 10, std: 20 } - { gcc: 10, std: 20 }
@ -727,9 +716,9 @@ jobs:
# This tests an "install" with the CMake tools # This tests an "install" with the CMake tools
install-classic: install-classic:
name: "🐍 3.7 • Debian • x86 • Install" name: "🐍 3.9 • Debian • x86 • Install"
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: i386/debian:buster container: i386/debian:bullseye
steps: steps:
- uses: actions/checkout@v1 # v1 is required to run inside docker - uses: actions/checkout@v1 # v1 is required to run inside docker
@ -809,7 +798,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
python: python:
- '3.7'
- '3.8' - '3.8'
- '3.9' - '3.9'
- '3.10' - '3.10'
@ -827,8 +815,6 @@ jobs:
args: -DCMAKE_CXX_STANDARD=20 args: -DCMAKE_CXX_STANDARD=20
- python: '3.8' - python: '3.8'
args: -DCMAKE_CXX_STANDARD=17 args: -DCMAKE_CXX_STANDARD=17
- python: '3.7'
args: -DCMAKE_CXX_STANDARD=14
name: "🐍 ${{ matrix.python }} • MSVC 2019 • x86 ${{ matrix.args }}" name: "🐍 ${{ matrix.python }} • MSVC 2019 • x86 ${{ matrix.args }}"

View File

@ -39,22 +39,22 @@ jobs:
- runs-on: macos-13 - runs-on: macos-13
arch: x64 arch: x64
cmake: "3.7" cmake: "3.8"
- runs-on: windows-2019 - runs-on: windows-2019
arch: x64 # x86 compilers seem to be missing on 2019 image arch: x64 # x86 compilers seem to be missing on 2019 image
cmake: "3.18" cmake: "3.18"
name: 🐍 3.7 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }} name: 🐍 3.8 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }}
runs-on: ${{ matrix.runs-on }} runs-on: ${{ matrix.runs-on }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Python 3.7 - name: Setup Python 3.8
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: 3.7 python-version: 3.8
architecture: ${{ matrix.arch }} architecture: ${{ matrix.arch }}
- name: Prepare env - name: Prepare env

View File

@ -34,7 +34,7 @@ dependency.
Think of this library as a tiny self-contained version of Boost.Python Think of this library as a tiny self-contained version of Boost.Python
with everything stripped away that isn't relevant for binding with everything stripped away that isn't relevant for binding
generation. Without comments, the core header files only require ~4K generation. Without comments, the core header files only require ~4K
lines of code and depend on Python (3.7+, or PyPy) and the C++ lines of code and depend on Python (3.8+, or PyPy) and the C++
standard library. This compact implementation was possible thanks to standard library. This compact implementation was possible thanks to
some C++11 language features (specifically: tuples, lambda functions and some C++11 language features (specifically: tuples, lambda functions and
variadic templates). Since its creation, this library has grown beyond variadic templates). Since its creation, this library has grown beyond
@ -79,7 +79,7 @@ Goodies
In addition to the core functionality, pybind11 provides some extra In addition to the core functionality, pybind11 provides some extra
goodies: goodies:
- Python 3.7+, and PyPy3 7.3 are supported with an implementation-agnostic - Python 3.8+, and PyPy3 7.3 are supported with an implementation-agnostic
interface (pybind11 2.9 was the last version to support Python 2 and 3.5). interface (pybind11 2.9 was the last version to support Python 2 and 3.5).
- It is possible to bind C++11 lambda functions with captured - It is possible to bind C++11 lambda functions with captured

View File

@ -826,8 +826,7 @@ An instance can now be pickled as follows:
always use the latest available version. Beware: failure to follow these always use the latest available version. Beware: failure to follow these
instructions will cause important pybind11 memory allocation routines to be instructions will cause important pybind11 memory allocation routines to be
skipped during unpickling, which will likely lead to memory corruption skipped during unpickling, which will likely lead to memory corruption
and/or segmentation faults. Python defaults to version 3 (Python 3-3.7) and and/or segmentation faults.
version 4 for Python 3.8+.
.. seealso:: .. seealso::

View File

@ -368,8 +368,7 @@ Should they throw or fail to catch any exceptions in their call graph,
the C++ runtime calls ``std::terminate()`` to abort immediately. the C++ runtime calls ``std::terminate()`` to abort immediately.
Similarly, Python exceptions raised in a class's ``__del__`` method do not Similarly, Python exceptions raised in a class's ``__del__`` method do not
propagate, but are logged by Python as an unraisable error. In Python 3.8+, a propagate, but ``sys.unraisablehook()`` `is triggered
`system hook is triggered
<https://docs.python.org/3/library/sys.html#sys.unraisablehook>`_ <https://docs.python.org/3/library/sys.html#sys.unraisablehook>`_
and an auditing event is logged. and an auditing event is logged.

View File

@ -426,7 +426,7 @@ with ``PYTHON_EXECUTABLE``. For example:
.. code-block:: bash .. code-block:: bash
cmake -DPYBIND11_PYTHON_VERSION=3.7 .. cmake -DPYBIND11_PYTHON_VERSION=3.8 ..
# Another method: # Another method:
cmake -DPYTHON_EXECUTABLE=/path/to/python .. cmake -DPYTHON_EXECUTABLE=/path/to/python ..
@ -493,7 +493,7 @@ existing targets instead:
cmake_minimum_required(VERSION 3.15...3.22) cmake_minimum_required(VERSION 3.15...3.22)
project(example LANGUAGES CXX) project(example LANGUAGES CXX)
find_package(Python 3.7 COMPONENTS Interpreter Development REQUIRED) find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED)
find_package(pybind11 CONFIG REQUIRED) find_package(pybind11 CONFIG REQUIRED)
# or add_subdirectory(pybind11) # or add_subdirectory(pybind11)

View File

@ -158,7 +158,7 @@ public:
} else { } else {
handle src_or_index = src; handle src_or_index = src;
// PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls. // PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
#if PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION) #if defined(PYPY_VERSION)
object index; object index;
if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr()) if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
index = reinterpret_steal<object>(PyNumber_Index(src.ptr())); index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
@ -1503,7 +1503,7 @@ struct kw_only {};
/// \ingroup annotations /// \ingroup annotations
/// Annotation indicating that all previous arguments are positional-only; the is the equivalent of /// Annotation indicating that all previous arguments are positional-only; the is the equivalent of
/// an unnamed '/' argument (in Python 3.8) /// an unnamed '/' argument
struct pos_only {}; struct pos_only {};
template <typename T> template <typename T>

View File

@ -466,19 +466,9 @@ extern "C" inline void pybind11_object_dealloc(PyObject *self) {
type->tp_free(self); type->tp_free(self);
#if PY_VERSION_HEX < 0x03080000
// `type->tp_dealloc != pybind11_object_dealloc` means that we're being called
// as part of a derived type's dealloc, in which case we're not allowed to decref
// the type here. For cross-module compatibility, we shouldn't compare directly
// with `pybind11_object_dealloc`, but with the common one stashed in internals.
auto pybind11_object_type = (PyTypeObject *) get_internals().instance_base;
if (type->tp_dealloc == pybind11_object_type->tp_dealloc)
Py_DECREF(type);
#else
// This was not needed before Python 3.8 (Python issue 35810) // This was not needed before Python 3.8 (Python issue 35810)
// https://github.com/pybind/pybind11/issues/1946 // https://github.com/pybind/pybind11/issues/1946
Py_DECREF(type); Py_DECREF(type);
#endif
} }
std::string error_string(); std::string error_string();

View File

@ -272,8 +272,8 @@ PYBIND11_WARNING_DISABLE_MSVC(4505)
#endif #endif
#include <Python.h> #include <Python.h>
#if PY_VERSION_HEX < 0x03070000 #if PY_VERSION_HEX < 0x03080000
# error "PYTHON < 3.7 IS UNSUPPORTED. pybind11 v2.12 was the last to support Python 3.6." # error "PYTHON < 3.8 IS UNSUPPORTED. pybind11 v2.13 was the last to support Python 3.7."
#endif #endif
#include <frameobject.h> #include <frameobject.h>
#include <pythread.h> #include <pythread.h>

View File

@ -447,7 +447,7 @@ inline void translate_local_exception(std::exception_ptr p) {
inline object get_python_state_dict() { inline object get_python_state_dict() {
object state_dict; object state_dict;
#if PYBIND11_INTERNALS_VERSION <= 4 || PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION) #if PYBIND11_INTERNALS_VERSION <= 4 || defined(PYPY_VERSION)
state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins()); state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins());
#else #else
# if PY_VERSION_HEX < 0x03090000 # if PY_VERSION_HEX < 0x03090000

View File

@ -104,23 +104,13 @@ inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
detail::precheck_interpreter(); detail::precheck_interpreter();
Py_InitializeEx(init_signal_handlers ? 1 : 0); Py_InitializeEx(init_signal_handlers ? 1 : 0);
// Before it was special-cased in python 3.8, passing an empty or null argv
// caused a segfault, so we have to reimplement the special case ourselves.
bool special_case = (argv == nullptr || argc <= 0);
const char *const empty_argv[]{"\0"};
const char *const *safe_argv = special_case ? empty_argv : argv;
if (special_case) {
argc = 1;
}
auto argv_size = static_cast<size_t>(argc); auto argv_size = static_cast<size_t>(argc);
// SetArgv* on python 3 takes wchar_t, so we have to convert. // SetArgv* on python 3 takes wchar_t, so we have to convert.
std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]); std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
std::vector<std::unique_ptr<wchar_t[], detail::wide_char_arg_deleter>> widened_argv_entries; std::vector<std::unique_ptr<wchar_t[], detail::wide_char_arg_deleter>> widened_argv_entries;
widened_argv_entries.reserve(argv_size); widened_argv_entries.reserve(argv_size);
for (size_t ii = 0; ii < argv_size; ++ii) { for (size_t ii = 0; ii < argv_size; ++ii) {
widened_argv_entries.emplace_back(detail::widen_chars(safe_argv[ii])); widened_argv_entries.emplace_back(detail::widen_chars(argv[ii]));
if (!widened_argv_entries.back()) { if (!widened_argv_entries.back()) {
// A null here indicates a character-encoding failure or the python // A null here indicates a character-encoding failure or the python
// interpreter out of memory. Give up. // interpreter out of memory. Give up.

View File

@ -19,7 +19,7 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
inline void ensure_builtins_in_globals(object &global) { inline void ensure_builtins_in_globals(object &global) {
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x03080000 #if defined(PYPY_VERSION)
// Running exec and eval adds `builtins` module under `__builtins__` key to // Running exec and eval adds `builtins` module under `__builtins__` key to
// globals if not yet present. Python 3.8 made PyRun_String behave // globals if not yet present. Python 3.8 made PyRun_String behave
// similarly. Let's also do that for older versions, for consistency. This // similarly. Let's also do that for older versions, for consistency. This

View File

@ -147,9 +147,7 @@ public:
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer) // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
tstate = PyEval_SaveThread(); tstate = PyEval_SaveThread();
if (disassoc) { if (disassoc) {
// Python >= 3.7 can remove this, it's an int before 3.7 auto key = internals.tstate; // NOLINT(readability-qualified-auto)
// NOLINTNEXTLINE(readability-qualified-auto)
auto key = internals.tstate;
PYBIND11_TLS_DELETE_VALUE(key); PYBIND11_TLS_DELETE_VALUE(key);
} }
} }
@ -173,9 +171,7 @@ public:
PyEval_RestoreThread(tstate); PyEval_RestoreThread(tstate);
} }
if (disassoc) { if (disassoc) {
// Python >= 3.7 can remove this, it's an int before 3.7 auto key = detail::get_internals().tstate; // NOLINT(readability-qualified-auto)
// NOLINTNEXTLINE(readability-qualified-auto)
auto key = detail::get_internals().tstate;
PYBIND11_TLS_REPLACE_VALUE(key, tstate); PYBIND11_TLS_REPLACE_VALUE(key, tstate);
} }
} }

View File

@ -2,8 +2,8 @@ from __future__ import annotations
import sys import sys
if sys.version_info < (3, 7): # noqa: UP036 if sys.version_info < (3, 8): # noqa: UP036
msg = "pybind11 does not support Python < 3.7. v2.12 was the last release supporting Python 3.6." msg = "pybind11 does not support Python < 3.8. v2.13 was the last release supporting Python 3.7."
raise ImportError(msg) raise ImportError(msg)

View File

@ -249,7 +249,7 @@ def has_flag(compiler: Any, flag: str) -> bool:
cpp_flag_cache = None cpp_flag_cache = None
@lru_cache() @lru_cache
def auto_cpp_level(compiler: Any) -> str | int: def auto_cpp_level(compiler: Any) -> str | int:
""" """
Return the max supported C++ std level (17, 14, or 11). Returns latest on Windows. Return the max supported C++ std level (17, 14, or 11). Returns latest on Windows.

View File

@ -30,7 +30,7 @@ ignore_missing_imports = true
[tool.pylint] [tool.pylint]
master.py-version = "3.7" master.py-version = "3.8"
reports.output-format = "colorized" reports.output-format = "colorized"
messages_control.disable = [ messages_control.disable = [
"design", "design",
@ -45,7 +45,7 @@ messages_control.disable = [
] ]
[tool.ruff] [tool.ruff]
target-version = "py37" target-version = "py38"
src = ["src"] src = ["src"]
[tool.ruff.lint] [tool.ruff.lint]

View File

@ -14,7 +14,6 @@ classifiers =
Topic :: Utilities Topic :: Utilities
Programming Language :: C++ Programming Language :: C++
Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.10
@ -39,5 +38,5 @@ project_urls =
Chat = https://gitter.im/pybind/Lobby Chat = https://gitter.im/pybind/Lobby
[options] [options]
python_requires = >=3.7 python_requires = >=3.8
zip_safe = False zip_safe = False

View File

@ -1,9 +1,8 @@
--only-binary=:all: --only-binary=:all:
build~=1.0; python_version>="3.7" build~=1.0; python_version>="3.8"
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.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.25.0; python_version=="3.9" and platform_python_implementation=='PyPy'
numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10" numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.8" and python_version<"3.10"
numpy~=1.22.2; platform_python_implementation!="PyPy" 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" and python_version<"3.13" numpy~=1.26.0; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13"
pytest~=7.0 pytest~=7.0

View File

@ -297,7 +297,7 @@ def test_int_convert():
cant_convert(3.14159) cant_convert(3.14159)
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar) # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
# TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7) # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON: if sys.version_info < (3, 10) and env.CPYTHON:
with env.deprecated_call(): with env.deprecated_call():
assert convert(Int()) == 42 assert convert(Int()) == 42
else: else:

View File

@ -103,28 +103,24 @@ def ignore_pytest_unraisable_warning(f):
@pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False) @pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
@ignore_pytest_unraisable_warning @ignore_pytest_unraisable_warning
def test_python_alreadyset_in_destructor(monkeypatch, capsys): def test_python_alreadyset_in_destructor(monkeypatch, capsys):
hooked = False
triggered = False triggered = False
if hasattr(sys, "unraisablehook"): # Python 3.8+ # Don't take `sys.unraisablehook`, as that's overwritten by pytest
hooked = True default_hook = sys.__unraisablehook__
# Don't take `sys.unraisablehook`, as that's overwritten by pytest
default_hook = sys.__unraisablehook__
def hook(unraisable_hook_args): def hook(unraisable_hook_args):
exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args
if obj == "already_set demo": if obj == "already_set demo":
nonlocal triggered nonlocal triggered
triggered = True triggered = True
default_hook(unraisable_hook_args) default_hook(unraisable_hook_args)
return return
# Use monkeypatch so pytest can apply and remove the patch as appropriate # Use monkeypatch so pytest can apply and remove the patch as appropriate
monkeypatch.setattr(sys, "unraisablehook", hook) monkeypatch.setattr(sys, "unraisablehook", hook)
assert m.python_alreadyset_in_destructor("already_set demo") is True assert m.python_alreadyset_in_destructor("already_set demo") is True
if hooked: assert triggered is True
assert triggered is True
_, captured_stderr = capsys.readouterr() _, captured_stderr = capsys.readouterr()
assert captured_stderr.startswith("Exception ignored in: 'already_set demo'") assert captured_stderr.startswith("Exception ignored in: 'already_set demo'")

View File

@ -92,7 +92,7 @@ endif()
# Use the Python interpreter to find the libs. # Use the Python interpreter to find the libs.
if(NOT PythonLibsNew_FIND_VERSION) if(NOT PythonLibsNew_FIND_VERSION)
set(PythonLibsNew_FIND_VERSION "3.7") set(PythonLibsNew_FIND_VERSION "3.8")
endif() endif()
if(NOT CMAKE_VERSION VERSION_LESS "3.27") if(NOT CMAKE_VERSION VERSION_LESS "3.27")

View File

@ -56,7 +56,7 @@ if(NOT Python_FOUND AND NOT Python3_FOUND)
endif() endif()
find_package( find_package(
Python 3.7 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component} Python 3.8 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component}
${_pybind11_quiet} ${_pybind11_global_keyword}) ${_pybind11_quiet} ${_pybind11_global_keyword})
# If we are in submodule mode, export the Python targets to global targets. # If we are in submodule mode, export the Python targets to global targets.

View File

@ -43,7 +43,7 @@ endif()
# A user can set versions manually too # A user can set versions manually too
set(Python_ADDITIONAL_VERSIONS set(Python_ADDITIONAL_VERSIONS
"3.12;3.11;3.10;3.9;3.8;3.7" "3.12;3.11;3.10;3.9;3.8"
CACHE INTERNAL "") CACHE INTERNAL "")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")