From ae2fb49f5f3e12e891042cf827f38080c1f26578 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Fri, 6 Sep 2024 17:28:23 -0600 Subject: [PATCH] update FFI bindings to reflect deprecated and removed items (#4534) * update FFI bindings to reflect deprecated and removed items * Update ceval.rs Co-authored-by: Lily Foote * fix ffi-check * add changelog entries --------- Co-authored-by: Lily Foote --- newsfragments/4534.changed.md | 3 ++ newsfragments/4534.removed.md | 1 + pyo3-ffi-check/src/main.rs | 3 +- pyo3-ffi/src/ceval.rs | 17 +++++++++++ pyo3-ffi/src/cpython/bytesobject.rs | 4 +++ pyo3-ffi/src/cpython/dictobject.rs | 4 +++ pyo3-ffi/src/cpython/pyerrors.rs | 5 +--- pyo3-ffi/src/cpython/unicodeobject.rs | 42 ++++++++++++--------------- pyo3-ffi/src/methodobject.rs | 1 + pyo3-ffi/src/pylifecycle.rs | 41 ++++++++++++++++++++++++-- pyo3-ffi/src/sysmodule.rs | 18 ++++++++++++ pyo3-ffi/src/unicodeobject.rs | 4 +++ 12 files changed, 112 insertions(+), 31 deletions(-) create mode 100644 newsfragments/4534.changed.md create mode 100644 newsfragments/4534.removed.md diff --git a/newsfragments/4534.changed.md b/newsfragments/4534.changed.md new file mode 100644 index 00000000000..c6ff877976d --- /dev/null +++ b/newsfragments/4534.changed.md @@ -0,0 +1,3 @@ +* Updated the FFI bindings for functions and struct fields that have been + deprecated or removed. You may see new deprecation warnings if you are using + functions or fields exposed by the C API that are deprecated. diff --git a/newsfragments/4534.removed.md b/newsfragments/4534.removed.md new file mode 100644 index 00000000000..3ecd27f5eb9 --- /dev/null +++ b/newsfragments/4534.removed.md @@ -0,0 +1 @@ +* Removed the bindings for the private function `_PyErr_ChainExceptions`. diff --git a/pyo3-ffi-check/src/main.rs b/pyo3-ffi-check/src/main.rs index 99713524702..0407a2ffa39 100644 --- a/pyo3-ffi-check/src/main.rs +++ b/pyo3-ffi-check/src/main.rs @@ -48,7 +48,8 @@ fn main() { macro_rules! check_field { ($struct_name:ident, $field:ident, $bindgen_field:ident) => {{ - #[allow(clippy::used_underscore_binding)] + // some struct fields are deprecated but still present in the ABI + #[allow(clippy::used_underscore_binding, deprecated)] let pyo3_ffi_offset = memoffset::offset_of!(pyo3_ffi::$struct_name, $field); #[allow(clippy::used_underscore_binding)] let bindgen_offset = memoffset::offset_of!(bindings::$struct_name, $bindgen_field); diff --git a/pyo3-ffi/src/ceval.rs b/pyo3-ffi/src/ceval.rs index 7aae25f8c3e..d1839a108cb 100644 --- a/pyo3-ffi/src/ceval.rs +++ b/pyo3-ffi/src/ceval.rs @@ -24,6 +24,7 @@ extern "C" { closure: *mut PyObject, ) -> *mut PyObject; + #[cfg(not(Py_3_13))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[cfg_attr(PyPy, link_name = "PyPyEval_CallObjectWithKeywords")] pub fn PyEval_CallObjectWithKeywords( @@ -33,6 +34,7 @@ extern "C" { ) -> *mut PyObject; } +#[cfg(not(Py_3_13))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[inline] pub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject { @@ -41,9 +43,11 @@ pub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut } extern "C" { + #[cfg(not(Py_3_13))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[cfg_attr(PyPy, link_name = "PyPyEval_CallFunction")] pub fn PyEval_CallFunction(obj: *mut PyObject, format: *const c_char, ...) -> *mut PyObject; + #[cfg(not(Py_3_13))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] #[cfg_attr(PyPy, link_name = "PyPyEval_CallMethod")] pub fn PyEval_CallMethod( @@ -95,9 +99,22 @@ extern "C" { } extern "C" { + #[cfg(not(Py_3_13))] #[cfg_attr(PyPy, link_name = "PyPyEval_ThreadsInitialized")] + #[cfg_attr( + Py_3_9, + deprecated( + note = "Deprecated in Python 3.9, this function always returns true in Python 3.7 or newer." + ) + )] pub fn PyEval_ThreadsInitialized() -> c_int; #[cfg_attr(PyPy, link_name = "PyPyEval_InitThreads")] + #[cfg_attr( + Py_3_9, + deprecated( + note = "Deprecated in Python 3.9, this function does nothing in Python 3.7 or newer." + ) + )] pub fn PyEval_InitThreads(); pub fn PyEval_AcquireLock(); pub fn PyEval_ReleaseLock(); diff --git a/pyo3-ffi/src/cpython/bytesobject.rs b/pyo3-ffi/src/cpython/bytesobject.rs index d0ac5b9c30e..306702de25e 100644 --- a/pyo3-ffi/src/cpython/bytesobject.rs +++ b/pyo3-ffi/src/cpython/bytesobject.rs @@ -8,6 +8,10 @@ use std::os::raw::c_int; #[repr(C)] pub struct PyBytesObject { pub ob_base: PyVarObject, + #[cfg_attr( + Py_3_11, + deprecated(note = "Deprecated in Python 3.11 and will be removed in a future version.") + )] pub ob_shash: crate::Py_hash_t, pub ob_sval: [c_char; 1], } diff --git a/pyo3-ffi/src/cpython/dictobject.rs b/pyo3-ffi/src/cpython/dictobject.rs index 74b970ebac2..79dcbfdb62e 100644 --- a/pyo3-ffi/src/cpython/dictobject.rs +++ b/pyo3-ffi/src/cpython/dictobject.rs @@ -13,6 +13,10 @@ opaque_struct!(PyDictValues); pub struct PyDictObject { pub ob_base: PyObject, pub ma_used: Py_ssize_t, + #[cfg_attr( + Py_3_12, + deprecated(note = "Deprecated in Python 3.12 and will be removed in the future.") + )] pub ma_version_tag: u64, pub ma_keys: *mut PyDictKeysObject, #[cfg(not(Py_3_11))] diff --git a/pyo3-ffi/src/cpython/pyerrors.rs b/pyo3-ffi/src/cpython/pyerrors.rs index 6d17ebc8124..ca08b44a95c 100644 --- a/pyo3-ffi/src/cpython/pyerrors.rs +++ b/pyo3-ffi/src/cpython/pyerrors.rs @@ -152,10 +152,7 @@ pub struct PyStopIterationObject { pub value: *mut PyObject, } -extern "C" { - #[cfg(not(any(PyPy, GraalPy)))] - pub fn _PyErr_ChainExceptions(typ: *mut PyObject, val: *mut PyObject, tb: *mut PyObject); -} +// skipped _PyErr_ChainExceptions // skipped PyNameErrorObject // skipped PyAttributeErrorObject diff --git a/pyo3-ffi/src/cpython/unicodeobject.rs b/pyo3-ffi/src/cpython/unicodeobject.rs index feb78cf0c82..1414b4ceb38 100644 --- a/pyo3-ffi/src/cpython/unicodeobject.rs +++ b/pyo3-ffi/src/cpython/unicodeobject.rs @@ -1,7 +1,6 @@ #[cfg(not(any(PyPy, GraalPy)))] use crate::Py_hash_t; -use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_UNICODE, Py_ssize_t}; -#[cfg(not(any(Py_3_12, GraalPy)))] +use crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_ssize_t}; use libc::wchar_t; use std::os::raw::{c_char, c_int, c_uint, c_void}; @@ -588,7 +587,7 @@ extern "C" { #[cfg(not(Py_3_12))] #[deprecated] #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromUnicode")] - pub fn PyUnicode_FromUnicode(u: *const Py_UNICODE, size: Py_ssize_t) -> *mut PyObject; + pub fn PyUnicode_FromUnicode(u: *const wchar_t, size: Py_ssize_t) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyUnicode_FromKindAndData")] pub fn PyUnicode_FromKindAndData( @@ -603,7 +602,7 @@ extern "C" { #[cfg(not(Py_3_12))] #[deprecated] #[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUnicode")] - pub fn PyUnicode_AsUnicode(unicode: *mut PyObject) -> *mut Py_UNICODE; + pub fn PyUnicode_AsUnicode(unicode: *mut PyObject) -> *mut wchar_t; // skipped _PyUnicode_AsUnicode @@ -613,7 +612,7 @@ extern "C" { pub fn PyUnicode_AsUnicodeAndSize( unicode: *mut PyObject, size: *mut Py_ssize_t, - ) -> *mut Py_UNICODE; + ) -> *mut wchar_t; // skipped PyUnicode_GetMax } @@ -642,14 +641,14 @@ extern "C" { // skipped _PyUnicode_AsString pub fn PyUnicode_Encode( - s: *const Py_UNICODE, + s: *const wchar_t, size: Py_ssize_t, encoding: *const c_char, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_EncodeUTF7( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, base64SetO: c_int, base64WhiteSpace: c_int, @@ -661,13 +660,13 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeUTF8")] pub fn PyUnicode_EncodeUTF8( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_EncodeUTF32( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, errors: *const c_char, byteorder: c_int, @@ -676,7 +675,7 @@ extern "C" { // skipped _PyUnicode_EncodeUTF32 pub fn PyUnicode_EncodeUTF16( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, errors: *const c_char, byteorder: c_int, @@ -685,13 +684,11 @@ extern "C" { // skipped _PyUnicode_EncodeUTF16 // skipped _PyUnicode_DecodeUnicodeEscape - pub fn PyUnicode_EncodeUnicodeEscape( - data: *const Py_UNICODE, - length: Py_ssize_t, - ) -> *mut PyObject; + pub fn PyUnicode_EncodeUnicodeEscape(data: *const wchar_t, length: Py_ssize_t) + -> *mut PyObject; pub fn PyUnicode_EncodeRawUnicodeEscape( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, ) -> *mut PyObject; @@ -699,7 +696,7 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeLatin1")] pub fn PyUnicode_EncodeLatin1( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; @@ -708,13 +705,13 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeASCII")] pub fn PyUnicode_EncodeASCII( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, errors: *const c_char, ) -> *mut PyObject; pub fn PyUnicode_EncodeCharmap( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, mapping: *mut PyObject, errors: *const c_char, @@ -723,7 +720,7 @@ extern "C" { // skipped _PyUnicode_EncodeCharmap pub fn PyUnicode_TranslateCharmap( - data: *const Py_UNICODE, + data: *const wchar_t, length: Py_ssize_t, table: *mut PyObject, errors: *const c_char, @@ -733,17 +730,14 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPyUnicode_EncodeDecimal")] pub fn PyUnicode_EncodeDecimal( - s: *mut Py_UNICODE, + s: *mut wchar_t, length: Py_ssize_t, output: *mut c_char, errors: *const c_char, ) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyUnicode_TransformDecimalToASCII")] - pub fn PyUnicode_TransformDecimalToASCII( - s: *mut Py_UNICODE, - length: Py_ssize_t, - ) -> *mut PyObject; + pub fn PyUnicode_TransformDecimalToASCII(s: *mut wchar_t, length: Py_ssize_t) -> *mut PyObject; // skipped _PyUnicode_TransformDecimalAndSpaceToASCII } diff --git a/pyo3-ffi/src/methodobject.rs b/pyo3-ffi/src/methodobject.rs index 8af41eda817..3dfbbb5a208 100644 --- a/pyo3-ffi/src/methodobject.rs +++ b/pyo3-ffi/src/methodobject.rs @@ -85,6 +85,7 @@ extern "C" { pub fn PyCFunction_GetFunction(f: *mut PyObject) -> Option; pub fn PyCFunction_GetSelf(f: *mut PyObject) -> *mut PyObject; pub fn PyCFunction_GetFlags(f: *mut PyObject) -> c_int; + #[cfg(not(Py_3_13))] #[cfg_attr(Py_3_9, deprecated(note = "Python 3.9"))] pub fn PyCFunction_Call( f: *mut PyObject, diff --git a/pyo3-ffi/src/pylifecycle.rs b/pyo3-ffi/src/pylifecycle.rs index 7f73e3f0e9b..3f051c54f7c 100644 --- a/pyo3-ffi/src/pylifecycle.rs +++ b/pyo3-ffi/src/pylifecycle.rs @@ -23,18 +23,55 @@ extern "C" { pub fn Py_Main(argc: c_int, argv: *mut *mut wchar_t) -> c_int; pub fn Py_BytesMain(argc: c_int, argv: *mut *mut c_char) -> c_int; + #[cfg_attr( + Py_3_11, + deprecated(note = "Deprecated since Python 3.11. Use `PyConfig.program_name` instead.") + )] pub fn Py_SetProgramName(arg1: *const wchar_t); #[cfg_attr(PyPy, link_name = "PyPy_GetProgramName")] + #[cfg_attr( + Py_3_13, + deprecated(note = "Deprecated since Python 3.13. Use `sys.executable` instead.") + )] pub fn Py_GetProgramName() -> *mut wchar_t; + #[cfg_attr( + Py_3_11, + deprecated(note = "Deprecated since Python 3.11. Use `PyConfig.home` instead.") + )] pub fn Py_SetPythonHome(arg1: *const wchar_t); + #[cfg_attr( + Py_3_13, + deprecated( + note = "Deprecated since Python 3.13. Use `PyConfig.home` or the value of the `PYTHONHOME` environment variable instead." + ) + )] pub fn Py_GetPythonHome() -> *mut wchar_t; - + #[cfg_attr( + Py_3_13, + deprecated(note = "Deprecated since Python 3.13. Use `sys.executable` instead.") + )] pub fn Py_GetProgramFullPath() -> *mut wchar_t; - + #[cfg_attr( + Py_3_13, + deprecated(note = "Deprecated since Python 3.13. Use `sys.prefix` instead.") + )] pub fn Py_GetPrefix() -> *mut wchar_t; + #[cfg_attr( + Py_3_13, + deprecated(note = "Deprecated since Python 3.13. Use `sys.exec_prefix` instead.") + )] pub fn Py_GetExecPrefix() -> *mut wchar_t; + #[cfg_attr( + Py_3_13, + deprecated(note = "Deprecated since Python 3.13. Use `sys.path` instead.") + )] pub fn Py_GetPath() -> *mut wchar_t; + #[cfg(not(Py_3_13))] + #[cfg_attr( + Py_3_11, + deprecated(note = "Deprecated since Python 3.11. Use `sys.path` instead.") + )] pub fn Py_SetPath(arg1: *const wchar_t); // skipped _Py_CheckPython3 diff --git a/pyo3-ffi/src/sysmodule.rs b/pyo3-ffi/src/sysmodule.rs index 3c552254244..6f402197ece 100644 --- a/pyo3-ffi/src/sysmodule.rs +++ b/pyo3-ffi/src/sysmodule.rs @@ -8,7 +8,19 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPySys_SetObject")] pub fn PySys_SetObject(arg1: *const c_char, arg2: *mut PyObject) -> c_int; + #[cfg_attr( + Py_3_11, + deprecated( + note = "Deprecated in Python 3.11, use `PyConfig.argv` and `PyConfig.parse_argv` instead" + ) + )] pub fn PySys_SetArgv(arg1: c_int, arg2: *mut *mut wchar_t); + #[cfg_attr( + Py_3_11, + deprecated( + note = "Deprecated in Python 3.11, use `PyConfig.argv` and `PyConfig.parse_argv` instead" + ) + )] pub fn PySys_SetArgvEx(arg1: c_int, arg2: *mut *mut wchar_t, arg3: c_int); pub fn PySys_SetPath(arg1: *const wchar_t); @@ -19,6 +31,12 @@ extern "C" { pub fn PySys_FormatStdout(format: *const c_char, ...); pub fn PySys_FormatStderr(format: *const c_char, ...); + #[cfg_attr( + Py_3_13, + deprecated( + note = "Deprecated since Python 3.13. Clear sys.warnoptions and warnings.filters instead." + ) + )] pub fn PySys_ResetWarnOptions(); #[cfg_attr(Py_3_11, deprecated(note = "Python 3.11"))] pub fn PySys_AddWarnOption(arg1: *const wchar_t); diff --git a/pyo3-ffi/src/unicodeobject.rs b/pyo3-ffi/src/unicodeobject.rs index 519bbf261f9..1e0425ce2a2 100644 --- a/pyo3-ffi/src/unicodeobject.rs +++ b/pyo3-ffi/src/unicodeobject.rs @@ -6,6 +6,10 @@ use std::os::raw::{c_char, c_int, c_void}; use std::ptr::addr_of_mut; #[cfg(not(Py_LIMITED_API))] +#[cfg_attr( + Py_3_13, + deprecated(note = "Deprecated since Python 3.13. Use `libc::wchar_t` instead.") +)] pub type Py_UNICODE = wchar_t; pub type Py_UCS4 = u32;