Commit 72330728 by Ralf W. Grosse-Kunstleve Committed by GitHub

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 518515a761ac37dc2cf5d0980da82d0de39edc28.

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

* Fix `-` vs `:` mixup.

* This reverts commit b1c4304475b8ad129c12330c7ed7eb85d15ba14a.

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

This reverts commit b203a294bb444fc6ae57a0100fa91dc91b8d3264.

* `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 bb5b9d187bffbfb61e2977d7eee46b766fa1cce9.

* 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
parent 2e260b06
...@@ -311,11 +311,6 @@ jobs: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 }}"
......
...@@ -39,22 +39,22 @@ jobs: ...@@ -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
......
...@@ -34,7 +34,7 @@ dependency. ...@@ -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 ...@@ -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
......
...@@ -826,8 +826,7 @@ An instance can now be pickled as follows: ...@@ -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::
......
...@@ -368,8 +368,7 @@ Should they throw or fail to catch any exceptions in their call graph, ...@@ -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.
......
...@@ -426,7 +426,7 @@ with ``PYTHON_EXECUTABLE``. For example: ...@@ -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: ...@@ -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)
......
...@@ -158,7 +158,7 @@ public: ...@@ -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 {}; ...@@ -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>
......
...@@ -466,19 +466,9 @@ extern "C" inline void pybind11_object_dealloc(PyObject *self) { ...@@ -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();
......
...@@ -272,8 +272,8 @@ PYBIND11_WARNING_DISABLE_MSVC(4505) ...@@ -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>
......
...@@ -447,7 +447,7 @@ inline void translate_local_exception(std::exception_ptr p) { ...@@ -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
......
...@@ -104,23 +104,13 @@ inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers, ...@@ -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.
......
...@@ -19,7 +19,7 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) ...@@ -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
......
...@@ -147,9 +147,7 @@ public: ...@@ -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: ...@@ -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);
} }
} }
......
...@@ -2,8 +2,8 @@ from __future__ import annotations ...@@ -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)
......
...@@ -249,7 +249,7 @@ def has_flag(compiler: Any, flag: str) -> bool: ...@@ -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.
......
...@@ -30,7 +30,7 @@ ignore_missing_imports = true ...@@ -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 = [ ...@@ -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]
......
...@@ -14,7 +14,6 @@ classifiers = ...@@ -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 = ...@@ -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
--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
......
...@@ -297,7 +297,7 @@ def test_int_convert(): ...@@ -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:
......
...@@ -103,28 +103,24 @@ def ignore_pytest_unraisable_warning(f): ...@@ -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'")
......
...@@ -92,7 +92,7 @@ endif() ...@@ -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")
......
...@@ -56,7 +56,7 @@ if(NOT Python_FOUND AND NOT Python3_FOUND) ...@@ -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.
......
...@@ -43,7 +43,7 @@ endif() ...@@ -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}")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment