From 3845e3fe33cbd13e21450615241334580ade1102 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Mon, 22 Aug 2022 22:25:02 +0200 Subject: [PATCH 1/3] Make a way to make const zeroed PyMethodDef --- pyo3-ffi/src/methodobject.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pyo3-ffi/src/methodobject.rs b/pyo3-ffi/src/methodobject.rs index 964c9a7c..5c378871 100644 --- a/pyo3-ffi/src/methodobject.rs +++ b/pyo3-ffi/src/methodobject.rs @@ -94,6 +94,19 @@ pub struct PyMethodDef { pub ml_doc: *const c_char, } +impl PyMethodDef { + pub const fn zeroed() -> PyMethodDef { + PyMethodDef { + ml_name: ptr::null(), + ml_meth: PyMethodDefPointer { + Void: ptr::null_mut(), + }, + ml_flags: 0, + ml_doc: ptr::null(), + } + } +} + impl Default for PyMethodDef { fn default() -> PyMethodDef { PyMethodDef { @@ -147,6 +160,12 @@ impl PyMethodDefPointer { pub fn is_null(&self) -> bool { self.as_ptr().is_null() } + + pub const fn zeroed() -> PyMethodDefPointer { + PyMethodDefPointer { + Void: ptr::null_mut(), + } + } } impl PartialEq for PyMethodDefPointer { From 5b845d3b1a7da7195be56385e29b5bec16245e93 Mon Sep 17 00:00:00 2001 From: mejrs <> Date: Mon, 22 Aug 2022 22:27:05 +0200 Subject: [PATCH 2/3] Improve pyo3-ffi example --- pyo3-ffi/src/lib.rs | 140 +++++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 73 deletions(-) diff --git a/pyo3-ffi/src/lib.rs b/pyo3-ffi/src/lib.rs index f37b758e..73ec459b 100644 --- a/pyo3-ffi/src/lib.rs +++ b/pyo3-ffi/src/lib.rs @@ -88,64 +88,40 @@ //! //! use pyo3_ffi::*; //! +//! static mut MODULE_DEF: PyModuleDef = PyModuleDef { +//! m_base: PyModuleDef_HEAD_INIT, +//! m_name: "string_sum\0".as_ptr().cast::(), +//! m_doc: "A Python module written in Rust.\0" +//! .as_ptr() +//! .cast::(), +//! m_size: 0, +//! m_methods: unsafe { METHODS.as_mut_ptr().cast() }, +//! m_slots: std::ptr::null_mut(), +//! m_traverse: None, +//! m_clear: None, +//! m_free: None, +//! }; +//! +//! static mut METHODS: [PyMethodDef; 2] = [ +//! PyMethodDef { +//! ml_name: "sum_as_string\0".as_ptr().cast::(), +//! ml_meth: PyMethodDefPointer { +//! _PyCFunctionFast: sum_as_string, +//! }, +//! ml_flags: METH_FASTCALL, +//! ml_doc: "returns the sum of two integers as a string\0" +//! .as_ptr() +//! .cast::(), +//! }, +//! // A zeroed PyMethodDef to mark the end of the array. +//! PyMethodDef::zeroed() +//! ]; +//! +//! // The module initialization function, which must be named `PyInit_`. //! #[allow(non_snake_case)] //! #[no_mangle] //! pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject { -//! let init = PyModuleDef { -//! m_base: PyModuleDef_HEAD_INIT, -//! m_name: "string_sum\0".as_ptr() as *const c_char, -//! m_doc: std::ptr::null(), -//! m_size: 0, -//! m_methods: std::ptr::null_mut(), -//! m_slots: std::ptr::null_mut(), -//! m_traverse: None, -//! m_clear: None, -//! m_free: None, -//! }; -//! -//! let mptr = PyModule_Create(Box::into_raw(Box::new(init))); -//! let version = env!("CARGO_PKG_VERSION"); -//! PyModule_AddObject( -//! mptr, -//! "__version__\0".as_ptr() as *const c_char, -//! PyUnicode_FromStringAndSize(version.as_ptr() as *const c_char, version.len() as isize), -//! ); -//! -//! let wrapped_sum_as_string = PyMethodDef { -//! ml_name: "sum_as_string\0".as_ptr() as *const c_char, -//! ml_meth: PyMethodDefPointer { -//! _PyCFunctionFast: sum_as_string -//! }, -//! ml_flags: METH_FASTCALL, -//! ml_doc: "returns the sum of two integers as a string\0".as_ptr() as *const c_char, -//! }; -//! -//! // PyModule_AddObject can technically fail. -//! // For more involved applications error checking may be necessary -//! PyModule_AddObject( -//! mptr, -//! "sum_as_string\0".as_ptr() as *const c_char, -//! PyCFunction_NewEx( -//! Box::into_raw(Box::new(wrapped_sum_as_string)), -//! std::ptr::null_mut(), -//! PyUnicode_InternFromString("string_sum\0".as_ptr() as *const c_char), -//! ), -//! ); -//! -//! let all = ["__all__\0", "__version__\0", "sum_as_string\0"]; -//! -//! let pyall = PyTuple_New(all.len() as isize); -//! for (i, obj) in all.iter().enumerate() { -//! PyTuple_SET_ITEM( -//! pyall, -//! i as isize, -//! PyUnicode_InternFromString(obj.as_ptr() as *const c_char), -//! ) -//! } -//! -//! PyModule_AddObject(mptr, "__all__\0".as_ptr() as *const c_char, pyall); -//! -//! mptr +//! PyModule_Create(ptr::addr_of_mut!(MODULE_DEF)) //! } //! //! pub unsafe extern "C" fn sum_as_string( @@ -154,42 +130,60 @@ //! nargs: Py_ssize_t, //! ) -> *mut PyObject { //! if nargs != 2 { -//! return raise_type_error("sum_as_string() expected 2 positional arguments"); +//! PyErr_SetString( +//! PyExc_TypeError, +//! "sum_as_string() expected 2 positional arguments\0" +//! .as_ptr() +//! .cast::(), +//! ); +//! return std::ptr::null_mut(); //! } //! //! let arg1 = *args; //! if PyLong_Check(arg1) == 0 { -//! return raise_type_error("sum_as_string() expected an int for positional argument 1"); +//! PyErr_SetString( +//! PyExc_TypeError, +//! "sum_as_string() expected an int for positional argument 1\0" +//! .as_ptr() +//! .cast::(), +//! ); +//! return std::ptr::null_mut(); //! } //! //! let arg1 = PyLong_AsLong(arg1); //! if !PyErr_Occurred().is_null() { -//! return ptr::null_mut() +//! return ptr::null_mut(); //! } //! //! let arg2 = *args.add(1); //! if PyLong_Check(arg2) == 0 { -//! return raise_type_error("sum_as_string() expected an int for positional argument 2"); +//! PyErr_SetString( +//! PyExc_TypeError, +//! "sum_as_string() expected an int for positional argument 2\0" +//! .as_ptr() +//! .cast::(), +//! ); +//! return std::ptr::null_mut(); //! } //! //! let arg2 = PyLong_AsLong(arg2); //! if !PyErr_Occurred().is_null() { -//! return ptr::null_mut() +//! return ptr::null_mut(); //! } -//! let res = (arg1 + arg2).to_string(); -//! PyUnicode_FromStringAndSize(res.as_ptr() as *const c_char, res.len() as isize) -//! } //! -//! #[cold] -//! #[inline(never)] -//! fn raise_type_error(msg: &str) -> *mut PyObject { -//! unsafe { -//! let err_msg = -//! PyUnicode_FromStringAndSize(msg.as_ptr() as *const c_char, msg.len() as isize); -//! PyErr_SetObject(PyExc_TypeError, err_msg); -//! Py_DECREF(err_msg); -//! }; -//! std::ptr::null_mut() +//! match arg1.checked_add(arg2) { +//! Some(sum) => { +//! let string = sum.to_string(); +//! PyUnicode_FromStringAndSize(string.as_ptr().cast::(), string.len() as isize) +//! } +//! None => { +//! PyErr_SetString( +//! PyExc_OverflowError, +//! "arguments too large to add\0".as_ptr().cast::(), +//! ); +//! std::ptr::null_mut() +//! } +//! } //! } //! ``` //! From 36ecadd69f8e81ffdb19dff77d3e1579877e42ba Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Tue, 23 Aug 2022 08:07:13 +0100 Subject: [PATCH 3/3] ci: unpin serde, fixup nightly ui tests --- .github/workflows/ci.yml | 1 - tests/ui/not_send_auto_trait.stderr | 10 ++++++---- tests/ui/not_send_auto_trait2.stderr | 15 ++++++++++----- tests/ui/send_wrapper.stderr | 16 +++++++++++----- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e29e280b..6a518931 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -189,7 +189,6 @@ jobs: cargo update -p plotters --precise 0.3.1 cargo update -p plotters-svg --precise 0.3.1 cargo update -p plotters-backend --precise 0.3.2 - cargo update -p serde --precise 1.0.142 cargo update -p bumpalo --precise 3.10.0 - name: Build docs diff --git a/tests/ui/not_send_auto_trait.stderr b/tests/ui/not_send_auto_trait.stderr index a769d7e8..99f46dc3 100644 --- a/tests/ui/not_send_auto_trait.stderr +++ b/tests/ui/not_send_auto_trait.stderr @@ -1,10 +1,12 @@ error[E0277]: the trait bound `pyo3::Python<'_>: Ungil` is not satisfied in `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]` - --> tests/ui/not_send_auto_trait.rs:4:8 + --> tests/ui/not_send_auto_trait.rs:4:22 | 4 | py.allow_threads(|| { drop(py); }); - | ^^^^^^^^^^^^^ -- within this `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]` - | | - | within `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]`, the trait `Ungil` is not implemented for `pyo3::Python<'_>` + | ------------- --^^^^^^^^^^^^^^ + | | | + | | within `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]`, the trait `Ungil` is not implemented for `pyo3::Python<'_>` + | | within this `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]` + | required by a bound introduced by this call | = note: required because it appears within the type `&pyo3::Python<'_>` note: required because it's used within this closure diff --git a/tests/ui/not_send_auto_trait2.stderr b/tests/ui/not_send_auto_trait2.stderr index 3aedb37c..592efb4a 100644 --- a/tests/ui/not_send_auto_trait2.stderr +++ b/tests/ui/not_send_auto_trait2.stderr @@ -1,10 +1,15 @@ error[E0277]: the trait bound `PyAny: Ungil` is not satisfied in `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]` - --> tests/ui/not_send_auto_trait2.rs:8:12 + --> tests/ui/not_send_auto_trait2.rs:8:26 | -8 | py.allow_threads(|| { - | ^^^^^^^^^^^^^ -- within this `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]` - | | - | within `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]`, the trait `Ungil` is not implemented for `PyAny` +8 | py.allow_threads(|| { + | ------------- ^- + | | | + | ____________|_____________within this `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]` + | | | + | | required by a bound introduced by this call +9 | | println!("{:?}", string); +10 | | }); + | |_________^ within `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]`, the trait `Ungil` is not implemented for `PyAny` | = note: required because it appears within the type `PyString` = note: required because it appears within the type `&PyString` diff --git a/tests/ui/send_wrapper.stderr b/tests/ui/send_wrapper.stderr index b24fb106..1f41784f 100644 --- a/tests/ui/send_wrapper.stderr +++ b/tests/ui/send_wrapper.stderr @@ -1,10 +1,16 @@ error[E0277]: the trait bound `PyAny: Ungil` is not satisfied in `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]` - --> tests/ui/send_wrapper.rs:11:12 + --> tests/ui/send_wrapper.rs:11:26 | -11 | py.allow_threads(|| { - | ^^^^^^^^^^^^^ -- within this `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]` - | | - | within `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]`, the trait `Ungil` is not implemented for `PyAny` +11 | py.allow_threads(|| { + | ------------- ^- + | | | + | ____________|_____________within this `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]` + | | | + | | required by a bound introduced by this call +12 | | let smuggled: &PyString = *wrapped; +13 | | println!("{:?}", smuggled); +14 | | }); + | |_________^ within `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]`, the trait `Ungil` is not implemented for `PyAny` | = note: required because it appears within the type `PyString` = note: required because it appears within the type `&PyString`