Merge #3209
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:
commit
e1f028f3e5
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
@ -44,7 +44,7 @@ jobs:
|
|||
with:
|
||||
toolchain: 1.56.0
|
||||
targets: x86_64-unknown-linux-gnu
|
||||
components: clippy,rust-src
|
||||
components: rust-src
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
architecture: "x64"
|
||||
|
|
|
@ -48,9 +48,7 @@ chrono = { version = "0.4" }
|
|||
criterion = "0.3.5"
|
||||
# Required for "and $N others" normalization
|
||||
trybuild = ">=1.0.70"
|
||||
rustversion = "1.0"
|
||||
# 1.0.0 requires Rust 1.50
|
||||
proptest = { version = "0.10.1", default-features = false, features = ["std"] }
|
||||
proptest = { version = "1.0", default-features = false, features = ["std"] }
|
||||
send_wrapper = "0.6"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.61"
|
||||
|
|
2
build.rs
2
build.rs
|
@ -46,7 +46,7 @@ fn configure_pyo3() -> Result<()> {
|
|||
|
||||
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();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -435,6 +435,7 @@ def set_minimal_package_versions(session: nox.Session):
|
|||
"rayon": "1.6.1",
|
||||
"rayon-core": "1.10.2",
|
||||
"regex": "1.7.3",
|
||||
"proptest": "1.0.0",
|
||||
}
|
||||
|
||||
# run cargo update first to ensure that everything is at highest
|
||||
|
|
|
@ -142,30 +142,10 @@ pub fn print_feature_cfgs() {
|
|||
|
||||
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
|
||||
if rustc_minor_version >= 59 {
|
||||
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
|
||||
|
|
|
@ -100,7 +100,7 @@ fn configure_pyo3() -> Result<()> {
|
|||
println!("{}", line);
|
||||
}
|
||||
|
||||
// Emit cfgs like `addr_of` and `min_const_generics`
|
||||
// Emit cfgs like `thread_local_const_init`
|
||||
print_feature_cfgs();
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::longobject::PyLongObject;
|
||||
use crate::object::*;
|
||||
use std::os::raw::{c_int, c_long};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -10,7 +11,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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"))]
|
||||
|
@ -23,12 +24,12 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg(not(any(PyPy, Py_LIMITED_API)))]
|
||||
#[repr(C)]
|
||||
|
@ -29,12 +30,12 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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" {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -16,7 +17,7 @@ pub unsafe fn PyBytes_Check(op: *mut PyObject) -> c_int {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::object::*;
|
||||
use std::os::raw::{c_double, c_int};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -40,12 +41,12 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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" {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::object::{PyObject, PyTypeObject, Py_TYPE};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
extern "C" {
|
||||
pub static mut PyContext_Type: PyTypeObject;
|
||||
|
@ -12,17 +13,17 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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]
|
||||
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" {
|
||||
|
|
|
@ -3,6 +3,8 @@ use crate::pyport::Py_ssize_t;
|
|||
|
||||
#[allow(unused_imports)]
|
||||
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_OPCODE
|
||||
|
@ -159,7 +161,7 @@ extern "C" {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
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]
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::pystate::PyThreadState;
|
|||
#[cfg(not(any(PyPy, Py_3_11)))]
|
||||
use std::os::raw::c_char;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg(not(any(PyPy, Py_3_11)))]
|
||||
pub type PyFrameState = c_char;
|
||||
|
@ -64,7 +65,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use std::os::raw::c_int;
|
||||
#[cfg(not(all(PyPy, not(Py_3_8))))]
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
use crate::PyObject;
|
||||
|
||||
|
@ -61,7 +63,7 @@ extern "C" {
|
|||
#[cfg(not(all(PyPy, not(Py_3_8))))]
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::_PyErr_StackItem;
|
|||
#[cfg(Py_3_11)]
|
||||
use std::os::raw::c_char;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg(not(PyPy))]
|
||||
#[repr(C)]
|
||||
|
@ -41,12 +42,12 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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" {
|
||||
|
@ -71,7 +72,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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
|
||||
|
@ -91,7 +92,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::{PyCFunctionObject, PyMethodDefPointer, METH_METHOD, METH_STATIC};
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
pub struct PyCMethodObject {
|
||||
pub func: PyCFunctionObject,
|
||||
|
@ -14,12 +15,12 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -15,7 +16,7 @@ pub unsafe fn PyDict_Check(op: *mut PyObject) -> c_int {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
@ -76,17 +77,17 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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]
|
||||
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]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::object::*;
|
||||
use std::os::raw::{c_double, c_int};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg(Py_LIMITED_API)]
|
||||
// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985)
|
||||
|
@ -20,12 +21,12 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::object::*;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -9,7 +10,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
@ -19,7 +20,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -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::bltinmodule::*;
|
||||
pub use self::boolobject::*;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -17,7 +18,7 @@ pub unsafe fn PyList_Check(op: *mut PyObject) -> c_int {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -4,6 +4,7 @@ use libc::size_t;
|
|||
#[cfg(not(Py_LIMITED_API))]
|
||||
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::ptr::addr_of_mut;
|
||||
|
||||
opaque_struct!(PyLongObject);
|
||||
|
||||
|
@ -20,7 +21,7 @@ pub unsafe fn PyLong_Check(op: *mut PyObject) -> c_int {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -13,7 +14,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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
|
||||
|
|
|
@ -24,19 +24,19 @@ extern "C" {
|
|||
#[cfg(Py_3_9)]
|
||||
#[inline]
|
||||
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)]
|
||||
#[inline]
|
||||
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))]
|
||||
#[inline]
|
||||
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 =
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::methodobject::PyMethodDef;
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -11,12 +12,12 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
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" {
|
||||
|
|
|
@ -488,7 +488,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
pub unsafe fn Py_None() -> *mut PyObject {
|
||||
addr_of_mut_shim!(_Py_NoneStruct)
|
||||
ptr::addr_of_mut!(_Py_NoneStruct)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -506,7 +506,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
pub unsafe fn Py_NotImplemented() -> *mut PyObject {
|
||||
addr_of_mut_shim!(_Py_NotImplementedStruct)
|
||||
ptr::addr_of_mut!(_Py_NotImplementedStruct)
|
||||
}
|
||||
|
||||
// skipped Py_RETURN_NOTIMPLEMENTED
|
||||
|
@ -554,5 +554,5 @@ pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {
|
|||
|
||||
#[inline]
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::object::*;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -11,7 +12,7 @@ pub type PyCapsule_Destructor = unsafe extern "C" fn(o: *mut PyObject);
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::object::*;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -11,5 +12,5 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use crate::object::*;
|
|||
use crate::pyport::Py_hash_t;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
pub const PySet_MINSIZE: usize = 8;
|
||||
|
||||
|
@ -93,7 +94,7 @@ extern "C" {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
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" {
|
||||
|
@ -105,8 +106,8 @@ extern "C" {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
pub unsafe fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(ob) == addr_of_mut_shim!(PyFrozenSet_Type)
|
||||
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut_shim!(PyFrozenSet_Type)) != 0) as c_int
|
||||
(Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type)
|
||||
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
@ -118,21 +119,21 @@ extern "C" {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
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_shim!(PyFrozenSet_Type)) as c_int
|
||||
(Py_TYPE(ob) == addr_of_mut!(PySet_Type) || Py_TYPE(ob) == addr_of_mut!(PyFrozenSet_Type))
|
||||
as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyAnySet_Check(ob: *mut PyObject) -> c_int {
|
||||
(PyAnySet_CheckExact(ob) != 0
|
||||
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut_shim!(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!(PySet_Type)) != 0
|
||||
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PyFrozenSet_Type)) != 0) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(Py_3_10)]
|
||||
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" {
|
||||
|
@ -144,6 +145,6 @@ extern "C" {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
pub unsafe fn PySet_Check(ob: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(ob) == addr_of_mut_shim!(PySet_Type)
|
||||
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut_shim!(PySet_Type)) != 0) as c_int
|
||||
(Py_TYPE(ob) == addr_of_mut!(PySet_Type)
|
||||
|| PyType_IsSubtype(Py_TYPE(ob), addr_of_mut!(PySet_Type)) != 0) as c_int
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -10,7 +11,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
pub unsafe fn Py_Ellipsis() -> *mut PyObject {
|
||||
addr_of_mut_shim!(_Py_EllipsisObject)
|
||||
addr_of_mut!(_Py_EllipsisObject)
|
||||
}
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
|
@ -31,7 +32,7 @@ extern "C" {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::object::*;
|
||||
use std::os::raw::c_int;
|
||||
#[cfg(not(PyPy))]
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
extern "C" {
|
||||
#[cfg_attr(PyPy, link_name = "PyPyTraceBack_Here")]
|
||||
|
@ -21,5 +23,5 @@ extern "C" {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::object::*;
|
||||
use crate::pyport::Py_ssize_t;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
|
@ -16,7 +17,7 @@ pub unsafe fn PyTuple_Check(op: *mut PyObject) -> c_int {
|
|||
|
||||
#[inline]
|
||||
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" {
|
||||
|
|
|
@ -2,6 +2,8 @@ use crate::object::*;
|
|||
use crate::pyport::Py_ssize_t;
|
||||
use libc::wchar_t;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
#[cfg(not(PyPy))]
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub type Py_UNICODE = wchar_t;
|
||||
|
@ -34,7 +36,7 @@ pub unsafe fn PyUnicode_Check(op: *mut PyObject) -> c_int {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
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;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use crate::object::*;
|
||||
use std::os::raw::c_int;
|
||||
#[cfg(not(PyPy))]
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
#[cfg(all(not(PyPy), Py_LIMITED_API))]
|
||||
opaque_struct!(PyWeakReference);
|
||||
|
@ -29,20 +31,20 @@ extern "C" {
|
|||
#[inline]
|
||||
#[cfg(not(PyPy))]
|
||||
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]
|
||||
#[cfg(not(PyPy))]
|
||||
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]
|
||||
#[cfg(not(PyPy))]
|
||||
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_shim!(_PyWeakref_CallableProxyType))) as c_int
|
||||
((Py_TYPE(op) == addr_of_mut!(_PyWeakref_ProxyType))
|
||||
|| (Py_TYPE(op) == addr_of_mut!(_PyWeakref_CallableProxyType))) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -1,308 +1,118 @@
|
|||
use crate::conversion::{AsPyPointer, IntoPyPointer};
|
||||
use crate::types::PySequence;
|
||||
use crate::{exceptions, PyErr};
|
||||
use crate::{
|
||||
ffi, FromPyObject, IntoPy, Py, PyAny, PyDowncastError, PyObject, PyResult, Python, ToPyObject,
|
||||
};
|
||||
|
||||
#[cfg(min_const_generics)]
|
||||
mod min_const_generics {
|
||||
use super::invalid_sequence_length;
|
||||
use crate::conversion::{AsPyPointer, IntoPyPointer};
|
||||
use crate::types::PySequence;
|
||||
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,
|
||||
};
|
||||
impl<T, const N: usize> IntoPy<PyObject> for [T; N]
|
||||
where
|
||||
T: IntoPy<PyObject>,
|
||||
{
|
||||
fn into_py(self, py: Python<'_>) -> PyObject {
|
||||
unsafe {
|
||||
let mut value_ptr = array.as_mut_ptr() as *mut T;
|
||||
for i in 0..N {
|
||||
core::ptr::write(value_ptr, cb(i)?);
|
||||
value_ptr = value_ptr.offset(1);
|
||||
guard.initialized += 1;
|
||||
#[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);
|
||||
}
|
||||
core::mem::forget(guard);
|
||||
Ok(array.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
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
|
||||
list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(min_const_generics))]
|
||||
mod array_impls {
|
||||
use super::invalid_sequence_length;
|
||||
use crate::conversion::{AsPyPointer, IntoPyPointer};
|
||||
use crate::types::PySequence;
|
||||
use crate::{
|
||||
ffi, FromPyObject, IntoPy, Py, PyAny, PyDowncastError, PyObject, PyResult, Python,
|
||||
ToPyObject,
|
||||
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());
|
||||
}
|
||||
};
|
||||
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 {
|
||||
($($N:expr),+) => {
|
||||
$(
|
||||
impl<T> IntoPy<PyObject> for [T; $N]
|
||||
where
|
||||
T: IntoPy<PyObject>
|
||||
{
|
||||
fn into_py(self, py: Python<'_>) -> PyObject {
|
||||
// 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,
|
||||
}
|
||||
|
||||
struct ArrayGuard<T> {
|
||||
elements: [ManuallyDrop<T>; $N],
|
||||
start: usize,
|
||||
}
|
||||
|
||||
impl<T> Drop for ArrayGuard<T> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
)+
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(min_const_generics))]
|
||||
array_impls!(
|
||||
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,
|
||||
25, 26, 27, 28, 29, 30, 31, 32
|
||||
);
|
||||
|
||||
#[cfg(not(min_const_generics))]
|
||||
fn extract_sequence_into_slice<'s, T>(obj: &'s PyAny, slice: &mut [T]) -> PyResult<()>
|
||||
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 != slice.len() {
|
||||
return Err(invalid_sequence_length(slice.len(), seq_len));
|
||||
// [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 {
|
||||
let mut value_ptr = array.as_mut_ptr() as *mut T;
|
||||
for i in 0..N {
|
||||
core::ptr::write(value_ptr, cb(i)?);
|
||||
value_ptr = value_ptr.offset(1);
|
||||
guard.initialized += 1;
|
||||
}
|
||||
for (value, item) in slice.iter_mut().zip(seq.iter()?) {
|
||||
*value = item?.extract::<T>()?;
|
||||
}
|
||||
Ok(())
|
||||
core::mem::forget(guard);
|
||||
Ok(array.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -315,8 +125,50 @@ fn invalid_sequence_length(expected: usize, actual: usize) -> PyErr {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{
|
||||
panic,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
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]
|
||||
fn test_extract_small_bytearray_to_array() {
|
||||
Python::with_gil(|py| {
|
||||
|
@ -390,4 +242,16 @@ mod tests {
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,13 +50,6 @@ pub fn extract_pyclass_ref<'a, 'py: 'a, T: PyClass>(
|
|||
obj: &'py PyAny,
|
||||
holder: &'a mut Option<PyRef<'py, 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()?))
|
||||
}
|
||||
|
||||
|
@ -65,13 +58,6 @@ pub fn extract_pyclass_ref_mut<'a, 'py: 'a, T: PyClass<Frozen = False>>(
|
|||
obj: &'py PyAny,
|
||||
holder: &'a mut Option<PyRefMut<'py, 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()?))
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,6 @@ fn recursive_class_attributes() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(cfg_panic, cfg(panic = "unwind"))]
|
||||
fn test_fallible_class_attribute() {
|
||||
use pyo3::{exceptions::PyValueError, types::PyString};
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#![cfg(feature = "macros")]
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::IntoPyDict;
|
||||
|
||||
#[macro_use]
|
||||
#[path = "../common.rs"]
|
||||
#[path = "common.rs"]
|
||||
mod common;
|
||||
|
||||
#[pyclass]
|
|
@ -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");
|
||||
}
|
|
@ -11,6 +11,5 @@ name = "xtask"
|
|||
anyhow = "1.0.51"
|
||||
|
||||
# Clap 3 requires MSRV 1.54
|
||||
rustversion = "1.0"
|
||||
structopt = { version = "0.3", default-features = false }
|
||||
clap = { version = "2" }
|
||||
|
|
|
@ -107,7 +107,7 @@ impl Subcommand {
|
|||
|
||||
/// Run a command as a child process, inheriting stdin, stdout and stderr.
|
||||
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();
|
||||
if github_actions {
|
||||
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.
|
||||
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);
|
||||
|
||||
|
|
|
@ -1,47 +1,16 @@
|
|||
use anyhow::ensure;
|
||||
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> {
|
||||
let output = command.output()?;
|
||||
ensure! {
|
||||
output.status.success(),
|
||||
"process did not run successfully ({exit}): {command}",
|
||||
"process did not run successfully ({exit}): {command:?}",
|
||||
exit = match output.status.code() {
|
||||
Some(code) => format!("exit code {}", code),
|
||||
None => "terminated by signal".into(),
|
||||
},
|
||||
command = format_command(command),
|
||||
command = command,
|
||||
};
|
||||
Ok(output)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue