Skip to content

Commit 0c362a8

Browse files
committed
Add support for the 3.15 ABI as ob 3.15.0b1
1 parent f57bda7 commit 0c362a8

14 files changed

Lines changed: 312 additions & 177 deletions

File tree

.github/workflows/ci.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,24 @@ jobs:
204204
python-architecture: "x64",
205205
rust-target: "x86_64-unknown-linux-gnu",
206206
}
207+
# Also test Python 3.15 and 3.15t, on ubuntu
208+
# (run for all OSes on build-full)
209+
- rust: stable
210+
python-version: "3.15-dev"
211+
platform:
212+
{
213+
os: "ubuntu-latest",
214+
python-architecture: "x64",
215+
rust-target: "x86_64-unknown-linux-gnu",
216+
}
217+
- rust: stable
218+
python-version: "3.15t-dev"
219+
platform:
220+
{
221+
os: "ubuntu-latest",
222+
python-architecture: "x64",
223+
rust-target: "x86_64-unknown-linux-gnu",
224+
}
207225

208226
build-full:
209227
if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}

pyo3-ffi-check/macro/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ pub fn for_all_fields(input: proc_macro::TokenStream) -> proc_macro::TokenStream
181181
// the field name in the C API is `type`, but that's a keyword in Rust
182182
// so PyO3 picked type_code, bindgen picked type_
183183
Ident::new("type_", Span::call_site())
184+
} else if struct_name == "PySlot" && field_name == "anon1" {
185+
// PySlot has two anonymous unions (since they aren't allowed in Rust,
186+
// PyO3 invented names for them); bindgen names the first one __bindgen_anon_1
187+
Ident::new("__bindgen_anon_1", Span::call_site())
188+
} else if struct_name == "PySlot" && field_name == "anon2" {
189+
// ...and the second one __bindgen_anon_2
190+
Ident::new("__bindgen_anon_2", Span::call_site())
184191
} else {
185192
field_ident.clone()
186193
};

