3209: Remove the conditional compilation flags which are made redundant  by the MSRV bump r=davidhewitt a=adamreichold



Co-authored-by: Adam Reichold <adam.reichold@t-online.de>
This commit is contained in:
bors[bot] 2023-06-05 14:09:05 +00:00 committed by GitHub
commit e1f028f3e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 255 additions and 451 deletions

View File

@ -44,7 +44,7 @@ jobs:
with: with:
toolchain: 1.56.0 toolchain: 1.56.0
targets: x86_64-unknown-linux-gnu targets: x86_64-unknown-linux-gnu
components: clippy,rust-src components: rust-src
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
with: with:
architecture: "x64" architecture: "x64"

View File

@ -48,9 +48,7 @@ chrono = { version = "0.4" }
criterion = "0.3.5" criterion = "0.3.5"
# Required for "and $N others" normalization # Required for "and $N others" normalization
trybuild = ">=1.0.70" trybuild = ">=1.0.70"
rustversion = "1.0" proptest = { version = "1.0", default-features = false, features = ["std"] }
# 1.0.0 requires Rust 1.50
proptest = { version = "0.10.1", default-features = false, features = ["std"] }
send_wrapper = "0.6" send_wrapper = "0.6"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.61" serde_json = "1.0.61"

View File

@ -46,7 +46,7 @@ fn configure_pyo3() -> Result<()> {
ensure_auto_initialize_ok(interpreter_config)?; ensure_auto_initialize_ok(interpreter_config)?;
// Emit cfgs like `addr_of` and `min_const_generics` // Emit cfgs like `thread_local_const_init`
print_feature_cfgs(); print_feature_cfgs();
Ok(()) Ok(())

View File

@ -435,6 +435,7 @@ def set_minimal_package_versions(session: nox.Session):
"rayon": "1.6.1", "rayon": "1.6.1",
"rayon-core": "1.10.2", "rayon-core": "1.10.2",
"regex": "1.7.3", "regex": "1.7.3",
"proptest": "1.0.0",
} }
# run cargo update first to ensure that everything is at highest # run cargo update first to ensure that everything is at highest

View File

@ -142,30 +142,10 @@ pub fn print_feature_cfgs() {
let rustc_minor_version = rustc_minor_version().unwrap_or(0); let rustc_minor_version = rustc_minor_version().unwrap_or(0);
// Enable use of const generics on Rust 1.51 and greater
if rustc_minor_version >= 51 {
println!("cargo:rustc-cfg=min_const_generics");
}
// Enable use of std::ptr::addr_of! on Rust 1.51 and greater
if rustc_minor_version >= 51 {
println!("cargo:rustc-cfg=addr_of");
}
// Enable use of Option::insert on Rust 1.53 and greater
if rustc_minor_version >= 53 {
println!("cargo:rustc-cfg=option_insert");
}
// Enable use of const initializer for thread_local! on Rust 1.59 and greater // Enable use of const initializer for thread_local! on Rust 1.59 and greater
if rustc_minor_version >= 59 { if rustc_minor_version >= 59 {
println!("cargo:rustc-cfg=thread_local_const_init"); println!("cargo:rustc-cfg=thread_local_const_init");
} }
// Enable use of `#[cfg(panic = "...")]` on Rust 1.60 and greater
if rustc_minor_version >= 60 {
println!("cargo:rustc-cfg=panic_unwind");
}
} }
/// Private exports used in PyO3's build.rs /// Private exports used in PyO3's build.rs

View File

@ -100,7 +100,7 @@ fn configure_pyo3() -> Result<()> {
println!("{}", line); println!("{}", line);
} }
// Emit cfgs like `addr_of` and `min_const_generics` // Emit cfgs like `thread_local_const_init`
print_feature_cfgs(); print_feature_cfgs();
Ok(()) Ok(())

View File

