Update MSRV to 1.63 (#4129)
* Bump MSRV to 1.63 * Drop parking_lot in favor of std::sync * Make portable-atomic dep conditional * Remove no longer required cfg
This commit is contained in:
parent
6fb972b232
commit
9e1960ea34
|
@ -54,7 +54,7 @@ jobs:
|
|||
name: Prepare LD_LIBRARY_PATH (Ubuntu only)
|
||||
run: echo LD_LIBRARY_PATH=${pythonLocation}/lib >> $GITHUB_ENV
|
||||
|
||||
- if: inputs.rust == '1.56.0'
|
||||
- if: inputs.rust == '1.63.0'
|
||||
name: Prepare minimal package versions (MSRV only)
|
||||
run: nox -s set-minimal-package-versions
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: 1.56.0
|
||||
toolchain: 1.63.0
|
||||
targets: x86_64-unknown-linux-gnu
|
||||
components: rust-src
|
||||
- uses: actions/setup-python@v5
|
||||
|
@ -255,7 +255,7 @@ jobs:
|
|||
]
|
||||
include:
|
||||
# Test minimal supported Rust version
|
||||
- rust: 1.56.0
|
||||
- rust: 1.63.0
|
||||
python-version: "3.12"
|
||||
platform:
|
||||
{
|
||||
|
|
|
@ -12,14 +12,12 @@ categories = ["api-bindings", "development-tools::ffi"]
|
|||
license = "MIT OR Apache-2.0"
|
||||
exclude = ["/.gitignore", ".cargo/config", "/codecov.yml", "/Makefile", "/pyproject.toml", "/noxfile.py", "/.github", "/tests/test_compile_error.rs", "/tests/ui"]
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.63"
|
||||
|
||||
[dependencies]
|
||||
cfg-if = "1.0"
|
||||
libc = "0.2.62"
|
||||
parking_lot = ">= 0.11, < 0.13"
|
||||
memoffset = "0.9"
|
||||
portable-atomic = "1.0"
|
||||
|
||||
# ffi bindings to the python interpreter, split into a separate crate so they can be used independently
|
||||
pyo3-ffi = { path = "pyo3-ffi", version = "=0.21.2" }
|
||||
|
@ -46,6 +44,9 @@ rust_decimal = { version = "1.0.0", default-features = false, optional = true }
|
|||
serde = { version = "1.0", optional = true }
|
||||
smallvec = { version = "1.0", optional = true }
|
||||
|
||||
[target.'cfg(not(target_has_atomic = "64"))'.dependencies]
|
||||
portable-atomic = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_approx_eq = "1.1.0"
|
||||
chrono = "0.4.25"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[![benchmark](https://img.shields.io/badge/benchmark-✓-Green?logo=github)](https://pyo3.rs/dev/bench/)
|
||||
[![codecov](https://img.shields.io/codecov/c/gh/PyO3/pyo3?logo=codecov)](https://codecov.io/gh/PyO3/pyo3)
|
||||
[![crates.io](https://img.shields.io/crates/v/pyo3?logo=rust)](https://crates.io/crates/pyo3)
|
||||
[![minimum rustc 1.56](https://img.shields.io/badge/rustc-1.56+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
|
||||
[![minimum rustc 1.63](https://img.shields.io/badge/rustc-1.63+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
|
||||
[![discord server](https://img.shields.io/discord/1209263839632424990?logo=discord)](https://discord.gg/33kcChzH7f)
|
||||
[![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green?logo=github)](https://github.com/PyO3/pyo3/blob/main/Contributing.md)
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
PyO3 supports the following software versions:
|
||||
- Python 3.7 and up (CPython, PyPy, and GraalPy)
|
||||
- Rust 1.56 and up
|
||||
- Rust 1.63 and up
|
||||
|
||||
You can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.
|
||||
|
||||
|
|
2
build.rs
2
build.rs
|
@ -39,7 +39,7 @@ fn configure_pyo3() -> Result<()> {
|
|||
println!("{}", cfg)
|
||||
}
|
||||
|
||||
// Emit cfgs like `thread_local_const_init`
|
||||
// Emit cfgs like `invalid_from_utf8_lint`
|
||||
print_feature_cfgs();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -151,7 +151,7 @@ rustflags = [
|
|||
]
|
||||
```
|
||||
|
||||
Alternatively, on rust >= 1.56, one can include in `build.rs`:
|
||||
Alternatively, one can include in `build.rs`:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
|
|
|
@ -6,7 +6,7 @@ To get started using PyO3 you will need three things: a Rust toolchain, a Python
|
|||
|
||||
## Rust
|
||||
|
||||
First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.56.
|
||||
First, make sure you have Rust installed on your system. If you haven't already done so, try following the instructions [here](https://www.rust-lang.org/tools/install). PyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best. The minimum required Rust version is 1.63.
|
||||
|
||||
If you can run `rustc --version` and the version is new enough you're good to go!
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Raised the MSRV to 1.63
|
21
noxfile.py
21
noxfile.py
|
@ -557,22 +557,11 @@ def set_minimal_package_versions(session: nox.Session):
|
|||
"examples/word-count",
|
||||
)
|
||||
min_pkg_versions = {
|
||||
"rust_decimal": "1.26.1",
|
||||
"csv": "1.1.6",
|
||||
"indexmap": "1.6.2",
|
||||
"hashbrown": "0.9.1",
|
||||
"log": "0.4.17",
|
||||
"once_cell": "1.17.2",
|
||||
"rayon": "1.6.1",
|
||||
"rayon-core": "1.10.2",
|
||||
"regex": "1.7.3",
|
||||
"proptest": "1.0.0",
|
||||
"chrono": "0.4.25",
|
||||
"byteorder": "1.4.3",
|
||||
"crossbeam-channel": "0.5.8",
|
||||
"crossbeam-deque": "0.8.3",
|
||||
"crossbeam-epoch": "0.9.15",
|
||||
"crossbeam-utils": "0.8.16",
|
||||
"regex": "1.9.6",
|
||||
"proptest": "1.2.0",
|
||||
"trybuild": "1.0.89",
|
||||
"eyre": "0.6.8",
|
||||
"allocator-api2": "0.2.10",
|
||||
}
|
||||
|
||||
# run cargo update first to ensure that everything is at highest
|
||||
|
|
|
@ -145,11 +145,6 @@ pub fn print_feature_cfgs() {
|
|||
|
||||
let rustc_minor_version = rustc_minor_version().unwrap_or(0);
|
||||
|
||||
// Enable use of const initializer for thread_local! on Rust 1.59 and greater
|
||||
if rustc_minor_version >= 59 {
|
||||
println!("cargo:rustc-cfg=thread_local_const_init");
|
||||
}
|
||||
|
||||
// invalid_from_utf8 lint was added in Rust 1.74
|
||||
if rustc_minor_version >= 74 {
|
||||
println!("cargo:rustc-cfg=invalid_from_utf8_lint");
|
||||
|
|
|
@ -14,7 +14,7 @@ Manual][capi] for up-to-date documentation.
|
|||
|
||||
PyO3 supports the following software versions:
|
||||
- Python 3.7 and up (CPython and PyPy)
|
||||
- Rust 1.56 and up
|
||||
- Rust 1.63 and up
|
||||
|
||||
# Example: Building Python Native modules
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ fn configure_pyo3() -> Result<()> {
|
|||
println!("{}", line);
|
||||
}
|
||||
|
||||
// Emit cfgs like `thread_local_const_init`
|
||||
// Emit cfgs like `invalid_from_utf8_lint`
|
||||
print_feature_cfgs();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
//!
|
||||
//! PyO3 supports the following software versions:
|
||||
//! - Python 3.7 and up (CPython and PyPy)
|
||||
//! - Rust 1.56 and up
|
||||
//! - Rust 1.63 and up
|
||||
//!
|
||||
//! # Example: Building Python Native modules
|
||||
//!
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use crate::{Py, PyAny, PyObject};
|
||||
use parking_lot::Mutex;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::task::{Context, Poll, Waker};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -25,12 +24,12 @@ impl CancelHandle {
|
|||
|
||||
/// Returns whether the associated coroutine has been cancelled.
|
||||
pub fn is_cancelled(&self) -> bool {
|
||||
self.0.lock().exception.is_some()
|
||||
self.0.lock().unwrap().exception.is_some()
|
||||
}
|
||||
|
||||
/// Poll to retrieve the exception thrown in the associated coroutine.
|
||||
pub fn poll_cancelled(&mut self, cx: &mut Context<'_>) -> Poll<PyObject> {
|
||||
let mut inner = self.0.lock();
|
||||
let mut inner = self.0.lock().unwrap();
|
||||
if let Some(exc) = inner.exception.take() {
|
||||
return Poll::Ready(exc);
|
||||
}
|
||||
|
@ -69,7 +68,7 @@ pub struct ThrowCallback(Arc<Mutex<Inner>>);
|
|||
|
||||
impl ThrowCallback {
|
||||
pub(super) fn throw(&self, exc: Py<PyAny>) {
|
||||
let mut inner = self.0.lock();
|
||||
let mut inner = self.0.lock().unwrap();
|
||||
inner.exception = Some(exc);
|
||||
if let Some(waker) = inner.waker.take() {
|
||||
waker.wake();
|
||||
|
|
67
src/gil.rs
67
src/gil.rs
|
@ -2,29 +2,16 @@
|
|||
|
||||
use crate::impl_::not_send::{NotSend, NOT_SEND};
|
||||
use crate::{ffi, Python};
|
||||
use parking_lot::{const_mutex, Mutex, Once};
|
||||
use std::cell::Cell;
|
||||
#[cfg(debug_assertions)]
|
||||
use std::cell::RefCell;
|
||||
#[cfg(not(debug_assertions))]
|
||||
use std::cell::UnsafeCell;
|
||||
use std::{mem, ptr::NonNull};
|
||||
use std::{mem, ptr::NonNull, sync};
|
||||
|
||||
static START: Once = Once::new();
|
||||
static START: sync::Once = sync::Once::new();
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(thread_local_const_init)] {
|
||||
use std::thread_local as thread_local_const_init;
|
||||
} else {
|
||||
macro_rules! thread_local_const_init {
|
||||
($($(#[$attr:meta])* static $name:ident: $ty:ty = const { $init:expr };)*) => (
|
||||
thread_local! { $($(#[$attr])* static $name: $ty = $init;)* }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thread_local_const_init! {
|
||||
std::thread_local! {
|
||||
/// This is an internal counter in pyo3 monitoring whether this thread has the GIL.
|
||||
///
|
||||
/// It will be incremented whenever a GILGuard or GILPool is created, and decremented whenever
|
||||
|
@ -249,26 +236,26 @@ type PyObjVec = Vec<NonNull<ffi::PyObject>>;
|
|||
/// Thread-safe storage for objects which were inc_ref / dec_ref while the GIL was not held.
|
||||
struct ReferencePool {
|
||||
// .0 is INCREFs, .1 is DECREFs
|
||||
pointer_ops: Mutex<(PyObjVec, PyObjVec)>,
|
||||
pointer_ops: sync::Mutex<(PyObjVec, PyObjVec)>,
|
||||
}
|
||||
|
||||
impl ReferencePool {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
pointer_ops: const_mutex((Vec::new(), Vec::new())),
|
||||
pointer_ops: sync::Mutex::new((Vec::new(), Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
fn register_incref(&self, obj: NonNull<ffi::PyObject>) {
|
||||
self.pointer_ops.lock().0.push(obj);
|
||||
self.pointer_ops.lock().unwrap().0.push(obj);
|
||||
}
|
||||
|
||||
fn register_decref(&self, obj: NonNull<ffi::PyObject>) {
|
||||
self.pointer_ops.lock().1.push(obj);
|
||||
self.pointer_ops.lock().unwrap().1.push(obj);
|
||||
}
|
||||
|
||||
fn update_counts(&self, _py: Python<'_>) {
|
||||
let mut ops = self.pointer_ops.lock();
|
||||
let mut ops = self.pointer_ops.lock().unwrap();
|
||||
if ops.0.is_empty() && ops.1.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
@ -523,9 +510,9 @@ mod tests {
|
|||
use super::{gil_is_acquired, GIL_COUNT, OWNED_OBJECTS, POOL};
|
||||
use crate::types::any::PyAnyMethods;
|
||||
use crate::{ffi, gil, PyObject, Python};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use parking_lot::{const_mutex, Condvar, Mutex};
|
||||
use std::ptr::NonNull;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use std::sync;
|
||||
|
||||
fn get_object(py: Python<'_>) -> PyObject {
|
||||
py.eval_bound("object()", None, None).unwrap().unbind()
|
||||
|
@ -543,6 +530,7 @@ mod tests {
|
|||
!POOL
|
||||
.pointer_ops
|
||||
.lock()
|
||||
.unwrap()
|
||||
.0
|
||||
.contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })
|
||||
}
|
||||
|
@ -551,6 +539,7 @@ mod tests {
|
|||
!POOL
|
||||
.pointer_ops
|
||||
.lock()
|
||||
.unwrap()
|
||||
.1
|
||||
.contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })
|
||||
}
|
||||
|
@ -559,6 +548,7 @@ mod tests {
|
|||
fn pool_dec_refs_contains(obj: &PyObject) -> bool {
|
||||
POOL.pointer_ops
|
||||
.lock()
|
||||
.unwrap()
|
||||
.1
|
||||
.contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })
|
||||
}
|
||||
|
@ -671,8 +661,8 @@ mod tests {
|
|||
Python::with_gil(|py| {
|
||||
assert_eq!(obj.get_refcnt(py), 1);
|
||||
let non_null = unsafe { NonNull::new_unchecked(obj.as_ptr()) };
|
||||
assert!(!POOL.pointer_ops.lock().0.contains(&non_null));
|
||||
assert!(!POOL.pointer_ops.lock().1.contains(&non_null));
|
||||
assert!(!POOL.pointer_ops.lock().unwrap().0.contains(&non_null));
|
||||
assert!(!POOL.pointer_ops.lock().unwrap().1.contains(&non_null));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -770,29 +760,30 @@ mod tests {
|
|||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
struct Event {
|
||||
set: Mutex<bool>,
|
||||
wait: Condvar,
|
||||
set: sync::Mutex<bool>,
|
||||
wait: sync::Condvar,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl Event {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
set: const_mutex(false),
|
||||
wait: Condvar::new(),
|
||||
set: sync::Mutex::new(false),
|
||||
wait: sync::Condvar::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&self) {
|
||||
*self.set.lock() = true;
|
||||
*self.set.lock().unwrap() = true;
|
||||
self.wait.notify_all();
|
||||
}
|
||||
|
||||
fn wait(&self) {
|
||||
let mut set = self.set.lock();
|
||||
while !*set {
|
||||
self.wait.wait(&mut set);
|
||||
}
|
||||
drop(
|
||||
self.wait
|
||||
.wait_while(self.set.lock().unwrap(), |s| !*s)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -891,16 +882,16 @@ mod tests {
|
|||
|
||||
// The pointer should appear once in the incref pool, and once in the
|
||||
// decref pool (for the clone being created and also dropped)
|
||||
assert!(POOL.pointer_ops.lock().0.contains(&ptr));
|
||||
assert!(POOL.pointer_ops.lock().1.contains(&ptr));
|
||||
assert!(POOL.pointer_ops.lock().unwrap().0.contains(&ptr));
|
||||
assert!(POOL.pointer_ops.lock().unwrap().1.contains(&ptr));
|
||||
|
||||
(obj, count, ptr)
|
||||
});
|
||||
|
||||
Python::with_gil(|py| {
|
||||
// Acquiring the gil clears the pool
|
||||
assert!(!POOL.pointer_ops.lock().0.contains(&ptr));
|
||||
assert!(!POOL.pointer_ops.lock().1.contains(&ptr));
|
||||
assert!(!POOL.pointer_ops.lock().unwrap().0.contains(&ptr));
|
||||
assert!(!POOL.pointer_ops.lock().unwrap().1.contains(&ptr));
|
||||
|
||||
// Overall count is still unchanged
|
||||
assert_eq!(count, obj.get_refcnt(py));
|
||||
|
|
|
@ -5,9 +5,17 @@ use std::{cell::UnsafeCell, marker::PhantomData};
|
|||
#[cfg(all(
|
||||
not(any(PyPy, GraalPy)),
|
||||
Py_3_9,
|
||||
not(all(windows, Py_LIMITED_API, not(Py_3_10)))
|
||||
not(all(windows, Py_LIMITED_API, not(Py_3_10))),
|
||||
not(target_has_atomic = "64"),
|
||||
))]
|
||||
use portable_atomic::{AtomicI64, Ordering};
|
||||
#[cfg(all(
|
||||
not(any(PyPy, GraalPy)),
|
||||
Py_3_9,
|
||||
not(all(windows, Py_LIMITED_API, not(Py_3_10))),
|
||||
target_has_atomic = "64",
|
||||
))]
|
||||
use std::sync::atomic::{AtomicI64, Ordering};
|
||||
|
||||
#[cfg(not(any(PyPy, GraalPy)))]
|
||||
use crate::exceptions::PyImportError;
|
||||
|
|
|
@ -132,7 +132,7 @@
|
|||
//!
|
||||
//! PyO3 supports the following software versions:
|
||||
//! - Python 3.7 and up (CPython and PyPy)
|
||||
//! - Rust 1.56 and up
|
||||
//! - Rust 1.63 and up
|
||||
//!
|
||||
//! # Example: Building a native Python module
|
||||
//!
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use std::{task::Poll, thread, time::Duration};
|
||||
|
||||
use futures::{channel::oneshot, future::poll_fn, FutureExt};
|
||||
#[cfg(not(target_has_atomic = "64"))]
|
||||
use portable_atomic::{AtomicBool, Ordering};
|
||||
use pyo3::{
|
||||
coroutine::CancelHandle,
|
||||
|
@ -10,6 +11,8 @@ use pyo3::{
|
|||
py_run,
|
||||
types::{IntoPyDict, PyType},
|
||||
};
|
||||
#[cfg(target_has_atomic = "64")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
#[path = "../src/tests/common.rs"]
|
||||
mod common;
|
||||
|
|
Loading…
Reference in New Issue