diff --git a/newsfragments/6038.added.md b/newsfragments/6038.added.md new file mode 100644 index 00000000000..62a29b3f123 --- /dev/null +++ b/newsfragments/6038.added.md @@ -0,0 +1 @@ +Add FFI definitions `PyEval_SetProfileAllThreads` and `PyEval_SetTraceAllThreads`. diff --git a/newsfragments/6038.changed.md b/newsfragments/6038.changed.md new file mode 100644 index 00000000000..a4d21f0361e --- /dev/null +++ b/newsfragments/6038.changed.md @@ -0,0 +1 @@ +FFI definitions `_PyCode_GetExtra`, `_PyCode_SetExtra`, and `_PyEval_RequestCodeExtraIndex` have been updated to `PyUnstable_Code_GetExtra`, `PyUnstable_Code_SetExtra`, and `PyUnstable_Eval_RequestCodeExtraIndex`. diff --git a/newsfragments/6038.removed.md b/newsfragments/6038.removed.md new file mode 100644 index 00000000000..cfa1f7fdf57 --- /dev/null +++ b/newsfragments/6038.removed.md @@ -0,0 +1 @@ +Remove private FFI definition `_PyEval_EvalFrameDefault`. diff --git a/pyo3-ffi-check/macro/src/lib.rs b/pyo3-ffi-check/macro/src/lib.rs index 7151e938c2a..9363f0fabec 100644 --- a/pyo3-ffi-check/macro/src/lib.rs +++ b/pyo3-ffi-check/macro/src/lib.rs @@ -424,6 +424,9 @@ const MACRO_EXCLUSIONS: &[(&str, &str)] = &[ ("Py_TYPE", "not(Py_3_14)"), ("Py_XDECREF", ""), ("Py_XINCREF", ""), + ("_PyCode_GetExtra", "Py_3_12"), + ("_PyCode_SetExtra", "Py_3_12"), + ("_PyEval_RequestCodeExtraIndex", "Py_3_12"), // These functions were only added in 3.10, but pyo3-ffi defines them for // all versions. Technically not macros but the machinery happens to work // the same way. @@ -435,10 +438,11 @@ const MACRO_EXCLUSIONS: &[(&str, &str)] = &[ // TODO: probably need to clean these up const EXCLUDED_SYMBOLS: &[&str] = &[ - // CPython deprecated these but the symbols still exist, pyo3-ffi will probably clean them up anyway - "_PyCode_GetExtra", - "_PyCode_SetExtra", - "_PyEval_RequestCodeExtraIndex", + // CPython moved these to the unstable API in 3.12, we exposed these for all versions just + // to keep it simpler to migrate + "PyUnstable_Code_GetExtra", + "PyUnstable_Code_SetExtra", + "PyUnstable_Eval_RequestCodeExtraIndex", // FIXME: probably outdated definitions that fail to build, need investigation, // temporarily here to make the build pass to get CI running "_PyFloat_CAST", @@ -483,10 +487,6 @@ const EXCLUDED_SYMBOLS: &[&str] = &[ "PyObject_Vectorcall", "PyVectorcall_Function", "PyObject_VectorcallDict", - // Needs fixing: since 3.9 it takes thread state as first argument - "_PyEval_EvalFrameDefault", - // Needs fixing: argument count is wrong on 3.13 against headers - "_PyLong_AsByteArray", // CPython gates these on a HAVE_FORK macro, pyo3-ffi needs to replicate this? "PyOS_BeforeFork", "PyOS_AfterFork_Parent", diff --git a/pyo3-ffi/src/cpython/ceval.rs b/pyo3-ffi/src/cpython/ceval.rs index 682280b6c15..ea12ccfc338 100644 --- a/pyo3-ffi/src/cpython/ceval.rs +++ b/pyo3-ffi/src/cpython/ceval.rs @@ -1,21 +1,46 @@ use crate::cpython::pystate::Py_tracefunc; use crate::object::{freefunc, PyObject}; -use core::ffi::c_int; +use crate::Py_ssize_t; extern_libpython! { - // skipped non-limited _PyEval_CallTracing + pub fn PyEval_SetProfile(trace_func: Option, arg1: *mut PyObject); + #[cfg(Py_3_12)] + pub fn PyEval_SetProfileAllThreads(trace_func: Option, arg1: *mut PyObject); + pub fn PyEval_SetTrace(trace_func: Option, arg1: *mut PyObject); + #[cfg(Py_3_12)] + pub fn PyEval_SetTraceAllThreads(trace_func: Option, arg1: *mut PyObject); - #[cfg(not(Py_3_11))] - pub fn _PyEval_EvalFrameDefault(arg1: *mut crate::PyFrameObject, exc: c_int) -> *mut PyObject; + // skipped PyEval_MergeCompilerFlags - #[cfg(Py_3_11)] - pub fn _PyEval_EvalFrameDefault( - tstate: *mut crate::PyThreadState, - frame: *mut crate::_PyInterpreterFrame, - exc: c_int, - ) -> *mut crate::PyObject; + // skipped private _PyEval_EvalFrameDefault + + // was moved to the unstable API tier on Py_3_12, use link_name for older versions + #[cfg_attr(Py_3_12, link_name = "_PyEval_RequestCodeExtraIndex")] + pub fn PyUnstable_Eval_RequestCodeExtraIndex(func: freefunc) -> Py_ssize_t; +} + +#[deprecated( + since = "0.29.0", + note = "renamed to PyUnstable_Eval_RequestCodeExtraIndex" +)] +#[inline] +pub unsafe extern "C" fn _PyEval_RequestCodeExtraIndex(func: freefunc) -> Py_ssize_t { + PyUnstable_Eval_RequestCodeExtraIndex(func) +} + +extern_libpython! { + + // skipped private _PyEval_SliceIndex + // skipped private _PyEval_SliceIndexNotNone + // skipped private _PyEval_UnpackIndices + + // skipped PerfMapState + + // skipped PyUnstable_PerfMapState_Init + // skipped PyUnstable_WritePerfMapEntry + // skipped PyUnstable_PerfMapState_Fini + // skipped PyUnstable_CopyPerfMapFile + // skipped PyUnstable_PerfTrampoline_CompileCode + // skipped PyUnstable_PerfTrampoline_SetPersistAfterFork - pub fn _PyEval_RequestCodeExtraIndex(func: freefunc) -> c_int; - pub fn PyEval_SetProfile(trace_func: Option, arg1: *mut PyObject); - pub fn PyEval_SetTrace(trace_func: Option, arg1: *mut PyObject); } diff --git a/pyo3-ffi/src/cpython/code.rs b/pyo3-ffi/src/cpython/code.rs index 9744256002a..10c25cad9cd 100644 --- a/pyo3-ffi/src/cpython/code.rs +++ b/pyo3-ffi/src/cpython/code.rs @@ -140,10 +140,38 @@ extern_libpython! { names: *mut PyObject, lnotab: *mut PyObject, ) -> *mut PyObject; - pub fn _PyCode_GetExtra( + + #[cfg_attr(not(Py_3_12), link_name = "_PyCode_GetExtra")] + pub fn PyUnstable_Code_GetExtra( + code: *mut PyObject, + index: Py_ssize_t, + extra: *mut *mut c_void, + ) -> c_int; + + #[cfg_attr(not(Py_3_12), link_name = "_PyCode_SetExtra")] + pub fn PyUnstable_Code_SetExtra( code: *mut PyObject, index: Py_ssize_t, - extra: *const *mut c_void, + extra: *mut c_void, ) -> c_int; - pub fn _PyCode_SetExtra(code: *mut PyObject, index: Py_ssize_t, extra: *mut c_void) -> c_int; +} + +#[deprecated(since = "0.29.0", note = "renamed to PyUnstable_Code_GetExtra")] +#[inline] +pub unsafe extern "C" fn _PyCode_GetExtra( + code: *mut PyObject, + index: Py_ssize_t, + extra: *mut *mut c_void, +) -> c_int { + PyUnstable_Code_GetExtra(code, index, extra) +} + +#[deprecated(since = "0.29.0", note = "renamed to PyUnstable_Code_SetExtra")] +#[inline] +pub unsafe extern "C" fn _PyCode_SetExtra( + code: *mut PyObject, + index: Py_ssize_t, + extra: *mut c_void, +) -> c_int { + PyUnstable_Code_SetExtra(code, index, extra) } diff --git a/pyo3-ffi/src/cpython/longobject.rs b/pyo3-ffi/src/cpython/longobject.rs index ef0e2c465b1..f5d50979ea5 100644 --- a/pyo3-ffi/src/cpython/longobject.rs +++ b/pyo3-ffi/src/cpython/longobject.rs @@ -1,10 +1,13 @@ +#[cfg(not(Py_3_13))] use crate::longobject::*; use crate::object::*; #[cfg(Py_3_13)] use crate::pyport::Py_ssize_t; +use core::ffi::c_int; +#[cfg(not(Py_3_13))] +use core::ffi::c_uchar; #[cfg(Py_3_13)] use core::ffi::c_void; -use core::ffi::{c_int, c_uchar}; use libc::size_t; #[cfg(Py_3_13)] @@ -53,7 +56,9 @@ extern_libpython! { // skipped PyUnstable_Long_IsCompact // skipped PyUnstable_Long_CompactValue + #[cfg(not(Py_3_13))] #[cfg_attr(PyPy, link_name = "_PyPyLong_FromByteArray")] + #[doc(hidden)] // used in PyO3's older bytes conversions, but not otherwise public API pub fn _PyLong_FromByteArray( bytes: *const c_uchar, n: size_t, @@ -61,6 +66,8 @@ extern_libpython! { is_signed: c_int, ) -> *mut PyObject; + #[cfg(not(Py_3_13))] + #[doc(hidden)] // used in PyO3's older bytes conversions, but not otherwise public API #[cfg_attr(PyPy, link_name = "_PyPyLong_AsByteArrayO")] pub fn _PyLong_AsByteArray( v: *mut PyLongObject, diff --git a/pyo3-ffi/src/cpython/pyframe.rs b/pyo3-ffi/src/cpython/pyframe.rs index b672ad103b9..1e244c14abe 100644 --- a/pyo3-ffi/src/cpython/pyframe.rs +++ b/pyo3-ffi/src/cpython/pyframe.rs @@ -5,7 +5,6 @@ use crate::{PyObject, PyTypeObject, Py_IS_TYPE}; use core::ffi::c_char; use core::ffi::c_int; -// NB used in `_PyEval_EvalFrameDefault`, maybe we remove this too. #[cfg(all(Py_3_11, not(PyPy)))] opaque_struct!(pub _PyInterpreterFrame); diff --git a/pyo3-ffi/src/impl_/macros.rs b/pyo3-ffi/src/impl_/macros.rs index 466fbb8f4de..66dfb4920f9 100644 --- a/pyo3-ffi/src/impl_/macros.rs +++ b/pyo3-ffi/src/impl_/macros.rs @@ -56,30 +56,6 @@ macro_rules! extern_libpython_maybe_private_fn { ) => { extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? } }; - ( - [_PyEval_EvalFrameDefault] - $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)? - ) => { - extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? } - }; - ( - [_PyEval_RequestCodeExtraIndex] - $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)? - ) => { - extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? } - }; - ( - [_PyCode_GetExtra] - $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)? - ) => { - extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? } - }; - ( - [_PyCode_SetExtra] - $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)? - ) => { - extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? } - }; ( [_PyLong_AsByteArray] $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?