@ -1,6 +1,7 @@
use crate::longobject::PyLongObject; use crate::longobject::PyLongObject;
use crate::object::*; use crate::object::*;
use std::os::raw::{c_int, c_long}; use std::os::raw::{c_int, c_long};
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -10,7 +11,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyBool_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyBool_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyBool_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyBool_Type)) as c_int
} }
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
@ -23,12 +24,12 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn Py_False() -> *mut PyObject { pub unsafe fn Py_False() -> *mut PyObject {
addr_of_mut_shim!(_Py_FalseStruct) as *mut PyLongObject as *mut PyObject addr_of_mut!(_Py_FalseStruct) as *mut PyLongObject as *mut PyObject
} }
#[inline] #[inline]
pub unsafe fn Py_True() -> *mut PyObject { pub unsafe fn Py_True() -> *mut PyObject {
addr_of_mut_shim!(_Py_TrueStruct) as *mut PyLongObject as *mut PyObject addr_of_mut!(_Py_TrueStruct) as *mut PyLongObject as *mut PyObject
} }
#[inline] #[inline]

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::ptr::addr_of_mut;
#[cfg(not(any(PyPy, Py_LIMITED_API)))] #[cfg(not(any(PyPy, Py_LIMITED_API)))]
#[repr(C)] #[repr(C)]
@ -29,12 +30,12 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyByteArray_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyByteArray_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyByteArray_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyByteArray_Type))
} }
#[inline] #[inline]
pub unsafe fn PyByteArray_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyByteArray_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyByteArray_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyByteArray_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -16,7 +17,7 @@ pub unsafe fn PyBytes_Check(op: *mut PyObject) -> c_int {
#[inline] #[inline]
pub unsafe fn PyBytes_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyBytes_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyBytes_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyBytes_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -1,5 +1,6 @@
use crate::object::*; use crate::object::*;
use std::os::raw::{c_double, c_int}; use std::os::raw::{c_double, c_int};
use std::ptr::addr_of_mut;
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -40,12 +41,12 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyComplex_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyComplex_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyComplex_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyComplex_Type))
} }
#[inline] #[inline]
pub unsafe fn PyComplex_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyComplex_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyComplex_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyComplex_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -1,5 +1,6 @@
use crate::object::{PyObject, PyTypeObject, Py_TYPE}; use crate::object::{PyObject, PyTypeObject, Py_TYPE};
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::ptr::addr_of_mut;
extern "C" { extern "C" {
pub static mut PyContext_Type: PyTypeObject; pub static mut PyContext_Type: PyTypeObject;
@ -12,17 +13,17 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyContext_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyContext_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyContext_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyContext_Type)) as c_int
} }
#[inline] #[inline]
pub unsafe fn PyContextVar_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyContextVar_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyContextVar_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyContextVar_Type)) as c_int
} }
#[inline] #[inline]
pub unsafe fn PyContextToken_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyContextToken_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyContextToken_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyContextToken_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -3,6 +3,8 @@ use crate::pyport::Py_ssize_t;
#[allow(unused_imports)] #[allow(unused_imports)]
use std::os::raw::{c_char, c_int, c_uchar, c_void}; use std::os::raw::{c_char, c_int, c_uchar, c_void};
#[cfg(not(PyPy))]
use std::ptr::addr_of_mut;
// skipped _Py_CODEUNIT // skipped _Py_CODEUNIT
// skipped _Py_OPCODE // skipped _Py_OPCODE
@ -159,7 +161,7 @@ extern "C" {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyCode_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyCode_Type)) as c_int
} }
#[inline] #[inline]

View File

@ -4,6 +4,7 @@ use crate::pystate::PyThreadState;
#[cfg(not(any(PyPy, Py_3_11)))] #[cfg(not(any(PyPy, Py_3_11)))]
use std::os::raw::c_char; use std::os::raw::c_char;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
#[cfg(not(any(PyPy, Py_3_11)))] #[cfg(not(any(PyPy, Py_3_11)))]
pub type PyFrameState = c_char; pub type PyFrameState = c_char;
@ -64,7 +65,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyFrame_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyFrame_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -1,4 +1,6 @@
use std::os::raw::c_int; use std::os::raw::c_int;
#[cfg(not(all(PyPy, not(Py_3_8))))]
use std::ptr::addr_of_mut;
use crate::PyObject; use crate::PyObject;
@ -61,7 +63,7 @@ extern "C" {
#[cfg(not(all(PyPy, not(Py_3_8))))] #[cfg(not(all(PyPy, not(Py_3_8))))]
#[inline] #[inline]
pub unsafe fn PyFunction_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyFunction_Check(op: *mut PyObject) -> c_int {
(crate::Py_TYPE(op) == addr_of_mut_shim!(PyFunction_Type)) as c_int (crate::Py_TYPE(op) == addr_of_mut!(PyFunction_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -5,6 +5,7 @@ use crate::_PyErr_StackItem;
#[cfg(Py_3_11)] #[cfg(Py_3_11)]
use std::os::raw::c_char; use std::os::raw::c_char;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
#[repr(C)] #[repr(C)]
@ -41,12 +42,12 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyGen_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyGen_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyGen_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyGen_Type))
} }
#[inline] #[inline]
pub unsafe fn PyGen_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyGen_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyGen_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyGen_Type)) as c_int
} }
extern "C" { extern "C" {
@ -71,7 +72,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyCoro_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyCoro_CheckExact(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyCoro_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyCoro_Type))
} }
// skipped _PyCoro_GetAwaitableIter // skipped _PyCoro_GetAwaitableIter
@ -91,7 +92,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyAsyncGen_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyAsyncGen_CheckExact(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyAsyncGen_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyAsyncGen_Type))
} }
// skipped _PyAsyncGenValueWrapperNew // skipped _PyAsyncGenValueWrapperNew

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::{PyCFunctionObject, PyMethodDefPointer, METH_METHOD, METH_STATIC}; use crate::{PyCFunctionObject, PyMethodDefPointer, METH_METHOD, METH_STATIC};
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
pub struct PyCMethodObject { pub struct PyCMethodObject {
pub func: PyCFunctionObject, pub func: PyCFunctionObject,
@ -14,12 +15,12 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyCMethod_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyCMethod_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyCMethod_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyCMethod_Type)) as c_int
} }
#[inline] #[inline]
pub unsafe fn PyCMethod_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyCMethod_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyCMethod_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyCMethod_Type))
} }
#[inline] #[inline]

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -15,7 +16,7 @@ pub unsafe fn PyDict_Check(op: *mut PyObject) -> c_int {
#[inline] #[inline]
pub unsafe fn PyDict_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyDict_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyDict_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyDict_Type)) as c_int
} }
extern "C" { extern "C" {
@ -76,17 +77,17 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyDictKeys_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyDictKeys_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyDictKeys_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyDictKeys_Type)) as c_int
} }
#[inline] #[inline]
pub unsafe fn PyDictValues_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyDictValues_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyDictValues_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyDictValues_Type)) as c_int
} }
#[inline] #[inline]
pub unsafe fn PyDictItems_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyDictItems_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyDictItems_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyDictItems_Type)) as c_int
} }
#[inline] #[inline]

View File

