Merge pull request #2143 from davidhewitt/pypy-3.9-dev

pypy: support 3.9
This commit is contained in:
David Hewitt 2022-02-25 08:39:39 +00:00 committed by GitHub
commit 1e1d6767d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 100 additions and 22 deletions

View File

@ -78,7 +78,16 @@ jobs:
fail-fast: false # If one platform fails, allow the rest to keep testing.
matrix:
rust: [stable]
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11-dev", "pypy-3.7-v7.3.7", "pypy-3.8"]
python-version: [
"3.7",
"3.8",
"3.9",
"3.10",
"3.11-dev",
"pypy-3.7-v7.3.7",
"pypy-3.8",
"pypy-3.9"
]
platform:
[
{
@ -108,6 +117,8 @@ jobs:
platform: { os: "windows-latest", python-architecture: "x86" }
- python-version: pypy-3.8
platform: { os: "windows-latest", python-architecture: "x86" }
- python-version: pypy-3.9
platform: { os: "windows-latest", python-architecture: "x86" }
include:
# Test minimal supported Rust version
- rust: 1.48.0

View File

@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Update `inventory` optional dependency to 0.2. [#2019](https://github.com/PyO3/pyo3/pull/2019)
- Drop `paste` dependency. [#2081](https://github.com/PyO3/pyo3/pull/2081)
- The bindings found `pyo3::ffi` are now a re-export of the new `pyo3-ffi` crate. [#2126](https://github.com/PyO3/pyo3/pull/2126)
- Support PyPy 3.9. [#2143](https://github.com/PyO3/pyo3/pull/2143)
### Added
@ -89,6 +91,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Use the Rust function path for `wrap_pymodule!` of a `#[pymodule]` with a `#[pyo3(name = "..")]` attribute, not the Python name. [#2081](https://github.com/PyO3/pyo3/pull/2081)
- Fix panic in `#[pyfunction]` generated code when a required argument following an `Option` was not provided. [#2093](https://github.com/PyO3/pyo3/pull/2093)
- Fixed undefined behaviour caused by incorrect `ExactSizeIterator` implementations. [#2124](https://github.com/PyO3/pyo3/pull/2124)
- Fix missing FFI definition `PyCMethod_New` on Python 3.9 and up. [#2143](https://github.com/PyO3/pyo3/pull/2143)
- Add missing FFI definitions `_PyLong_NumBits` and `_PyLong_AsByteArray` on PyPy. [#2146](https://github.com/PyO3/pyo3/pull/2146)
- Fix memory leak in implementation of `AsPyPointer` for `Option<T>`. [#2160](https://github.com/PyO3/pyo3/pull/2160)
- Fix the signature of `_PyLong_NumBits` [#2161](https://github.com/PyO3/pyo3/pull/2161)

View File

@ -1131,7 +1131,16 @@ fn default_lib_name_unix(
Some(ld_version) => format!("python{}", ld_version),
None => format!("python{}.{}", version.major, version.minor),
},
PythonImplementation::PyPy => format!("pypy{}-c", version.major),
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)
}
}
}
}
@ -1237,6 +1246,11 @@ fn fixup_config_for_abi3(
config: &mut InterpreterConfig,
abi3_version: Option<PythonVersion>,
) -> Result<()> {
// PyPy doesn't support abi3; don't adjust the version
if config.implementation.is_pypy() {
return Ok(());
}
if let Some(version) = abi3_version {
ensure!(
version <= config.version,
@ -1567,11 +1581,17 @@ mod tests {
"python3.7md",
);
// PyPy ignores ldversion
// PyPy 3.7 ignores ldversion
assert_eq!(
super::default_lib_name_unix(PythonVersion { major: 3, minor: 9 }, PyPy, Some("3.7md")),
super::default_lib_name_unix(PythonVersion { major: 3, minor: 7 }, PyPy, Some("3.7md")),
"pypy3-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",
);
}
#[test]

View File

@ -9,7 +9,7 @@ use crate::{
pyport::PY_SSIZE_T_MAX, vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET,
PyTuple_Check, PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL,
};
#[cfg(all(Py_3_8, not(PyPy)))]
#[cfg(Py_3_8)]
use libc::size_t;
extern "C" {
@ -101,17 +101,29 @@ pub unsafe fn PyObject_Vectorcall(
}
extern "C" {
#[cfg(all(Py_3_8, not(PyPy)))]
#[cfg_attr(not(Py_3_9), link_name = "_PyObject_VectorcallDict")]
#[cfg(all(PyPy, Py_3_8))]
#[cfg_attr(not(Py_3_9), link_name = "_PyPyObject_Vectorcall")]
pub fn PyObject_Vectorcall(
callable: *mut PyObject,
args: *const *mut PyObject,
nargsf: size_t,
kwnames: *mut PyObject,
) -> *mut PyObject;
#[cfg(all(Py_3_8))]
#[cfg_attr(all(not(PyPy), not(Py_3_9)), link_name = "_PyObject_VectorcallDict")]
#[cfg_attr(all(PyPy, not(Py_3_9)), link_name = "_PyPyObject_VectorcallDict")]
#[cfg_attr(all(PyPy, Py_3_9), link_name = "PyPyObject_VectorcallDict")]
pub fn PyObject_VectorcallDict(
callable: *mut PyObject,
args: *const *mut PyObject,
nargsf: size_t,
kwargs: *mut PyObject,
kwdict: *mut PyObject,
) -> *mut PyObject;
#[cfg(all(Py_3_8, not(PyPy)))]
#[cfg_attr(not(Py_3_9), link_name = "_PyVectorcall_Call")]
#[cfg(all(Py_3_8))]
#[cfg_attr(not(any(Py_3_9, PyPy)), link_name = "_PyVectorcall_Call")]
#[cfg_attr(PyPy, link_name = "PyPyVectorcall_Call")]
pub fn PyVectorcall_Call(
callable: *mut PyObject,
tuple: *mut PyObject,
@ -152,6 +164,12 @@ pub unsafe fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject {
)
}
extern "C" {
#[cfg(PyPy)]
#[link_name = "_PyPyObject_CallNoArg"]
pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject;
}
#[cfg(all(Py_3_8, not(PyPy)))]
#[inline(always)]
pub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {

View File

@ -117,6 +117,7 @@ pub union PyMethodDefPointer {
const _: () =
[()][mem::size_of::<PyMethodDefPointer>() - mem::size_of::<Option<extern "C" fn()>>()];
#[cfg(not(Py_3_9))]
extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyCFunction_New")]
pub fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject;
@ -129,7 +130,32 @@ extern "C" {
) -> *mut PyObject;
}
// skipped non-limited / 3.9 PyCMethod_New
#[cfg(Py_3_9)]
#[inline]
pub unsafe fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject {
PyCFunction_NewEx(ml, slf, std::ptr::null_mut())
}
#[cfg(Py_3_9)]
#[inline]
pub unsafe fn PyCFunction_NewEx(
ml: *mut PyMethodDef,
slf: *mut PyObject,
module: *mut PyObject,
) -> *mut PyObject {
PyCMethod_New(ml, slf, module, std::ptr::null_mut())
}
#[cfg(Py_3_9)]
extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyCMethod_New")]
pub fn PyCMethod_New(
ml: *mut PyMethodDef,
slf: *mut PyObject,
module: *mut PyObject,
cls: *mut PyTypeObject,
) -> *mut PyObject;
}
/* Flag passed to newmethodobject */
pub const METH_VARARGS: c_int = 0x0001;

View File

@ -583,7 +583,7 @@ impl<T> Py<T> {
/// This is equivalent to the Python expression `self()`.
pub fn call0(&self, py: Python) -> PyResult<PyObject> {
cfg_if::cfg_if! {
if #[cfg(Py_3_9)] {
if #[cfg(all(Py_3_9, not(PyPy)))] {
// Optimized path on python 3.9+
unsafe {
PyObject::from_owned_ptr_or_err(py, ffi::PyObject_CallNoArgs(self.as_ptr()))
@ -636,7 +636,7 @@ impl<T> Py<T> {
/// This is equivalent to the Python expression `self.name()`.
pub fn call_method0(&self, py: Python, name: &str) -> PyResult<PyObject> {
cfg_if::cfg_if! {
if #[cfg(all(Py_3_9, not(Py_LIMITED_API)))] {
if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy))))] {
// Optimized path on python 3.9+
unsafe {
let name = name.into_py(py);

View File

@ -218,7 +218,7 @@ fn type_object_creation_failed(py: Python, e: PyErr, name: &'static str) -> ! {
/// Additional type initializations necessary before Python 3.10
#[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]
unsafe fn tp_init_additional(
type_object: *mut ffi::PyTypeObject,
_type_object: *mut ffi::PyTypeObject,
_tp_doc: &str,
#[cfg(not(Py_3_9))] buffer_procs: &ffi::PyBufferProcs,
#[cfg(not(Py_3_9))] dict_offset: Option<ffi::Py_ssize_t>,
@ -236,10 +236,10 @@ unsafe fn tp_init_additional(
// heap-types, and it removed the text_signature value from it.
// We go in after the fact and replace tp_doc with something
// that _does_ include the text_signature value!
ffi::PyObject_Free((*type_object).tp_doc as _);
ffi::PyObject_Free((*_type_object).tp_doc as _);
let data = ffi::PyObject_Malloc(_tp_doc.len());
data.copy_from(_tp_doc.as_ptr() as _, _tp_doc.len());
(*type_object).tp_doc = data as _;
(*_type_object).tp_doc = data as _;
}
}
@ -247,15 +247,15 @@ unsafe fn tp_init_additional(
// Python 3.9, so on older versions we must manually fixup the type object.
#[cfg(not(Py_3_9))]
{
(*(*type_object).tp_as_buffer).bf_getbuffer = buffer_procs.bf_getbuffer;
(*(*type_object).tp_as_buffer).bf_releasebuffer = buffer_procs.bf_releasebuffer;
(*(*_type_object).tp_as_buffer).bf_getbuffer = buffer_procs.bf_getbuffer;
(*(*_type_object).tp_as_buffer).bf_releasebuffer = buffer_procs.bf_releasebuffer;
if let Some(dict_offset) = dict_offset {
(*type_object).tp_dictoffset = dict_offset;
(*_type_object).tp_dictoffset = dict_offset;
}
if let Some(weaklist_offset) = weaklist_offset {
(*type_object).tp_weaklistoffset = weaklist_offset;
(*_type_object).tp_weaklistoffset = weaklist_offset;
}
}
}

View File

@ -333,7 +333,7 @@ impl PyAny {
/// This is equivalent to the Python expression `help()`.
pub fn call0(&self) -> PyResult<&PyAny> {
cfg_if::cfg_if! {
if #[cfg(Py_3_9)] {
if #[cfg(all(Py_3_9, not(PyPy)))] {
// Optimized path on python 3.9+
unsafe {
self.py().from_owned_ptr_or_err(ffi::PyObject_CallNoArgs(self.as_ptr()))
@ -461,7 +461,7 @@ impl PyAny {
/// ```
pub fn call_method0(&self, name: &str) -> PyResult<&PyAny> {
cfg_if::cfg_if! {
if #[cfg(all(Py_3_9, not(Py_LIMITED_API)))] {
if #[cfg(all(Py_3_9, not(any(Py_LIMITED_API, PyPy))))] {
// Optimized path on python 3.9+
unsafe {
let name = name.into_py(self.py());