From 2b364d319059923f0d94cc705f35e77680c55ccb Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Fri, 22 Nov 2024 16:31:22 +0000 Subject: [PATCH] support 3.13t free-threaded python --- .github/workflows/ci.yml | 3 ++- CHANGELOG.md | 1 + src/datetime.rs | 12 ++++++------ src/strings.rs | 11 +++++------ 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4e801413..f6c84b891 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,6 +39,7 @@ jobs: "3.11", "3.12", "3.13", + "3.13t", "pypy-3.9", "pypy-3.10", ] @@ -108,7 +109,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: Quansight-Labs/setup-python@v5 with: python-version: ${{ matrix.python-version }} architecture: ${{ matrix.platform.python-architecture }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b748cf6f..65fd124a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - removed the `gil-refs` feature - reintroduced function names without `_bound` suffix + deprecating the old names - switched to `IntoPyObject` as trait bound + - Support Python 3.13t "free-threaded" Python. ([#471](https://github.com/PyO3/rust-numpy/pull/471) - v0.22.1 - Fix building on 32-bit Windows. ([#463](https://github.com/PyO3/rust-numpy/pull/463)) diff --git a/src/datetime.rs b/src/datetime.rs index 3eef346d8..b43a2e062 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -54,13 +54,13 @@ //! [scalars-datetime64]: https://numpy.org/doc/stable/reference/arrays.scalars.html#numpy.datetime64 //! [scalars-timedelta64]: https://numpy.org/doc/stable/reference/arrays.scalars.html#numpy.timedelta64 -use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; use std::hash::Hash; use std::marker::PhantomData; +use std::sync::Mutex; -use pyo3::{sync::GILProtected, Bound, Py, Python}; +use pyo3::{Bound, Py, Python}; use rustc_hash::FxHashMap; use crate::dtype::{clone_methods_impl, Element, PyArrayDescr, PyArrayDescrMethods}; @@ -209,8 +209,7 @@ impl fmt::Debug for Timedelta { struct TypeDescriptors { npy_type: NPY_TYPES, - #[allow(clippy::type_complexity)] - dtypes: GILProtected>>>>, + dtypes: Mutex>>>, } impl TypeDescriptors { @@ -218,13 +217,14 @@ impl TypeDescriptors { const unsafe fn new(npy_type: NPY_TYPES) -> Self { Self { npy_type, - dtypes: GILProtected::new(RefCell::new(None)), + dtypes: Mutex::new(None), } } #[allow(clippy::wrong_self_convention)] fn from_unit<'py>(&self, py: Python<'py>, unit: NPY_DATETIMEUNIT) -> Bound<'py, PyArrayDescr> { - let mut dtypes = self.dtypes.get(py).borrow_mut(); + // FIXME probably a deadlock risk here due to the GIL? Might need MutexExt trait in PyO3 + let mut dtypes = self.dtypes.lock().expect("dtype cache poisoned"); let dtype = match dtypes.get_or_insert_with(Default::default).entry(unit) { Entry::Occupied(entry) => entry.into_mut(), diff --git a/src/strings.rs b/src/strings.rs index 067327865..e2a05b95e 100644 --- a/src/strings.rs +++ b/src/strings.rs @@ -3,16 +3,15 @@ //! [ascii]: https://numpy.org/doc/stable/reference/c-api/dtype.html#c.NPY_STRING //! [ucs4]: https://numpy.org/doc/stable/reference/c-api/dtype.html#c.NPY_UNICODE -use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; use std::mem::size_of; use std::os::raw::c_char; use std::str; +use std::sync::Mutex; use pyo3::{ ffi::{Py_UCS1, Py_UCS4}, - sync::GILProtected, Bound, Py, Python, }; use rustc_hash::FxHashMap; @@ -160,14 +159,13 @@ unsafe impl Element for PyFixedUnicode { } struct TypeDescriptors { - #[allow(clippy::type_complexity)] - dtypes: GILProtected>>>>, + dtypes: Mutex>>>, } impl TypeDescriptors { const fn new() -> Self { Self { - dtypes: GILProtected::new(RefCell::new(None)), + dtypes: Mutex::new(None), } } @@ -180,7 +178,8 @@ impl TypeDescriptors { byteorder: c_char, size: usize, ) -> Bound<'py, PyArrayDescr> { - let mut dtypes = self.dtypes.get(py).borrow_mut(); + // FIXME probably a deadlock risk here due to the GIL? Might need MutexExt trait in PyO3 + let mut dtypes = self.dtypes.lock().expect("dtype cache poisoned"); let dtype = match dtypes.get_or_insert_with(Default::default).entry(size) { Entry::Occupied(entry) => entry.into_mut(),