@ -1,5 +1,6 @@
use crate::object::*; use crate::object::*;
use std::os::raw::{c_double, c_int}; use std::os::raw::{c_double, c_int};
use std::ptr::addr_of_mut;
#[cfg(Py_LIMITED_API)] #[cfg(Py_LIMITED_API)]
// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985) // TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985)
@ -20,12 +21,12 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyFloat_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyFloat_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyFloat_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyFloat_Type))
} }
#[inline] #[inline]
pub unsafe fn PyFloat_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyFloat_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyFloat_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyFloat_Type)) as c_int
} }
// skipped Py_RETURN_NAN // skipped Py_RETURN_NAN

View File

@ -1,5 +1,6 @@
use crate::object::*; use crate::object::*;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -9,7 +10,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PySeqIter_Check(op: *mut PyObject) -> c_int { pub unsafe fn PySeqIter_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PySeqIter_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PySeqIter_Type)) as c_int
} }
extern "C" { extern "C" {
@ -19,7 +20,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyCallIter_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyCallIter_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyCallIter_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyCallIter_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -258,19 +258,6 @@ macro_rules! opaque_struct {
}; };
} }
macro_rules! addr_of_mut_shim {
($place:expr) => {{
#[cfg(addr_of)]
{
::std::ptr::addr_of_mut!($place)
}
#[cfg(not(addr_of))]
{
&mut $place as *mut _
}
}};
}
pub use self::abstract_::*; pub use self::abstract_::*;
pub use self::bltinmodule::*; pub use self::bltinmodule::*;
pub use self::boolobject::*; pub use self::boolobject::*;

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -17,7 +18,7 @@ pub unsafe fn PyList_Check(op: *mut PyObject) -> c_int {
#[inline] #[inline]
pub unsafe fn PyList_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyList_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyList_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyList_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -4,6 +4,7 @@ use libc::size_t;
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
use std::os::raw::c_uchar; use std::os::raw::c_uchar;
use std::os::raw::{c_char, c_double, c_int, c_long, c_longlong, c_ulong, c_ulonglong, c_void}; use std::os::raw::{c_char, c_double, c_int, c_long, c_longlong, c_ulong, c_ulonglong, c_void};
use std::ptr::addr_of_mut;
opaque_struct!(PyLongObject); opaque_struct!(PyLongObject);
@ -20,7 +21,7 @@ pub unsafe fn PyLong_Check(op: *mut PyObject) -> c_int {
#[inline] #[inline]
pub unsafe fn PyLong_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyLong_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyLong_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyLong_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -13,7 +14,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyMemoryView_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyMemoryView_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyMemoryView_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyMemoryView_Type)) as c_int
} }
// skipped non-limited PyMemoryView_GET_BUFFER // skipped non-limited PyMemoryView_GET_BUFFER

View File

@ -24,19 +24,19 @@ extern "C" {
#[cfg(Py_3_9)] #[cfg(Py_3_9)]
#[inline] #[inline]
pub unsafe fn PyCFunction_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyCFunction_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyCFunction_Type)) as c_int (Py_TYPE(op) == ptr::addr_of_mut!(PyCFunction_Type)) as c_int
} }
#[cfg(Py_3_9)] #[cfg(Py_3_9)]
#[inline] #[inline]
pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyCFunction_Type)) PyObject_TypeCheck(op, ptr::addr_of_mut!(PyCFunction_Type))
} }
#[cfg(not(Py_3_9))] #[cfg(not(Py_3_9))]
#[inline] #[inline]
pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyCFunction_Type)) as c_int (Py_TYPE(op) == ptr::addr_of_mut!(PyCFunction_Type)) as c_int
} }
pub type PyCFunction = pub type PyCFunction =

View File

@ -2,6 +2,7 @@ use crate::methodobject::PyMethodDef;
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int, c_void}; use std::os::raw::{c_char, c_int, c_void};
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -11,12 +12,12 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyModule_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyModule_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(PyModule_Type)) PyObject_TypeCheck(op, addr_of_mut!(PyModule_Type))
} }
#[inline] #[inline]
pub unsafe fn PyModule_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyModule_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyModule_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyModule_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -488,7 +488,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn Py_None() -> *mut PyObject { pub unsafe fn Py_None() -> *mut PyObject {
addr_of_mut_shim!(_Py_NoneStruct) ptr::addr_of_mut!(_Py_NoneStruct)
} }
#[inline] #[inline]
@ -506,7 +506,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn Py_NotImplemented() -> *mut PyObject { pub unsafe fn Py_NotImplemented() -> *mut PyObject {
addr_of_mut_shim!(_Py_NotImplementedStruct) ptr::addr_of_mut!(_Py_NotImplementedStruct)
} }
// skipped Py_RETURN_NOTIMPLEMENTED // skipped Py_RETURN_NOTIMPLEMENTED
@ -554,5 +554,5 @@ pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {
#[inline] #[inline]
pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyType_Type)) as c_int (Py_TYPE(op) == ptr::addr_of_mut!(PyType_Type)) as c_int
} }

View File

@ -1,5 +1,6 @@
use crate::object::*; use crate::object::*;
use std::os::raw::{c_char, c_int, c_void}; use std::os::raw::{c_char, c_int, c_void};
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -11,7 +12,7 @@ pub type PyCapsule_Destructor = unsafe extern "C" fn(o: *mut PyObject);
#[inline] #[inline]
pub unsafe fn PyCapsule_CheckExact(ob: *mut PyObject) -> c_int { pub unsafe fn PyCapsule_CheckExact(ob: *mut PyObject) -> c_int {
(Py_TYPE(ob) == addr_of_mut_shim!(PyCapsule_Type)) as c_int (Py_TYPE(ob) == addr_of_mut!(PyCapsule_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -1,5 +1,6 @@
use crate::object::*; use crate::object::*;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -11,5 +12,5 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PyRange_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyRange_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyRange_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyRange_Type)) as c_int
} }

