Skip to content

Commit

Permalink
drop support for PyPy 3.7 and 3.8 (#4582)
Browse files Browse the repository at this point in the history
* drop support for PyPy 3.7 and 3.8

* newsfragment
  • Loading branch information
davidhewitt authored Sep 30, 2024
1 parent 2fa97f9 commit 8a6855e
Show file tree
Hide file tree
Showing 17 changed files with 67 additions and 94 deletions.
14 changes: 6 additions & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ on:

jobs:
build:
continue-on-error: ${{ endsWith(inputs.python-version, '-dev') || contains(fromJSON('["3.7", "pypy3.7"]'), inputs.python-version) || inputs.rust == 'beta' || inputs.rust == 'nightly' }}
continue-on-error: ${{ endsWith(inputs.python-version, '-dev') || contains(fromJSON('["3.7", "3.8"]'), inputs.python-version) || contains(fromJSON('["beta", "nightly"]'), inputs.rust) }}
runs-on: ${{ inputs.os }}
if: ${{ !(startsWith(inputs.python-version, 'graalpy') && startsWith(inputs.os, 'windows')) }}
steps:
Expand Down Expand Up @@ -95,8 +95,8 @@ jobs:
run: cargo build --lib --tests --no-default-features --features "multiple-pymethods full $MAYBE_NIGHTLY"

- if: ${{ startsWith(inputs.python-version, 'pypy') }}
name: Build PyPy (abi3-py37)
run: cargo build --lib --tests --no-default-features --features "multiple-pymethods abi3-py37 full $MAYBE_NIGHTLY"
name: Build PyPy (abi3-py39)
run: cargo build --lib --tests --no-default-features --features "multiple-pymethods abi3-py39 full $MAYBE_NIGHTLY"

# Run tests (except on PyPy, because no embedding API).
- if: ${{ !startsWith(inputs.python-version, 'pypy') && !startsWith(inputs.python-version, 'graalpy') }}
Expand Down Expand Up @@ -131,8 +131,7 @@ jobs:
CARGO_TARGET_DIR: ${{ github.workspace }}/target

- uses: dorny/paths-filter@v3
# pypy 3.7 and 3.8 are not PEP 3123 compliant so fail checks here
if: ${{ inputs.rust == 'stable' && inputs.python-version != 'pypy3.7' && inputs.python-version != 'pypy3.8' && !startsWith(inputs.python-version, 'graalpy') }}
if: ${{ inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy') }}
id: ffi-changes
with:
base: ${{ github.event.pull_request.base.ref || github.event.merge_group.base_ref }}
Expand All @@ -145,9 +144,8 @@ jobs:
- '.github/workflows/build.yml'
- name: Run pyo3-ffi-check
# pypy 3.7 and 3.8 are not PEP 3123 compliant so fail checks here, nor
# is pypy 3.9 on windows
if: ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && inputs.python-version != 'pypy3.7' && inputs.python-version != 'pypy3.8' && !startsWith(inputs.python-version, 'graalpy') && !(inputs.python-version == 'pypy3.9' && contains(inputs.os, 'windows'))) }}
# pypy 3.9 on windows is not PEP 3123 compliant, nor is graalpy
if: ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy') && !(inputs.python-version == 'pypy3.9' && contains(inputs.os, 'windows'))) }}
run: nox -s ffi-check

env:
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,6 @@ jobs:
"3.11",
"3.12",
"3.13-dev",
"pypy3.7",
"pypy3.8",
"pypy3.9",
"pypy3.10",
"graalpy24.0",
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@

## Usage

PyO3 supports the following software versions:
- Python 3.7 and up (CPython, PyPy, and GraalPy)
- Rust 1.63 and up
Requires Rust 1.63 or greater.

PyO3 supports the following Python distributions:
- CPython 3.7 or greater
- PyPy 7.3 (Python 3.9+)
- GraalPy 24.0 or greater (Python 3.10+)

You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.