pyo3-ffi/examples/sequential/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ pub unsafe extern "C" fn PyInit_sequential() -> *mut PyObject {
1717
#[cfg(Py_3_15)]
1818
#[allow(non_snake_case, reason = "must be named `PyModExport_<your_module>`")]
1919
#[no_mangle]
20-
pub unsafe extern "C" fn PyModExport_sequential() -> *mut PyModuleDef_Slot {
20+
pub unsafe extern "C" fn PyModExport_sequential() -> *mut PySlot {
2121
(&raw mut SEQUENTIAL_SLOTS).cast()
2222
}

pyo3-ffi/examples/sequential/src/module.rs

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,44 +20,36 @@ PyABIInfo_VAR!(ABI_INFO);
2020

2121
const SEQUENTIAL_SLOTS_LEN: usize =
2222
2 + cfg!(Py_3_12) as usize + cfg!(Py_GIL_DISABLED) as usize + 7 * (cfg!(Py_3_15) as usize);
23+
#[cfg(Py_3_15)]
24+
pub static mut SEQUENTIAL_SLOTS: [PySlot; SEQUENTIAL_SLOTS_LEN] = [
25+
PySlot_STATIC_DATA(Py_mod_abi, (&raw mut ABI_INFO).cast()),
26+
PySlot_STATIC_DATA(Py_mod_name, c"sequential".as_ptr() as *mut c_void),
27+
PySlot_STATIC_DATA(
28+
Py_mod_doc,
29+
c"A library for generating sequential ids, written in Rust.".as_ptr() as *mut c_void,
30+
),
31+
PySlot_SIZE(
32+
Py_mod_state_size,
33+
mem::size_of::<sequential_state>() as Py_ssize_t,
34+
),
35+
PySlot_FUNC!(Py_mod_state_traverse, traverseproc, sequential_traverse),
36+
PySlot_FUNC!(Py_mod_state_clear, inquiry, sequential_clear),
37+
PySlot_FUNC!(Py_mod_state_free, freefunc, sequential_free),
38+
PySlot_FUNC!(
39+
Py_mod_exec,
40+
unsafe extern "C" fn(*mut PyObject) -> c_int,
41+
sequential_exec
42+
),
43+
PySlot_DATA(
44+
Py_mod_multiple_interpreters,
45+
Py_MOD_PER_INTERPRETER_GIL_SUPPORTED,
46+
),
47+
#[cfg(Py_GIL_DISABLED)]
48+
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
49+
PySlot_END(),
50+
];
51+
#[cfg(not(Py_3_15))]
2352
pub static mut SEQUENTIAL_SLOTS: [PyModuleDef_Slot; SEQUENTIAL_SLOTS_LEN] = [
24-
#[cfg(Py_3_15)]
25-
PyModuleDef_Slot {
26-
slot: Py_mod_abi,
27-
value: (&raw mut ABI_INFO).cast(),
28-
},
29-
#[cfg(Py_3_15)]
30-
PyModuleDef_Slot {
31-
slot: Py_mod_name,
32-
// safety: Python does not write to this field
33-
value: c"sequential".as_ptr() as *mut c_void,
34-
},
35-
#[cfg(Py_3_15)]
36-
PyModuleDef_Slot {
37-
slot: Py_mod_doc,
38-
// safety: Python does not write to this field
39-
value: c"A library for generating sequential ids, written in Rust.".as_ptr() as *mut c_void,
40-
},
41-
#[cfg(Py_3_15)]
42-
PyModuleDef_Slot {
43-
slot: Py_mod_state_size,
44-
value: mem::size_of::<sequential_state>() as *mut c_void,
45-
},
46-
#[cfg(Py_3_15)]
47-
PyModuleDef_Slot {
48-
slot: Py_mod_state_traverse,
49-
value: sequential_traverse as *mut c_void,
50-
},
51-
#[cfg(Py_3_15)]
52-
PyModuleDef_Slot {
53-
slot: Py_mod_state_clear,
54-
value: sequential_clear as *mut c_void,
55-
},
56-
#[cfg(Py_3_15)]
57-
PyModuleDef_Slot {
58-
slot: Py_mod_state_free,
59-
value: sequential_free as *mut c_void,
60-
},
6153
PyModuleDef_Slot {
6254
slot: Py_mod_exec,
6355
value: sequential_exec as *mut c_void,

pyo3-ffi/examples/string-sum/src/lib.rs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#[cfg(Py_3_15)]
22
use std::ffi::c_void;
33
use std::ffi::{c_char, c_long};
4-
use std::ptr;
54

65
use pyo3_ffi::*;
76

@@ -36,29 +35,26 @@ PyABIInfo_VAR!(ABI_INFO);
3635

3736
const SLOTS_LEN: usize =
3837
1 + cfg!(Py_3_12) as usize + cfg!(Py_GIL_DISABLED) as usize + 4 * (cfg!(Py_3_15) as usize);
38+
#[cfg(Py_3_15)]
39+
static mut SLOTS: [PySlot; SLOTS_LEN] = [
40+
PySlot_STATIC_DATA(Py_mod_abi, (&raw mut ABI_INFO).cast()),
41+
// safety: Python does not write to these static fields
42+
PySlot_STATIC_DATA(Py_mod_name, c"string_sum".as_ptr() as *mut c_void),
43+
PySlot_STATIC_DATA(
44+
Py_mod_doc,
45+
c"A Python module written in Rust.".as_ptr() as *mut c_void,
46+
),
47+
PySlot_STATIC_DATA(Py_mod_methods, (&raw mut METHODS).cast()),
48+
PySlot_DATA(
49+
Py_mod_multiple_interpreters,
50+
Py_MOD_PER_INTERPRETER_GIL_SUPPORTED,
51+
),
52+
#[cfg(Py_GIL_DISABLED)]
53+
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED),
54+
PySlot_END(),
55+
];
56+
#[cfg(not(Py_3_15))]
3957
static mut SLOTS: [PyModuleDef_Slot; SLOTS_LEN] = [
40-
#[cfg(Py_3_15)]
41-
PyModuleDef_Slot {
42-
slot: Py_mod_abi,
43-
value: (&raw mut ABI_INFO).cast(),
44-
},
45-
#[cfg(Py_3_15)]
46-
PyModuleDef_Slot {
47-
slot: Py_mod_name,
48-
// safety: Python does not write to this field
49-
value: c"string_sum".as_ptr() as *mut c_void,
50-
},
51-
#[cfg(Py_3_15)]
52-
PyModuleDef_Slot {
53-
slot: Py_mod_doc,
54-
// safety: Python does not write to this field
55-
value: c"A Python module written in Rust.".as_ptr() as *mut c_void,
56-
},
57-
#[cfg(Py_3_15)]
58-
PyModuleDef_Slot {
59-
slot: Py_mod_methods,
60-
value: (&raw mut METHODS).cast(),
61-
},
6258
#[cfg(Py_3_12)]
6359
PyModuleDef_Slot {
6460
slot: Py_mod_multiple_interpreters,
@@ -71,7 +67,7 @@ static mut SLOTS: [PyModuleDef_Slot; SLOTS_LEN] = [
7167
},
7268
PyModuleDef_Slot {
7369
slot: 0,
74-
value: ptr::null_mut(),
70+
value: std::ptr::null_mut(),
7571
},
7672
];
7773

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,11 @@
1-
#[cfg(any(Py_3_14, Py_GIL_DISABLED))]
21
use crate::PyMutex;
3-
use crate::PyObject;
4-
5-
#[repr(C)]
6-
#[cfg(Py_GIL_DISABLED)]
7-
pub struct PyCriticalSection {
8-
_cs_prev: usize,
9-
_cs_mutex: *mut PyMutex,
10-
}
11-
12-
#[repr(C)]
13-
#[cfg(Py_GIL_DISABLED)]
14-
pub struct PyCriticalSection2 {
15-
_cs_base: PyCriticalSection,
16-
_cs_mutex2: *mut PyMutex,
17-
}
18-
19-
#[cfg(not(Py_GIL_DISABLED))]
20-
opaque_struct!(pub PyCriticalSection);
21-
22-
#[cfg(not(Py_GIL_DISABLED))]
23-
opaque_struct!(pub PyCriticalSection2);
2+
use crate::{PyCriticalSection, PyCriticalSection2};
243

254
extern_libpython! {
26-
pub fn PyCriticalSection_Begin(c: *mut PyCriticalSection, op: *mut PyObject);
27-
#[cfg(Py_3_14)]
285
pub fn PyCriticalSection_BeginMutex(c: *mut PyCriticalSection, m: *mut PyMutex);
29-
pub fn PyCriticalSection_End(c: *mut PyCriticalSection);
30-
pub fn PyCriticalSection2_Begin(c: *mut PyCriticalSection2, a: *mut PyObject, b: *mut PyObject);
31-
#[cfg(Py_3_14)]
326
pub fn PyCriticalSection2_BeginMutex(
337
c: *mut PyCriticalSection2,
348
m1: *mut PyMutex,
359
m2: *mut PyMutex,
3610
);
37-
pub fn PyCriticalSection2_End(c: *mut PyCriticalSection2);
3811
}

pyo3-ffi/src/cpython/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub(crate) mod ceval;
77
pub(crate) mod code;
88
pub(crate) mod compile;
99
pub(crate) mod complexobject;
10-
#[cfg(Py_3_13)]
10+
#[cfg(all(Py_3_14, Py_GIL_DISABLED))]
1111
pub(crate) mod critical_section;
1212
pub(crate) mod descrobject;
1313
pub(crate) mod dictobject;
@@ -56,8 +56,8 @@ pub use self::ceval::*;
5656
pub use self::code::*;
5757
pub use self::compile::*;
5858
pub use self::complexobject::*;
59-
#[cfg(Py_3_13)]
60-
pub use self::critical_section::*;
59+
#[cfg(all(Py_3_14, Py_GIL_DISABLED))]
60+
pub use self::critical_section::{PyCriticalSection2_BeginMutex, PyCriticalSection_BeginMutex};
6161
pub use self::descrobject::*;
6262
pub use self::dictobject::*;
6363
pub use self::floatobject::*;

pyo3-ffi/src/cpython/object.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::mem;
66
// skipped private _Py_NewReference
77
// skipped private _Py_NewReferenceNoTotal
88
// skipped private _Py_ResurrectReference
9+
// skipped private _Py_ForgetReference
910

1011
// skipped private _Py_GetGlobalRefTotal
1112
// skipped private _Py_GetRefTotal
@@ -277,6 +278,8 @@ pub struct PyTypeObject {
277278
pub tp_next: *mut PyTypeObject,
278279
#[cfg(Py_3_13)]
279280
pub tp_versions_used: u16,
281+
#[cfg(Py_3_15)]
282+
pub _tp_iteritem: Option<object::_Py_iteritemfunc>,
280283
}
281284

282285
#[cfg(Py_3_11)]

0 commit comments

Comments
 (0)