View File

@ -3,6 +3,7 @@ use crate::object::*;
use crate::pyport::Py_hash_t; use crate::pyport::Py_hash_t;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
pub const PySet_MINSIZE: usize = 8; pub const PySet_MINSIZE: usize = 8;
@ -93,7 +94,7 @@ extern "C" {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int { pub unsafe fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int {
(Py_TYPE(ob) == addr_of_mut_shim!(PyFrozenSet_Type)) as c_int (Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)) as c_int
} }
extern "C" { extern "C" {
@ -105,8 +106,8 @@ extern "C" {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int { pub unsafe fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int {
(Py_TYPE(ob) == addr_of_mut_shim!(PyFrozenSet_Type) (Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut_shim!(PyFrozenSet_Type)) != 0) as c_int || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int
} }
extern "C" { extern "C" {
@ -118,21 +119,21 @@ extern "C" {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int { pub unsafe fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int {
(Py_TYPE(ob) == addr_of_mut_shim!(PySet_Type) (Py_TYPE(ob) == addr_of_mut!(PySet_Type) || Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type))
|| Py_TYPE(ob) == addr_of_mut_shim!(PyFrozenSet_Type)) as c_int as c_int
} }
#[inline] #[inline]
pub unsafe fn PyAnySet_Check(ob: *mut PyObject) -> c_int { pub unsafe fn PyAnySet_Check(ob: *mut PyObject) -> c_int {
(PyAnySet_CheckExact(ob) != 0 (PyAnySet_CheckExact(ob) != 0
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut_shim!(PySet_Type)) != 0 || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PySet_Type)) != 0
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut_shim!(PyFrozenSet_Type)) != 0) as c_int || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int
} }
#[inline] #[inline]
#[cfg(Py_3_10)] #[cfg(Py_3_10)]
pub unsafe fn PySet_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PySet_CheckExact(op: *mut PyObject) -> c_int {
crate::Py_IS_TYPE(op, addr_of_mut_shim!(PySet_Type)) crate::Py_IS_TYPE(op, addr_of_mut!(PySet_Type))
} }
extern "C" { extern "C" {
@ -144,6 +145,6 @@ extern "C" {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PySet_Check(ob: *mut PyObject) -> c_int { pub unsafe fn PySet_Check(ob: *mut PyObject) -> c_int {
(Py_TYPE(ob) == addr_of_mut_shim!(PySet_Type) (Py_TYPE(ob) == addr_of_mut!(PySet_Type)
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut_shim!(PySet_Type)) != 0) as c_int || PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PySet_Type)) != 0) as c_int
} }

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -10,7 +11,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn Py_Ellipsis() -> *mut PyObject { pub unsafe fn Py_Ellipsis() -> *mut PyObject {
addr_of_mut_shim!(_Py_EllipsisObject) addr_of_mut!(_Py_EllipsisObject)
} }
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
@ -31,7 +32,7 @@ extern "C" {
#[inline] #[inline]
pub unsafe fn PySlice_Check(op: *mut PyObject) -> c_int { pub unsafe fn PySlice_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PySlice_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PySlice_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -1,5 +1,7 @@
use crate::object::*; use crate::object::*;
use std::os::raw::c_int; use std::os::raw::c_int;
#[cfg(not(PyPy))]
use std::ptr::addr_of_mut;
extern "C" { extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyTraceBack_Here")] #[cfg_attr(PyPy, link_name = "PyPyTraceBack_Here")]
@ -21,5 +23,5 @@ extern "C" {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyTraceBack_Check(op: *mut PyObject) -> c_int { pub unsafe fn PyTraceBack_Check(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyTraceBack_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyTraceBack_Type)) as c_int
} }

View File

@ -1,6 +1,7 @@
use crate::object::*; use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use std::os::raw::c_int; use std::os::raw::c_int;
use std::ptr::addr_of_mut;
#[cfg_attr(windows, link(name = "pythonXY"))] #[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" { extern "C" {
@ -16,7 +17,7 @@ pub unsafe fn PyTuple_Check(op: *mut PyObject) -> c_int {
#[inline] #[inline]
pub unsafe fn PyTuple_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyTuple_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyTuple_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyTuple_Type)) as c_int
} }
extern "C" { extern "C" {

View File

@ -2,6 +2,8 @@ use crate::object::*;
use crate::pyport::Py_ssize_t; use crate::pyport::Py_ssize_t;
use libc::wchar_t; use libc::wchar_t;
use std::os::raw::{c_char, c_int, c_void}; use std::os::raw::{c_char, c_int, c_void};
#[cfg(not(PyPy))]
use std::ptr::addr_of_mut;
#[cfg(not(Py_LIMITED_API))] #[cfg(not(Py_LIMITED_API))]
pub type Py_UNICODE = wchar_t; pub type Py_UNICODE = wchar_t;
@ -34,7 +36,7 @@ pub unsafe fn PyUnicode_Check(op: *mut PyObject) -> c_int {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int { pub unsafe fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(PyUnicode_Type)) as c_int (Py_TYPE(op) == addr_of_mut!(PyUnicode_Type)) as c_int
} }
pub const Py_UNICODE_REPLACEMENT_CHARACTER: Py_UCS4 = 0xFFFD; pub const Py_UNICODE_REPLACEMENT_CHARACTER: Py_UCS4 = 0xFFFD;

View File

@ -1,5 +1,7 @@
use crate::object::*; use crate::object::*;
use std::os::raw::c_int; use std::os::raw::c_int;
#[cfg(not(PyPy))]
use std::ptr::addr_of_mut;
#[cfg(all(not(PyPy), Py_LIMITED_API))] #[cfg(all(not(PyPy), Py_LIMITED_API))]
opaque_struct!(PyWeakReference); opaque_struct!(PyWeakReference);
@ -29,20 +31,20 @@ extern "C" {
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int { pub unsafe fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, addr_of_mut_shim!(_PyWeakref_RefType)) PyObject_TypeCheck(op, addr_of_mut!(_PyWeakref_RefType))
} }
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int { pub unsafe fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == addr_of_mut_shim!(_PyWeakref_RefType)) as c_int (Py_TYPE(op) == addr_of_mut!(_PyWeakref_RefType)) as c_int
} }
#[inline] #[inline]
#[cfg(not(PyPy))] #[cfg(not(PyPy))]
pub unsafe fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int { pub unsafe fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int {
((Py_TYPE(op) == addr_of_mut_shim!(_PyWeakref_ProxyType)) ((Py_TYPE(op) == addr_of_mut!(_PyWeakref_ProxyType))
|| (Py_TYPE(op) == addr_of_mut_shim!(_PyWeakref_CallableProxyType))) as c_int || (Py_TYPE(op) == addr_of_mut!(_PyWeakref_CallableProxyType))) as c_int
} }
#[inline] #[inline]