Expand Down
4 changes: 2 additions & 2 deletions guide/src/building-and-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ Rather than using just the `.so` or `.pyd` extension suggested above (depending
# CPython 3.10 on macOS
.cpython-310-darwin.so

# PyPy 7.3 (Python 3.8) on Linux
# PyPy 7.3 (Python 3.9) on Linux
$ python -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX"))'
.pypy38-pp73-x86_64-linux-gnu.so
.pypy39-pp73-x86_64-linux-gnu.so
```

So, for example, a valid module library name on CPython 3.10 for macOS is `your_module.cpython-310-darwin.so`, and its equivalent when compiled for PyPy 7.3 on Linux would be `your_module.pypy38-pp73-x86_64-linux-gnu.so`.
Expand Down
1 change: 1 addition & 0 deletions newsfragments/4582.packaging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Drop support for PyPy 3.7 and 3.8.
6 changes: 3 additions & 3 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
PYO3_GUIDE_TARGET = PYO3_TARGET / "guide"
PYO3_DOCS_TARGET = PYO3_TARGET / "doc"
PY_VERSIONS = ("3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13")
PYPY_VERSIONS = ("3.7", "3.8", "3.9", "3.10")
PYPY_VERSIONS = ("3.9", "3.10")


@nox.session(venv_backend="none")
Expand Down Expand Up @@ -646,8 +646,8 @@ def test_version_limits(session: nox.Session):
env["PYO3_USE_ABI3_FORWARD_COMPATIBILITY"] = "1"
_run_cargo(session, "check", env=env)

assert "3.6" not in PYPY_VERSIONS
config_file.set("PyPy", "3.6")
assert "3.8" not in PYPY_VERSIONS
config_file.set("PyPy", "3.8")
_run_cargo(session, "check", env=env, expect_error=True)

assert "3.11" not in PYPY_VERSIONS
Expand Down
56 changes: 28 additions & 28 deletions pyo3-build-config/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,16 +1648,11 @@ fn default_lib_name_unix(
}
}
},
PythonImplementation::PyPy => {
if version >= (PythonVersion { major: 3, minor: 9 }) {
match ld_version {
Some(ld_version) => format!("pypy{}-c", ld_version),
None => format!("pypy{}.{}-c", version.major, version.minor),
}
} else {
format!("pypy{}-c", version.major)
}
}
PythonImplementation::PyPy => match ld_version {
Some(ld_version) => format!("pypy{}-c", ld_version),
None => format!("pypy{}.{}-c", version.major, version.minor),
},

PythonImplementation::GraalPy => "python-native".to_string(),
}
}
Expand Down Expand Up @@ -2348,17 +2343,17 @@ mod tests {
use PythonImplementation::*;
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
PythonVersion { major: 3, minor: 9 },
CPython,
false,
false,
false,
),
"python37",
"python39",
);
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
PythonVersion { major: 3, minor: 9 },
CPython,
true,
false,
Expand All @@ -2368,17 +2363,17 @@ mod tests {
);
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
PythonVersion { major: 3, minor: 9 },
CPython,
false,
true,
false,
),
"python3.7",
"python3.9",
);
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
PythonVersion { major: 3, minor: 9 },
CPython,
true,
true,
Expand All @@ -2388,35 +2383,35 @@ mod tests {
);
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
PythonVersion { major: 3, minor: 9 },
PyPy,
true,
false,
false,
),
"python37",
"python39",
);
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
PythonVersion { major: 3, minor: 9 },
CPython,
false,
false,
true,
),
"python37_d",
"python39_d",
);
// abi3 debug builds on windows use version-specific lib
// to workaround https://github.com/python/cpython/issues/101614
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
PythonVersion { major: 3, minor: 9 },
CPython,
true,
false,
true,
),
"python37_d",
"python39_d",
);
}

Expand Down Expand Up @@ -2447,13 +2442,12 @@ mod tests {
"python3.7md",
);

// PyPy 3.7 ignores ldversion
// PyPy 3.9 includes ldversion
assert_eq!(
super::default_lib_name_unix(PythonVersion { major: 3, minor: 7 }, PyPy, Some("3.7md")),
"pypy3-c",
super::default_lib_name_unix(PythonVersion { major: 3, minor: 9 }, PyPy, None),
"pypy3.9-c",
);

// PyPy 3.9 includes ldversion
assert_eq!(
super::default_lib_name_unix(PythonVersion { major: 3, minor: 9 }, PyPy, Some("3.9d")),
"pypy3.9d-c",
Expand Down Expand Up @@ -2692,7 +2686,7 @@ mod tests {
fn test_build_script_outputs_base() {
let interpreter_config = InterpreterConfig {
implementation: PythonImplementation::CPython,
version: PythonVersion { major: 3, minor: 8 },
version: PythonVersion { major: 3, minor: 9 },
shared: true,
abi3: false,
lib_name: Some("python3".into()),
Expand All @@ -2708,6 +2702,7 @@ mod tests {
[
"cargo:rustc-cfg=Py_3_7".to_owned(),
"cargo:rustc-cfg=Py_3_8".to_owned(),
"cargo:rustc-cfg=Py_3_9".to_owned(),
]
);

Expand All @@ -2720,6 +2715,7 @@ mod tests {
[
"cargo:rustc-cfg=Py_3_7".to_owned(),
"cargo:rustc-cfg=Py_3_8".to_owned(),
"cargo:rustc-cfg=Py_3_9".to_owned(),
"cargo:rustc-cfg=PyPy".to_owned(),
]
);
Expand All @@ -2729,7 +2725,7 @@ mod tests {
fn test_build_script_outputs_abi3() {
let interpreter_config = InterpreterConfig {
implementation: PythonImplementation::CPython,
version: PythonVersion { major: 3, minor: 7 },
version: PythonVersion { major: 3, minor: 9 },
shared: true,
abi3: true,
lib_name: Some("python3".into()),
Expand All @@ -2745,6 +2741,8 @@ mod tests {
interpreter_config.build_script_outputs(),
[
"cargo:rustc-cfg=Py_3_7".to_owned(),
"cargo:rustc-cfg=Py_3_8".to_owned(),
"cargo:rustc-cfg=Py_3_9".to_owned(),
"cargo:rustc-cfg=Py_LIMITED_API".to_owned(),
]
);
Expand All @@ -2757,6 +2755,8 @@ mod tests {
interpreter_config.build_script_outputs(),
[
"cargo:rustc-cfg=Py_3_7".to_owned(),
"cargo:rustc-cfg=Py_3_8".to_owned(),
"cargo:rustc-cfg=Py_3_9".to_owned(),
"cargo:rustc-cfg=PyPy".to_owned(),
"cargo:rustc-cfg=Py_LIMITED_API".to_owned(),
]
Expand Down
2 changes: 1 addition & 1 deletion pyo3-ffi/ACKNOWLEDGEMENTS
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ for binary compatibility, with additional metadata to support PyPy.

For original implementations please see:
- https://github.com/python/cpython
- https://foss.heptapod.net/pypy/pypy
- https://github.com/pypy/pypy
9 changes: 6 additions & 3 deletions pyo3-ffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ Manual][capi] for up-to-date documentation.

# Minimum supported Rust and Python versions

PyO3 supports the following software versions:
- Python 3.7 and up (CPython and PyPy)
- Rust 1.63 and up
Requires Rust 1.63 or greater.

`pyo3-ffi` supports the following Python distributions:
- CPython 3.7 or greater
- PyPy 7.3 (Python 3.9+)
- GraalPy 24.0 or greater (Python 3.10+)

# Example: Building Python Native modules

Expand Down
4 changes: 2 additions & 2 deletions pyo3-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const SUPPORTED_VERSIONS_CPYTHON: SupportedVersions = SupportedVersions {
};

const SUPPORTED_VERSIONS_PYPY: SupportedVersions = SupportedVersions {
min: PythonVersion { major: 3, minor: 7 },
min: PythonVersion { major: 3, minor: 9 },
max: PythonVersion {
major: 3,
minor: 10,
Expand Down Expand Up @@ -110,7 +110,7 @@ fn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> {
PythonImplementation::CPython => {}
PythonImplementation::PyPy => warn!(
"PyPy does not yet support abi3 so the build artifacts will be version-specific. \
See https://foss.heptapod.net/pypy/pypy/-/issues/3397 for more information."
See https://github.com/pypy/pypy/issues/3397 for more information."
),
PythonImplementation::GraalPy => warn!(
"GraalPy does not support abi3 so the build artifacts will be version-specific."
Expand Down
9 changes: 0 additions & 9 deletions pyo3-ffi/src/cpython/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,6 @@ pub type printfunc =
#[repr(C)]
#[derive(Debug)]
pub struct PyTypeObject {
#[cfg(all(PyPy, not(Py_3_9)))]
pub ob_refcnt: Py_ssize_t,
#[cfg(all(PyPy, not(Py_3_9)))]
pub ob_pypy_link: Py_ssize_t,
#[cfg(all(PyPy, not(Py_3_9)))]
pub ob_type: *mut PyTypeObject,
#[cfg(all(PyPy, not(Py_3_9)))]
pub ob_size: Py_ssize_t,
#[cfg(not(all(PyPy, not(Py_3_9))))]
pub ob_base: object::PyVarObject,
#[cfg(GraalPy)]
pub ob_size: Py_ssize_t,
Expand Down
5 changes: 0 additions & 5 deletions pyo3-ffi/src/datetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
//! This is the unsafe thin wrapper around the [CPython C API](https://docs.python.org/3/c-api/datetime.html),
//! and covers the various date and time related objects in the Python `datetime`
//! standard library module.
//!
//! A note regarding PyPy (cpyext) support:
//!
//! Support for `PyDateTime_CAPI` is limited as of PyPy 7.0.0.
//! `DateTime_FromTimestamp` and `Date_FromTimestamp` are currently not supported.

#[cfg(GraalPy)]
use crate::{PyLong_AsLong, PyLong_Check, PyObject_GetAttrString, Py_DecRef};
Expand Down
7 changes: 4 additions & 3 deletions pyo3-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@
//!
//! # Minimum supported Rust and Python versions
//!
//! PyO3 supports the following software versions:
//! - Python 3.7 and up (CPython and PyPy)
//! - Rust 1.63 and up
//! `pyo3-ffi` supports the following Python distributions:
//! - CPython 3.7 or greater
//! - PyPy 7.3 (Python 3.9+)
//! - GraalPy 24.0 or greater (Python 3.10+)
//!
//! # Example: Building Python Native modules
//!
Expand Down
4 changes: 0 additions & 4 deletions pyo3-ffi/src/pystate.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#[cfg(any(not(PyPy), Py_3_9))]
use crate::moduleobject::PyModuleDef;
use crate::object::PyObject;
use std::os::raw::c_int;
Expand Down Expand Up @@ -28,15 +27,12 @@ extern "C" {
#[cfg(not(PyPy))]
pub fn PyInterpreterState_GetID(arg1: *mut PyInterpreterState) -> i64;

#[cfg(any(not(PyPy), Py_3_9))] // only on PyPy since 3.9
#[cfg_attr(PyPy, link_name = "PyPyState_AddModule")]
pub fn PyState_AddModule(arg1: *mut PyObject, arg2: *mut PyModuleDef) -> c_int;

#[cfg(any(not(PyPy), Py_3_9))] // only on PyPy since 3.9
#[cfg_attr(PyPy, link_name = "PyPyState_RemoveModule")]
pub fn PyState_RemoveModule(arg1: *mut PyModuleDef) -> c_int;

#[cfg(any(not(PyPy), Py_3_9))] // only on PyPy since 3.9
// only has PyPy prefix since 3.10
#[cfg_attr(all(PyPy, Py_3_10), link_name = "PyPyState_FindModule")]
pub fn PyState_FindModule(arg1: *mut PyModuleDef) -> *mut PyObject;
Expand Down
Loading

0 comments on commit 8a6855e

Please sign in to comment.