Skip to content

Commit 07ccfde

Browse files
authored
drop support for Python 3.7 (#5912)
* drop support for Python 3.7 * newsfragment * fixup tests * add clarifying comment to test
1 parent 7e67f9e commit 07ccfde

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+243
-452
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ env:
2828

2929
jobs:
3030
build:
31-
continue-on-error: ${{ endsWith(inputs.python-version, '-dev') || contains(fromJSON('["3.7", "3.8"]'), inputs.python-version) || contains(fromJSON('["beta", "nightly"]'), inputs.rust) }}
31+
continue-on-error: ${{ endsWith(inputs.python-version, '-dev') || contains(fromJSON('["3.8"]'), inputs.python-version) || contains(fromJSON('["beta", "nightly"]'), inputs.rust) }}
3232
runs-on: ${{ inputs.os }}
3333
if: ${{ !(startsWith(inputs.python-version, 'graalpy') && startsWith(inputs.os, 'windows')) }}
3434
steps:
@@ -44,7 +44,7 @@ jobs:
4444
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
4545

4646
# installs using setup-python do not work for arm macOS 3.9 and below
47-
- if: ${{ !(inputs.os == 'macos-latest' && contains(fromJSON('["3.7", "3.8", "3.9"]'), inputs.python-version) && inputs.python-architecture == 'x64') }}
47+
- if: ${{ !(inputs.os == 'macos-latest' && contains(fromJSON('["3.8", "3.9"]'), inputs.python-version) && inputs.python-architecture == 'x64') }}
4848
name: Set up Python ${{ inputs.python-version }}
4949
uses: actions/setup-python@v6
5050
with:
@@ -89,8 +89,8 @@ jobs:
8989
# to match windows-2022 images
9090
version: "18"
9191

92-
- name: Install zoneinfo backport for Python 3.7 / 3.8
93-
if: contains(fromJSON('["3.7", "3.8"]'), inputs.python-version)
92+
- name: Install zoneinfo backport for Python 3.8
93+
if: contains(fromJSON('["3.8"]'), inputs.python-version)
9494
run: python -m pip install backports.zoneinfo
9595

9696
- uses: Swatinem/rust-cache@v2

.github/workflows/ci.yml

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,6 @@ jobs:
226226
rust: [stable]
227227
python-version:
228228
[
229-
"3.7",
230229
"3.8",
231230
"3.9",
232231
"3.10",
@@ -306,25 +305,8 @@ jobs:
306305
python-architecture: "x64",
307306
rust-target: "x86_64-apple-darwin",
308307
}
309-
# ubuntu-latest (24.04) no longer supports 3.7, so run on 22.04
310-
- rust: stable
311-
python-version: "3.7"
312-
platform:
313-
{
314-
os: "ubuntu-22.04",
315-
python-architecture: "x64",
316-
rust-target: "x86_64-unknown-linux-gnu",
317-
}
318308

319309
# arm64 macOS Python not available on GitHub Actions until 3.10, test older versions on x64
320-
- rust: stable
321-
python-version: "3.7"
322-
platform:
323-
{
324-
os: "macos-15-intel",
325-
python-architecture: "x64",
326-
rust-target: "x86_64-apple-darwin",
327-
}
328310
- rust: stable
329311
python-version: "3.8"
330312
platform:
@@ -359,18 +341,7 @@ jobs:
359341
rust-target: "aarch64-pc-windows-msvc",
360342
}
361343
exclude:
362-
# ubuntu-latest (24.04) no longer supports 3.7
363-
- python-version: "3.7"
364-
platform: { os: "ubuntu-latest" }
365344
# arm64 macOS Python not available on GitHub Actions until 3.10
366-
- rust: stable
367-
python-version: "3.7"
368-
platform:
369-
{
370-
os: "macos-latest",
371-
python-architecture: "arm64",
372-
rust-target: "aarch64-apple-darwin",
373-
}
374345
- rust: stable
375346
python-version: "3.8"
376347
platform:

Architecture.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,21 @@ To summarize, there are six main parts to the PyO3 codebase.
3434