View File

@ -1,308 +1,118 @@
use crate::conversion::{AsPyPointer, IntoPyPointer};
use crate::types::PySequence;
use crate::{exceptions, PyErr}; use crate::{exceptions, PyErr};
use crate::{
ffi, FromPyObject, IntoPy, Py, PyAny, PyDowncastError, PyObject, PyResult, Python, ToPyObject,
};
#[cfg(min_const_generics)] impl<T, const N: usize> IntoPy<PyObject> for [T; N]
mod min_const_generics { where
use super::invalid_sequence_length; T: IntoPy<PyObject>,
use crate::conversion::{AsPyPointer, IntoPyPointer}; {
use crate::types::PySequence; fn into_py(self, py: Python<'_>) -> PyObject {
use crate::{
ffi, FromPyObject, IntoPy, Py, PyAny, PyDowncastError, PyObject, PyResult, Python,
ToPyObject,
};
impl<T, const N: usize> IntoPy<PyObject> for [T; N]
where
T: IntoPy<PyObject>,
{
fn into_py(self, py: Python<'_>) -> PyObject {
unsafe {
#[allow(deprecated)] // we're not on edition 2021 yet
let elements = std::array::IntoIter::new(self);
let len = N as ffi::Py_ssize_t;
let ptr = ffi::PyList_New(len);
// We create the `Py` pointer here for two reasons:
// - panics if the ptr is null
// - its Drop cleans up the list if user code panics.
let list: Py<PyAny> = Py::from_owned_ptr(py, ptr);
for (i, obj) in (0..len).zip(elements) {
let obj = obj.into_py(py).into_ptr();
#[cfg(not(Py_LIMITED_API))]
ffi::PyList_SET_ITEM(ptr, i, obj);
#[cfg(Py_LIMITED_API)]
ffi::PyList_SetItem(ptr, i, obj);
}
list
}
}
}
impl<T, const N: usize> ToPyObject for [T; N]
where
T: ToPyObject,
{
fn to_object(&self, py: Python<'_>) -> PyObject {
self.as_ref().to_object(py)
}
}
impl<'a, T, const N: usize> FromPyObject<'a> for [T; N]
where
T: FromPyObject<'a>,
{
fn extract(obj: &'a PyAny) -> PyResult<Self> {
create_array_from_obj(obj)
}
}
fn create_array_from_obj<'s, T, const N: usize>(obj: &'s PyAny) -> PyResult<[T; N]>
where
T: FromPyObject<'s>,
{
// Types that pass `PySequence_Check` usually implement enough of the sequence protocol
// to support this function and if not, we will only fail extraction safely.
let seq: &PySequence = unsafe {
if ffi::PySequence_Check(obj.as_ptr()) != 0 {
obj.downcast_unchecked()
} else {
return Err(PyDowncastError::new(obj, "Sequence").into());
}
};
let seq_len = seq.len()?;
if seq_len != N {
return Err(invalid_sequence_length(N, seq_len));
}
array_try_from_fn(|idx| seq.get_item(idx).and_then(PyAny::extract))
}
// TODO use std::array::try_from_fn, if that stabilises:
// (https://github.com/rust-lang/rust/pull/75644)
fn array_try_from_fn<E, F, T, const N: usize>(mut cb: F) -> Result<[T; N], E>
where
F: FnMut(usize) -> Result<T, E>,
{
// Helper to safely create arrays since the standard library doesn't
// provide one yet. Shouldn't be necessary in the future.
struct ArrayGuard<T, const N: usize> {
dst: *mut T,
initialized: usize,
}
impl<T, const N: usize> Drop for ArrayGuard<T, N> {
fn drop(&mut self) {
debug_assert!(self.initialized <= N);
let initialized_part =
core::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
unsafe {
core::ptr::drop_in_place(initialized_part);
}
}
}
// [MaybeUninit<T>; N] would be "nicer" but is actually difficult to create - there are nightly
// APIs which would make this easier.
let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
let mut guard: ArrayGuard<T, N> = ArrayGuard {
dst: array.as_mut_ptr() as _,
initialized: 0,
};
unsafe { unsafe {
let mut value_ptr = array.as_mut_ptr() as *mut T; #[allow(deprecated)] // we're not on edition 2021 yet
for i in 0..N { let elements = std::array::IntoIter::new(self);
core::ptr::write(value_ptr, cb(i)?); let len = N as ffi::Py_ssize_t;
value_ptr = value_ptr.offset(1);
guard.initialized += 1; let ptr = ffi::PyList_New(len);
// We create the `Py` pointer here for two reasons:
// - panics if the ptr is null
// - its Drop cleans up the list if user code panics.
let list: Py<PyAny> = Py::from_owned_ptr(py, ptr);
for (i, obj) in (0..len).zip(elements) {
let obj = obj.into_py(py).into_ptr();
#[cfg(not(Py_LIMITED_API))]
ffi::PyList_SET_ITEM(ptr, i, obj);
#[cfg(Py_LIMITED_API)]
ffi::PyList_SetItem(ptr, i, obj);
} }
core::mem::forget(guard);
Ok(array.assume_init())
}
}
#[cfg(test)] list
mod tests {
use super::*;
use std::{
panic,
sync::atomic::{AtomicUsize, Ordering},
};
#[test]
fn array_try_from_fn() {
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
struct CountDrop;
impl Drop for CountDrop {
fn drop(&mut self) {
DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
}
}
let _ = catch_unwind_silent(move || {
let _: Result<[CountDrop; 4], ()> = super::array_try_from_fn(|idx| {
#[allow(clippy::manual_assert)]
if idx == 2 {
panic!("peek a boo");
}
Ok(CountDrop)
});
});
assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2);
}
#[test]
fn test_extract_bytearray_to_array() {
Python::with_gil(|py| {
let v: [u8; 33] = py
.eval(
"bytearray(b'abcabcabcabcabcabcabcabcabcabcabc')",
None,
None,
)
.unwrap()
.extract()
.unwrap();
assert!(&v == b"abcabcabcabcabcabcabcabcabcabcabc");
})
}
// https://stackoverflow.com/a/59211505
fn catch_unwind_silent<F, R>(f: F) -> std::thread::Result<R>
where
F: FnOnce() -> R + panic::UnwindSafe,
{
let prev_hook = panic::take_hook();
panic::set_hook(Box::new(|_| {}));
let result = panic::catch_unwind(f);
panic::set_hook(prev_hook);
result
} }
} }
} }
#[cfg(not(min_const_generics))] impl<T, const N: usize> ToPyObject for [T; N]
mod array_impls { where
use super::invalid_sequence_length; T: ToPyObject,
use crate::conversion::{AsPyPointer, IntoPyPointer}; {
use crate::types::PySequence; fn to_object(&self, py: Python<'_>) -> PyObject {
use crate::{ self.as_ref().to_object(py)
ffi, FromPyObject, IntoPy, Py, PyAny, PyDowncastError, PyObject, PyResult, Python, }
ToPyObject, }
impl<'a, T, const N: usize> FromPyObject<'a> for [T; N]
where
T: FromPyObject<'a>,
{
fn extract(obj: &'a PyAny) -> PyResult<Self> {
create_array_from_obj(obj)
}
}
fn create_array_from_obj<'s, T, const N: usize>(obj: &'s PyAny) -> PyResult<[T; N]>
where
T: FromPyObject<'s>,
{
// Types that pass `PySequence_Check` usually implement enough of the sequence protocol
// to support this function and if not, we will only fail extraction safely.
let seq: &PySequence = unsafe {
if ffi::PySequence_Check(obj.as_ptr()) != 0 {
obj.downcast_unchecked()
} else {
return Err(PyDowncastError::new(obj, "Sequence").into());
}
}; };
use std::mem::{transmute_copy, ManuallyDrop}; let seq_len = seq.len()?;
if seq_len != N {
return Err(invalid_sequence_length(N, seq_len));
}
array_try_from_fn(|idx| seq.get_item(idx).and_then(PyAny::extract))
}
macro_rules! array_impls { // TODO use std::array::try_from_fn, if that stabilises:
($($N:expr),+) => { // (https://github.com/rust-lang/rust/pull/75644)
$( fn array_try_from_fn<E, F, T, const N: usize>(mut cb: F) -> Result<[T; N], E>
impl<T> IntoPy<PyObject> for [T; $N] where
where F: FnMut(usize) -> Result<T, E>,
T: IntoPy<PyObject> {
{ // Helper to safely create arrays since the standard library doesn't
fn into_py(self, py: Python<'_>) -> PyObject { // provide one yet. Shouldn't be necessary in the future.
struct ArrayGuard<T, const N: usize> {
dst: *mut T,
initialized: usize,
}
struct ArrayGuard<T> { impl<T, const N: usize> Drop for ArrayGuard<T, N> {
elements: [ManuallyDrop<T>; $N], fn drop(&mut self) {
start: usize, debug_assert!(self.initialized <= N);
} let initialized_part = core::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
unsafe {
impl<T> Drop for ArrayGuard<T> { core::ptr::drop_in_place(initialized_part);
fn drop(&mut self) { }
unsafe {
let needs_drop = self.elements.get_mut(self.start..).unwrap();
for item in needs_drop {
ManuallyDrop::drop(item);
}
}
}
}
unsafe {
let ptr = ffi::PyList_New($N as ffi::Py_ssize_t);
// We create the `Py` pointer here for two reasons:
// - panics if the ptr is null
// - its Drop cleans up the list if user code panics.
let list: Py<PyAny> = Py::from_owned_ptr(py, ptr);
let slf = ManuallyDrop::new(self);
let mut guard = ArrayGuard {
// the transmute size check is _very_ dumb around generics
elements: transmute_copy(&slf),
start: 0
};
for i in 0..$N {
let obj: T = ManuallyDrop::take(&mut guard.elements[i]);
guard.start += 1;
let obj = obj.into_py(py).into_ptr();
#[cfg(not(Py_LIMITED_API))]
ffi::PyList_SET_ITEM(ptr, i as ffi::Py_ssize_t, obj);
#[cfg(Py_LIMITED_API)]
ffi::PyList_SetItem(ptr, i as ffi::Py_ssize_t, obj);
}
std::mem::forget(guard);
list
}
}
}
impl<T> ToPyObject for [T; $N]
where
T: ToPyObject,
{
fn to_object(&self, py: Python<'_>) -> PyObject {
self.as_ref().to_object(py)
}
}
impl<'a, T> FromPyObject<'a> for [T; $N]
where
T: Copy + Default + FromPyObject<'a>,
{
fn extract(obj: &'a PyAny) -> PyResult<Self> {
let mut array = [T::default(); $N];
extract_sequence_into_slice(obj, &mut array)?;
Ok(array)
}
}
)+
} }
} }
#[cfg(not(min_const_generics))] // [MaybeUninit<T>; N] would be "nicer" but is actually difficult to create - there are nightly
array_impls!( // APIs which would make this easier.
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
25, 26, 27, 28, 29, 30, 31, 32 let mut guard: ArrayGuard<T, N> = ArrayGuard {
); dst: array.as_mut_ptr() as _,
initialized: 0,
#[cfg(not(min_const_generics))] };
fn extract_sequence_into_slice<'s, T>(obj: &'s PyAny, slice: &mut [T]) -> PyResult<()> unsafe {
where let mut value_ptr = array.as_mut_ptr() as *mut T;
T: FromPyObject<'s>, for i in 0..N {
{ core::ptr::write(value_ptr, cb(i)?);
// Types that pass `PySequence_Check` usually implement enough of the sequence protocol value_ptr = value_ptr.offset(1);
// to support this function and if not, we will only fail extraction safely. guard.initialized += 1;
let seq: &PySequence = unsafe {
if ffi::PySequence_Check(obj.as_ptr()) != 0 {
obj.downcast_unchecked()
} else {
return Err(PyDowncastError::new(obj, "Sequence").into());
}
};
let seq_len = seq.len()?;
if seq_len != slice.len() {
return Err(invalid_sequence_length(slice.len(), seq_len));
} }
for (value, item) in slice.iter_mut().zip(seq.iter()?) { core::mem::forget(guard);
*value = item?.extract::<T>()?; Ok(array.assume_init())
}
Ok(())
} }
} }
@ -315,8 +125,50 @@ fn invalid_sequence_length(expected: usize, actual: usize) -> PyErr {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::{
panic,
sync::atomic::{AtomicUsize, Ordering},
};
use crate::{types::PyList, IntoPy, PyResult, Python, ToPyObject}; use crate::{types::PyList, IntoPy, PyResult, Python, ToPyObject};
#[test]
fn array_try_from_fn() {
static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);
struct CountDrop;
impl Drop for CountDrop {
fn drop(&mut self) {
DROP_COUNTER.fetch_add(1, Ordering::SeqCst);
}
}
let _ = catch_unwind_silent(move || {
let _: Result<[CountDrop; 4], ()> = super::array_try_from_fn(|idx| {
#[allow(clippy::manual_assert)]
if idx == 2 {
panic!("peek a boo");
}
Ok(CountDrop)
});
});
assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2);
}
#[test]
fn test_extract_bytearray_to_array() {
Python::with_gil(|py| {
let v: [u8; 33] = py
.eval(
"bytearray(b'abcabcabcabcabcabcabcabcabcabcabc')",
None,
None,
)
.unwrap()
.extract()
.unwrap();
assert!(&v == b"abcabcabcabcabcabcabcabcabcabcabc");
})
}
#[test] #[test]
fn test_extract_small_bytearray_to_array() { fn test_extract_small_bytearray_to_array() {
Python::with_gil(|py| { Python::with_gil(|py| {
@ -390,4 +242,16 @@ mod tests {
let _cell: &crate::PyCell<Foo> = list.get_item(4).unwrap().extract().unwrap(); let _cell: &crate::PyCell<Foo> = list.get_item(4).unwrap().extract().unwrap();
}); });
} }
// https://stackoverflow.com/a/59211505
fn catch_unwind_silent<F, R>(f: F) -> std::thread::Result<R>
where
F: FnOnce() -> R + panic::UnwindSafe,
{
let prev_hook = panic::take_hook();
panic::set_hook(Box::new(|_| {}));
let result = panic::catch_unwind(f);
panic::set_hook(prev_hook);
result
}
} }

