ffi: updates for Python 3.10

Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com>
This commit is contained in:
David Hewitt 2021-09-26 09:44:40 +01:00
parent a5d0aa777c
commit 7c4503e0ca
12 changed files with 115 additions and 29 deletions

View File

@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Packaging
- Support Python 3.10. [#1889](https://github.com/PyO3/pyo3/pull/1889)
### Added
- Add `PyList::get_item_unchecked` and `PyTuple::get_item_unchecked` to get items without bounds checks. [#1733](https://github.com/PyO3/pyo3/pull/1733)

View File

@ -110,7 +110,9 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyIter_Next")]
pub fn PyIter_Next(arg1: *mut PyObject) -> *mut PyObject;
// skipped non-limited / 3.10 PyIter_Send
#[cfg(all(not(PyPy), Py_3_10))]
#[cfg_attr(docsrs, doc(cfg(all(not(PyPy), Py_3_10))))]
pub fn PyIter_Send(iter: *mut PyObject, arg: *mut PyObject, presult: *mut *mut PyObject);
#[cfg_attr(PyPy, link_name = "PyPyNumber_Check")]
pub fn PyNumber_Check(o: *mut PyObject) -> c_int;

View File

@ -31,6 +31,16 @@ pub unsafe fn Py_True() -> *mut PyObject {
&mut _Py_TrueStruct as *mut PyLongObject as *mut PyObject
}
#[inline]
pub unsafe fn Py_IsTrue(x: *mut PyObject) -> c_int {
Py_Is(x, Py_True())
}
#[inline]
pub unsafe fn Py_IsFalse(x: *mut PyObject) -> c_int {
Py_Is(x, Py_False())
}
// skipped Py_RETURN_TRUE
// skipped Py_RETURN_FALSE

View File

@ -3,7 +3,9 @@ use std::os::raw::{c_char, c_int};
extern "C" {
pub fn PyCodec_Register(search_function: *mut PyObject) -> c_int;
// skipped PyCodec_Unregister
#[cfg(Py_3_10)]
#[cfg(not(PyPy))]
pub fn PyCodec_Unregister(search_function: *mut PyObject) -> c_int;
// skipped non-limited _PyCodec_Lookup from Include/codecs.h
// skipped non-limited _PyCodec_Forget from Include/codecs.h
pub fn PyCodec_KnownEncoding(encoding: *const c_char) -> c_int;

View File

@ -323,14 +323,6 @@ extern "C" {
// skipped _PyUnicode_FormatAdvancedWriter
extern "C" {
#[cfg(Py_3_7)]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8AndSize")]
pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *const c_char;
#[cfg(not(Py_3_7))]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8AndSize")]
pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *mut c_char;
// skipped _PyUnicode_AsStringAndSize
#[cfg(Py_3_7)]

View File

@ -53,21 +53,30 @@ extern "C" {
// skipped non-limited _PyArg_UnpackKeywords
// skipped non-limited _PyArg_Fini
// skipped PyModule_AddObjectRef
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn PyModule_AddObjectRef(
module: *mut PyObject,
name: *const c_char,
value: *mut PyObject,
) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyModule_AddObject")]
pub fn PyModule_AddObject(
arg1: *mut PyObject,
arg2: *const c_char,
arg3: *mut PyObject,
module: *mut PyObject,
name: *const c_char,
value: *mut PyObject,
) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyModule_AddIntConstant")]
pub fn PyModule_AddIntConstant(arg1: *mut PyObject, arg2: *const c_char, arg3: c_long)
-> c_int;
pub fn PyModule_AddIntConstant(
module: *mut PyObject,
name: *const c_char,
value: c_long,
) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyModule_AddStringConstant")]
pub fn PyModule_AddStringConstant(
arg1: *mut PyObject,
arg2: *const c_char,
arg3: *const c_char,
module: *mut PyObject,
name: *const c_char,
value: *const c_char,
) -> c_int;
// skipped non-limited / 3.9 PyModule_AddType
// skipped PyModule_AddIntMacro

View File

@ -85,6 +85,11 @@ pub struct PyVarObject {
// skipped _PyVarObject_CAST
// skipped _PyVarObject_CAST_CONST
#[inline]
pub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int {
(x == y).into()
}
// skipped _Py_REFCNT: defined in Py_REFCNT
#[inline]
@ -347,6 +352,14 @@ extern "C" {
// Flag bits for printing:
pub const Py_PRINT_RAW: c_int = 1; // No string quotes etc.
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub const Py_TPFLAGS_DISALLOW_INSTANTIATION: c_ulong = 1 << 7;
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub const Py_TPFLAGS_IMMUTABLETYPE: c_ulong = 1 << 8;
/// Set if the type object is dynamically allocated
pub const Py_TPFLAGS_HEAPTYPE: c_ulong = 1 << 9;
@ -454,10 +467,28 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPy_DecRef")]
pub fn Py_DecRef(o: *mut PyObject);
// skipped Py_NewRef
// skipped Py_XNewRef
// skipped _Py_NewRef
// skipped _Py_XNewRef
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;
}
// Technically these macros are only available in the C header from 3.10 and up, however their
// implementation works on all supported Python versions so we define these macros on all
// versions for simplicity.
#[inline]
pub unsafe fn _Py_NewRef(obj: *mut PyObject) -> *mut PyObject {
Py_INCREF(obj);
obj
}
#[inline]
pub unsafe fn _Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {
Py_XINCREF(obj);
obj
}
#[cfg_attr(windows, link(name = "pythonXY"))]
@ -471,6 +502,11 @@ pub unsafe fn Py_None() -> *mut PyObject {
&mut _Py_NoneStruct
}
#[inline]
pub unsafe fn Py_IsNone(x: *mut PyObject) -> c_int {
Py_Is(x, Py_None())
}
// skipped Py_RETURN_NONE
#[cfg_attr(windows, link(name = "pythonXY"))]
@ -494,7 +530,14 @@ pub const Py_NE: c_int = 3;
pub const Py_GT: c_int = 4;
pub const Py_GE: c_int = 5;
// skipped non-limited / 3.10 PySendResult
#[cfg(Py_3_10)]
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PySendResult {
PYGEN_RETURN = 0,
PYGEN_ERROR = -1,
PYGEN_NEXT = 1,
}
// skipped Py_RETURN_RICHCOMPARE

View File

@ -28,6 +28,14 @@ extern "C" {
pub fn _PyObject_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject;
pub fn PyGC_Collect() -> Py_ssize_t;
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn PyGC_Enable() -> c_int;
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn PyGC_Disable() -> c_int;
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn PyGC_IsEnabled() -> c_int;
}
#[repr(C)]

View File

@ -158,7 +158,7 @@ pub unsafe fn PyUnicodeDecodeError_Create(
end: Py_ssize_t,
_reason: *const c_char,
) -> *mut PyObject {
return crate::ffi::PyObject_CallFunction(
crate::ffi::PyObject_CallFunction(
PyExc_UnicodeDecodeError,
std::ffi::CStr::from_bytes_with_nul(b"sy#nns\0")
.unwrap()
@ -168,7 +168,7 @@ pub unsafe fn PyUnicodeDecodeError_Create(
length,
start,
end,
);
)
}
#[cfg_attr(windows, link(name = "pythonXY"))]
@ -374,6 +374,9 @@ extern "C" {
pub fn PyErr_CheckSignals() -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyErr_SetInterrupt")]
pub fn PyErr_SetInterrupt();
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub fn PyErr_SetInterruptEx(signum: c_int);
pub fn PyErr_SyntaxLocation(filename: *const c_char, lineno: c_int);
pub fn PyErr_SyntaxLocationEx(filename: *const c_char, lineno: c_int, col_offset: c_int);
pub fn PyErr_ProgramText(filename: *const c_char, lineno: c_int) -> *mut PyObject;

View File

@ -117,7 +117,12 @@ pub unsafe fn PyAnySet_Check(ob: *mut PyObject) -> c_int {
|| PyType_IsSubtype(Py_TYPE(ob), &mut PyFrozenSet_Type) != 0) as c_int
}
// skipped PySet_CheckExact
#[inline]
#[cfg(Py_3_10)]
#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]
pub unsafe fn PySet_CheckExact(op: *mut PyObject) -> c_int {
crate::ffi::Py_IS_TYPE(op, &mut PySet_Type)
}
extern "C" {
#[cfg(PyPy)]

View File

@ -165,6 +165,14 @@ extern "C" {
) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8String")]
pub fn PyUnicode_AsUTF8String(unicode: *mut PyObject) -> *mut PyObject;
#[cfg(any(Py_3_10, all(Py_3_7, not(Py_LIMITED_API))))]
#[cfg_attr(docsrs, doc(cfg(any(Py_3_10, not(Py_LIMITED_API)))))]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8AndSize")]
pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *const c_char;
#[cfg(not(any(Py_3_7, Py_LIMITED_API)))]
#[cfg_attr(docsrs, doc(cfg(any(Py_3_10, not(Py_LIMITED_API)))))]
#[cfg_attr(PyPy, link_name = "PyPyUnicode_AsUTF8AndSize")]
pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *mut c_char;
#[cfg_attr(PyPy, link_name = "PyPyUnicode_DecodeUTF32")]
pub fn PyUnicode_DecodeUTF32(
string: *const c_char,

View File

@ -167,8 +167,8 @@ impl PyString {
pub fn to_str(&self) -> PyResult<&str> {
let utf8_slice = {
cfg_if::cfg_if! {
if #[cfg(not(Py_LIMITED_API))] {
// PyUnicode_AsUTF8AndSize only available on limited API.
if #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] {
// PyUnicode_AsUTF8AndSize only available on limited API before 3.10.
let mut size: ffi::Py_ssize_t = 0;
let data = unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size) };
if data.is_null() {