3535
[`pyo3-ffi`] contains wrappers of the [Python/C API]. This is currently done by hand rather than
3636
automated tooling because:
37-
- it gives us best control about how to adapt C conventions to Rust, and
38-
- there are many Python interpreter versions we support in a single set of files.
37+
38+
- it gives us best control about how to adapt C conventions to Rust, and
39+
- there are many Python interpreter versions we support in a single set of files.
3940

4041
We aim to provide straight-forward Rust wrappers resembling the file structure of [`cpython/Include`](https://github.com/python/cpython/tree/main/Include).
4142

4243
We are continuously updating the module to match the latest CPython version which PyO3 supports (i.e. as of time of writing Python 3.13). The tracking issue is [#1289](https://github.com/PyO3/pyo3/issues/1289), and contribution is welcome.
4344

4445
In the [`pyo3-ffi`] crate, there is lots of conditional compilation such as `#[cfg(Py_LIMITED_API)]`,
45-
`#[cfg(Py_3_7)]`, and `#[cfg(PyPy)]`.
46+
`#[cfg(Py_3_8)]`, and `#[cfg(PyPy)]`.
4647
`Py_LIMITED_API` corresponds to `#define Py_LIMITED_API` macro in Python/C API.
4748
With `Py_LIMITED_API`, we can build a Python-version-agnostic binary called an
4849
[abi3 wheel](https://pyo3.rs/latest/building-and-distribution.html#py_limited_apiabi3).
49-
`Py_3_7` means that the API is available from Python >= 3.7.
50-
There are also `Py_3_8`, `Py_3_9`, and so on.
50+
`Py_3_8` means that the API is available from Python >= 3.8.
51+
There are also `Py_3_9`, `Py_3_10`, and so on.
5152
`PyPy` means that the API definition is for PyPy.
5253
Those flags are set in [`build.rs`](#6-buildrs-and-pyo3-build-config).
5354

@@ -142,8 +143,9 @@ The `pyo3` `build.rs` also runs some safety checks such as ensuring the Python v
142143
actually supported.
143144

144145
Some of the functionality of `pyo3-build-config`:
146+
145147
- Find the interpreter for build and detect the Python version.
146-
- We have to set some version flags like `#[cfg(Py_3_7)]`.
148+
- We have to set some version flags like `#[cfg(Py_3_8)]`.
147149
- If the interpreter is PyPy, we set `#[cfg(PyPy)`.
148150
- If the `PYO3_CONFIG_FILE` environment variable is set then that file's contents will be used
149151
instead of any detected configuration.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ extension-module = ["pyo3-ffi/extension-module"]
109109
abi3 = ["pyo3-build-config/abi3", "pyo3-ffi/abi3"]
110110

111111
# With abi3, we can manually set the minimum Python version.
112-
abi3-py37 = ["abi3-py38", "pyo3-build-config/abi3-py37", "pyo3-ffi/abi3-py37"]
113112
abi3-py38 = ["abi3-py39", "pyo3-build-config/abi3-py38", "pyo3-ffi/abi3-py38"]
114113
abi3-py39 = ["abi3-py310", "pyo3-build-config/abi3-py39", "pyo3-ffi/abi3-py39"]
115114
abi3-py310 = ["abi3-py311", "pyo3-build-config/abi3-py310", "pyo3-ffi/abi3-py310"]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
Requires Rust 1.83 or greater.
2020

2121
PyO3 supports the following Python distributions:
22-
- CPython 3.7 or greater
22+
- CPython 3.8 or greater
2323
- PyPy 7.3 (Python 3.11+)
2424
- GraalPy 25.0 or greater (Python 3.12+)
2525

examples/maturin-starter/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ crate-type = ["cdylib"]
1212
pyo3 = { path = "../../" }
1313

1414
[features]
15-
abi3 = ["pyo3/abi3-py37"]
15+
abi3 = ["pyo3/abi3-py38"]
1616

1717
[workspace]

examples/plugin/plugin_api/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "maturin"
44

55
[project]
66
name = "plugin_api"
7-
requires-python = ">=3.7"
7+
requires-python = ">=3.8"
88
classifiers = [
99
"Programming Language :: Rust",
1010
"Programming Language :: Python :: Implementation :: CPython",

guide/src/building-and-distribution.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This chapter of the guide goes into detail on how to build and distribute projects using PyO3.
44
The way to achieve this is very different depending on whether the project is a Python module implemented in Rust, or a Rust binary embedding Python.
5-
For both types of project there are also common problems such as the Python version to build for and the [linker](https://en.wikipedia.org/wiki/Linker_(computing)) arguments to use.
5+
For both types of project there are also common problems such as the Python version to build for and the [linker](<https://en.wikipedia.org/wiki/Linker_(computing)>) arguments to use.
66

77
The material in this chapter is intended for users who have already read the PyO3 [README](./index.md).
88
It covers in turn the choices that can be made for Python modules and for Rust binaries.
@@ -19,7 +19,7 @@ By default it will attempt to use the following in order:
1919
- The `python` executable (if it's a Python 3 interpreter).
2020
- The `python3` executable.
2121

22-
You can override the Python interpreter by setting the `PYO3_PYTHON` environment variable, e.g. `PYO3_PYTHON=python3.7`, `PYO3_PYTHON=/usr/bin/python3.9`, or even a PyPy interpreter `PYO3_PYTHON=pypy3`.
22+
You can override the Python interpreter by setting the `PYO3_PYTHON` environment variable, e.g. `PYO3_PYTHON=python3.8`, `PYO3_PYTHON=/usr/bin/python3.9`, or even a PyPy interpreter `PYO3_PYTHON=pypy3`.
2323

2424
Once the Python interpreter is located, `pyo3-build-config` executes it to query the information in the `sysconfig` module which is needed to configure the rest of the compilation.
2525

@@ -109,7 +109,7 @@ You can then open a Python shell in the output directory and you'll be able to r
109109

110110
If you're packaging your library for redistribution, you should indicate the Python interpreter your library is compiled for by including the [platform tag](#platform-tags) in its name.
111111
This prevents incompatible interpreters from trying to import your library.
112-
If you're compiling for PyPy you *must* include the platform tag, or PyPy will ignore the module.
112+
If you're compiling for PyPy you _must_ include the platform tag, or PyPy will ignore the module.
113113

114114
#### Bazel builds
115115

@@ -245,18 +245,18 @@ There are three steps involved in making use of `abi3` when building Python pack
245245

246246
#### Minimum Python version for `abi3`
247247

248-
Because a single `abi3` wheel can be used with many different Python versions, PyO3 has feature flags `abi3-py37`, `abi3-py38`, `abi3-py39` etc. to set the minimum required Python version for your `abi3` wheel.
249-
For example, if you set the `abi3-py37` feature, your extension wheel can be used on all Python 3 versions from Python 3.7 and up.
250-
`maturin` and `setuptools-rust` will give the wheel a name like `my-extension-1.0-cp37-abi3-manylinux2020_x86_64.whl`.
248+
Because a single `abi3` wheel can be used with many different Python versions, PyO3 has feature flags `abi3-py38`, `abi3-py39`, `abi3-py310` etc. to set the minimum required Python version for your `abi3` wheel.
249+
For example, if you set the `abi3-py38` feature, your extension wheel can be used on all Python 3 versions from Python 3.8 and up.
250+
`maturin` and `setuptools-rust` will give the wheel a name like `my-extension-1.0-cp38-abi3-manylinux2020_x86_64.whl`.
251251

252252
As your extension module may be run with multiple different Python versions you may occasionally find you need to check the Python version at runtime to customize behavior.
253253
See [the relevant section of this guide](./building-and-distribution/multiple-python-versions.md#checking-the-python-version-at-runtime) on supporting multiple Python versions at runtime.
254254

255255
PyO3 is only able to link your extension module to abi3 version up to and including your host Python version.
256-
E.g., if you set `abi3-py38` and try to compile the crate with a host of Python 3.7, the build will fail.
256+
E.g., if you set `abi3-py39` and try to compile the crate with a host of Python 3.8, the build will fail.
257257

258258
> [!NOTE]
259-
> If you set more that one of these `abi3` version feature flags the lowest version always wins. For example, with both `abi3-py37` and `abi3-py38` set, PyO3 would build a wheel which supports Python 3.7 and up.
259+
> If you set more that one of these `abi3` version feature flags the lowest version always wins. For example, with both `abi3-py38` and `abi3-py39` set, PyO3 would build a wheel which supports Python 3.8 and up.
260260
261261
#### Building `abi3` extensions without a Python interpreter
262262

@@ -321,17 +321,17 @@ The known complications are:
321321
- To import compiled extension modules (such as other Rust extension modules, or those written in C), your binary must have the correct linker flags set during compilation to export the original contents of `libpython.a` so that extensions can use them (e.g. `-Wl,--export-dynamic`).
322322
- The C compiler and flags which were used to create `libpython.a` must be compatible with your Rust compiler and flags, else you will experience compilation failures.
323323

324-
Significantly different compiler versions may see errors like this:
324+
Significantly different compiler versions may see errors like this:
325325

326-
```text
327-
lto1: fatal error: bytecode stream in file 'rust-numpy/target/release/deps/libpyo3-6a7fb2ed970dbf26.rlib' generated with LTO version 6.0 instead of the expected 6.2
328-
```
326+
```text
327+
lto1: fatal error: bytecode stream in file 'rust-numpy/target/release/deps/libpyo3-6a7fb2ed970dbf26.rlib' generated with LTO version 6.0 instead of the expected 6.2
328+
```
329329

330-
Mismatching flags may lead to errors like this:
330+
Mismatching flags may lead to errors like this:
331331

332-
```text
333-
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpython3.9.a(zlibmodule.o): relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE
334-
```
332+
```text
333+
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpython3.9.a(zlibmodule.o): relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE
334+
```
335335

336336
If you encounter these or other complications when linking the interpreter statically, discuss them on [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416).
337337
It is hoped that eventually that discussion will contain enough information and solutions that PyO3 can offer first-class support for static embedding.

guide/src/building-and-distribution/multiple-python-versions.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ PyO3 itself depends on this crate, so by using it you can be sure that you are c
1818
This allows us to write code like the following
1919

2020
```rust,ignore
21-
#[cfg(Py_3_7)]
22-
fn function_only_supported_on_python_3_7_and_up() {}
21+
#[cfg(Py_3_8)]
22+
fn function_only_supported_on_python_3_8_and_up() {}
2323
2424
#[cfg(not(Py_3_8))]
2525
fn function_only_supported_before_python_3_8() {}
@@ -60,17 +60,17 @@ The `#[cfg]` flags added by `pyo3-build-cfg` can be combined with all of Rust's
6060
The following are some common patterns implemented using these flags:
6161

6262
```text
63-
#[cfg(Py_3_7)]
63+
#[cfg(Py_3_8)]
6464
```
6565

66-
This `#[cfg]` marks code that will only be present on Python 3.7 and upwards.
67-
There are similar options `Py_3_8`, `Py_3_9`, `Py_3_10` and so on for each minor version.
66+
This `#[cfg]` marks code that will only be present on Python 3.8 and upwards.
67+
There are similar options `Py_3_9`, `Py_3_10`, `Py_3_11` and so on for each minor version.
6868

6969
```text
70-
#[cfg(not(Py_3_7))]
70+
#[cfg(not(Py_3_8))]
7171
```
7272

73-
This `#[cfg]` marks code that will only be present on Python versions before (but not including) Python 3.7.
73+
This `#[cfg]` marks code that will only be present on Python versions before (but not including) Python 3.8.
7474

7575
```text
7676
#[cfg(not(Py_LIMITED_API))]
@@ -109,9 +109,9 @@ This allows you to do the following, for example:
109109
use pyo3::Python;
110110

111111
Python::attach(|py| {
112-
// PyO3 supports Python 3.7 and up.
113-
assert!(py.version_info() >= (3, 7));
114-
assert!(py.version_info() >= (3, 7, 0));
112+
// PyO3 supports Python 3.8 and up.
113+
assert!(py.version_info() >= (3, 8));
114+
assert!(py.version_info() >= (3, 8, 0));
115115
});
116116
```
117117

0 commit comments

Comments
 (0)