View File

@ -50,13 +50,6 @@ pub fn extract_pyclass_ref<'a, 'py: 'a, T: PyClass>(
obj: &'py PyAny, obj: &'py PyAny,
holder: &'a mut Option<PyRef<'py, T>>, holder: &'a mut Option<PyRef<'py, T>>,
) -> PyResult<&'a T> { ) -> PyResult<&'a T> {
#[cfg(not(option_insert))]
{
*holder = Some(obj.extract()?);
return Ok(holder.as_deref().unwrap());
}
#[cfg(option_insert)]
Ok(&*holder.insert(obj.extract()?)) Ok(&*holder.insert(obj.extract()?))
} }
@ -65,13 +58,6 @@ pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass<Frozen = False>>(
obj: &'py PyAny, obj: &'py PyAny,
holder: &'a mut Option<PyRefMut<'py, T>>, holder: &'a mut Option<PyRefMut<'py, T>>,
) -> PyResult<&'a mut T> { ) -> PyResult<&'a mut T> {
#[cfg(not(option_insert))]
{
*holder = Some(obj.extract()?);
return Ok(holder.as_deref_mut().unwrap());
}
#[cfg(option_insert)]
Ok(&mut *holder.insert(obj.extract()?)) Ok(&mut *holder.insert(obj.extract()?))
} }

View File

@ -96,7 +96,6 @@ fn recursive_class_attributes() {
} }
#[test] #[test]
#[cfg_attr(cfg_panic, cfg(panic = "unwind"))]
fn test_fallible_class_attribute() { fn test_fallible_class_attribute() {
use pyo3::{exceptions::PyValueError, types::PyString}; use pyo3::{exceptions::PyValueError, types::PyString};

View File

@ -1,8 +1,10 @@
#![cfg(feature = "macros")]
use pyo3::prelude::*; use pyo3::prelude::*;
use pyo3::types::IntoPyDict; use pyo3::types::IntoPyDict;
#[macro_use] #[macro_use]
#[path = "../common.rs"] #[path = "common.rs"]
mod common; mod common;
#[pyclass] #[pyclass]

View File

@ -1,11 +0,0 @@
#![cfg(feature = "macros")]
//! Functionality which is not only not supported on MSRV,
//! but can't even be cfg-ed out on MSRV because the compiler doesn't support
//! the syntax.
#[rustversion::since(1.54)]
mod requires_1_54 {
include!("not_msrv/requires_1_54.rs");
}

View File

@ -11,6 +11,5 @@ name = "xtask"
anyhow = "1.0.51" anyhow = "1.0.51"
# Clap 3 requires MSRV 1.54 # Clap 3 requires MSRV 1.54
rustversion = "1.0"
structopt = { version = "0.3", default-features = false } structopt = { version = "0.3", default-features = false }
clap = { version = "2" } clap = { version = "2" }

View File

@ -107,7 +107,7 @@ impl Subcommand {
/// Run a command as a child process, inheriting stdin, stdout and stderr. /// Run a command as a child process, inheriting stdin, stdout and stderr.
pub fn run(command: &mut Command) -> Result<()> { pub fn run(command: &mut Command) -> Result<()> {
let command_str = format_command(command); let command_str = format!("{:?}", command);
let github_actions = std::env::var_os("GITHUB_ACTIONS").is_some(); let github_actions = std::env::var_os("GITHUB_ACTIONS").is_some();
if github_actions { if github_actions {
println!("::group::Running: {}", command_str); println!("::group::Running: {}", command_str);
@ -135,7 +135,7 @@ pub fn run(command: &mut Command) -> Result<()> {
/// Like `run`, but does not inherit stdin, stdout and stderr. /// Like `run`, but does not inherit stdin, stdout and stderr.
pub fn run_with_output(command: &mut Command) -> Result<Output> { pub fn run_with_output(command: &mut Command) -> Result<Output> {
let command_str = format_command(command); let command_str = format!("{:?}", command);
println!("Running: {}", command_str); println!("Running: {}", command_str);

View File

@ -1,47 +1,16 @@
use anyhow::ensure; use anyhow::ensure;
use std::process::Command; use std::process::Command;
// Replacement for str.split_once() on Rust older than 1.52
#[rustversion::before(1.52)]
pub fn split_once(s: &str, pat: char) -> Option<(&str, &str)> {
let mut iter = s.splitn(2, pat);
Some((iter.next()?, iter.next()?))
}
#[rustversion::since(1.52)]
pub fn split_once(s: &str, pat: char) -> Option<(&str, &str)> {
s.split_once(pat)
}
#[rustversion::since(1.57)]
pub fn format_command(command: &Command) -> String {
let mut buf = String::new();
buf.push('`');
buf.push_str(&command.get_program().to_string_lossy());
for arg in command.get_args() {
buf.push(' ');
buf.push_str(&arg.to_string_lossy());
}
buf.push('`');
buf
}
#[rustversion::before(1.57)]
pub fn format_command(command: &Command) -> String {
// Debug impl isn't as nice as the above, but will do on < 1.57
format!("{:?}", command)
}
pub fn get_output(command: &mut Command) -> anyhow::Result<std::process::Output> { pub fn get_output(command: &mut Command) -> anyhow::Result<std::process::Output> {
let output = command.output()?; let output = command.output()?;
ensure! { ensure! {
output.status.success(), output.status.success(),
"process did not run successfully ({exit}): {command}", "process did not run successfully ({exit}): {command:?}",
exit = match output.status.code() { exit = match output.status.code() {
Some(code) => format!("exit code {}", code), Some(code) => format!("exit code {}", code),
None => "terminated by signal".into(), None => "terminated by signal".into(),
}, },
command = format_command(command), command = command,
}; };
Ok(output) Ok(output)
} }