Skip to content

Commit b97546a

Browse files
authored
Merge branch 'PyO3:main' into main
2 parents 74007d7 + 2f65abf commit b97546a

File tree

6 files changed

+113
-88
lines changed

6 files changed

+113
-88
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ jobs:
189189
cargo update -p plotters --precise 0.3.1
190190
cargo update -p plotters-svg --precise 0.3.1
191191
cargo update -p plotters-backend --precise 0.3.2
192-
cargo update -p serde --precise 1.0.142
193192
cargo update -p bumpalo --precise 3.10.0
194193
195194
- name: Build docs

pyo3-ffi/src/lib.rs

Lines changed: 67 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -88,64 +88,40 @@
8888
//!
8989
//! use pyo3_ffi::*;
9090
//!
91-
//! #[allow(non_snake_case)]
92-
//! #[no_mangle]
93-
//! pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject {
94-
//! let init = PyModuleDef {
95-
//! m_base: PyModuleDef_HEAD_INIT,
96-
//! m_name: "string_sum\0".as_ptr() as *const c_char,
97-
//! m_doc: std::ptr::null(),
98-
//! m_size: 0,
99-
//! m_methods: std::ptr::null_mut(),
100-
//! m_slots: std::ptr::null_mut(),
101-
//! m_traverse: None,
102-
//! m_clear: None,
103-
//! m_free: None,
104-
//! };
105-
//!
106-
//! let mptr = PyModule_Create(Box::into_raw(Box::new(init)));
107-
//! let version = env!("CARGO_PKG_VERSION");
108-
//! PyModule_AddObject(
109-
//! mptr,
110-
//! "__version__\0".as_ptr() as *const c_char,
111-
//! PyUnicode_FromStringAndSize(version.as_ptr() as *const c_char, version.len() as isize),
112-
//! );
113-
//!
114-
//! let wrapped_sum_as_string = PyMethodDef {
115-
//! ml_name: "sum_as_string\0".as_ptr() as *const c_char,
91+
//! static mut MODULE_DEF: PyModuleDef = PyModuleDef {
92+
//! m_base: PyModuleDef_HEAD_INIT,
93+
//! m_name: "string_sum\0".as_ptr().cast::<c_char>(),
94+
//! m_doc: "A Python module written in Rust.\0"
95+
//! .as_ptr()
96+
//! .cast::<c_char>(),
97+
//! m_size: 0,
98+
//! m_methods: unsafe { METHODS.as_mut_ptr().cast() },
99+
//! m_slots: std::ptr::null_mut(),
100+
//! m_traverse: None,
101+
//! m_clear: None,
102+
//! m_free: None,
103+
//! };
104+
//!
105+
//! static mut METHODS: [PyMethodDef; 2] = [
106+
//! PyMethodDef {
107+
//! ml_name: "sum_as_string\0".as_ptr().cast::<c_char>(),
116108
//! ml_meth: PyMethodDefPointer {
117-
//! _PyCFunctionFast: sum_as_string
109+
//! _PyCFunctionFast: sum_as_string,
118110
//! },
119111
//! ml_flags: METH_FASTCALL,
120-
//! ml_doc: "returns the sum of two integers as a string\0".as_ptr() as *const c_char,
121-
//! };
122-
//!
123-
//! // PyModule_AddObject can technically fail.
124-
//! // For more involved applications error checking may be necessary
125-
//! PyModule_AddObject(
126-
//! mptr,
127-
//! "sum_as_string\0".as_ptr() as *const c_char,
128-
//! PyCFunction_NewEx(
129-
//! Box::into_raw(Box::new(wrapped_sum_as_string)),
130-
//! std::ptr::null_mut(),
131-
//! PyUnicode_InternFromString("string_sum\0".as_ptr() as *const c_char),
132-
//! ),
133-
//! );
134-
//!
135-
//! let all = ["__all__\0", "__version__\0", "sum_as_string\0"];
136-
//!
137-
//! let pyall = PyTuple_New(all.len() as isize);
138-
//! for (i, obj) in all.iter().enumerate() {
139-
//! PyTuple_SET_ITEM(
140-
//! pyall,
141-
//! i as isize,
142-
//! PyUnicode_InternFromString(obj.as_ptr() as *const c_char),
143-
//! )
144-
//! }
145-
//!
146-
//! PyModule_AddObject(mptr, "__all__\0".as_ptr() as *const c_char, pyall);
147-
//!
148-
//! mptr
112+
//! ml_doc: "returns the sum of two integers as a string\0"
113+
//! .as_ptr()
114+
//! .cast::<c_char>(),
115+
//! },
116+
//! // A zeroed PyMethodDef to mark the end of the array.
117+
//! PyMethodDef::zeroed()
118+
//! ];
119+
//!
120+
//! // The module initialization function, which must be named `PyInit_<your_module>`.
121+
//! #[allow(non_snake_case)]
122+
//! #[no_mangle]
123+
//! pub unsafe extern "C" fn PyInit_string_sum() -> *mut PyObject {
124+
//! PyModule_Create(ptr::addr_of_mut!(MODULE_DEF))
149125
//! }
150126
//!
151127
//! pub unsafe extern "C" fn sum_as_string(
@@ -154,42 +130,60 @@
154130
//! nargs: Py_ssize_t,
155131
//! ) -> *mut PyObject {
156132
//! if nargs != 2 {
157-
//! return raise_type_error("sum_as_string() expected 2 positional arguments");
133+
//! PyErr_SetString(
134+
//! PyExc_TypeError,
135+
//! "sum_as_string() expected 2 positional arguments\0"
136+
//! .as_ptr()
137+
//! .cast::<c_char>(),
138+
//! );
139+
//! return std::ptr::null_mut();
158140
//! }
159141
//!
160142
//! let arg1 = *args;
161143
//! if PyLong_Check(arg1) == 0 {
162-
//! return raise_type_error("sum_as_string() expected an int for positional argument 1");
144+
//! PyErr_SetString(
145+
//! PyExc_TypeError,
146+
//! "sum_as_string() expected an int for positional argument 1\0"
147+
//! .as_ptr()
148+
//! .cast::<c_char>(),
149+
//! );
150+
//! return std::ptr::null_mut();
163151
//! }
164152
//!
165153
//! let arg1 = PyLong_AsLong(arg1);
166154
//! if !PyErr_Occurred().is_null() {
167-
//! return ptr::null_mut()
155+
//! return ptr::null_mut();
168156
//! }
169157
//!
170158
//! let arg2 = *args.add(1);
171159
//! if PyLong_Check(arg2) == 0 {
172-
//! return raise_type_error("sum_as_string() expected an int for positional argument 2");
160+
//! PyErr_SetString(
161+
//! PyExc_TypeError,
162+
//! "sum_as_string() expected an int for positional argument 2\0"
163+
//! .as_ptr()
164+
//! .cast::<c_char>(),
165+
//! );
166+
//! return std::ptr::null_mut();
173167
//! }
174168
//!
175169
//! let arg2 = PyLong_AsLong(arg2);
176170
//! if !PyErr_Occurred().is_null() {
177-
//! return ptr::null_mut()
171+
//! return ptr::null_mut();
178172
//! }
179-
//! let res = (arg1 + arg2).to_string();
180-
//! PyUnicode_FromStringAndSize(res.as_ptr() as *const c_char, res.len() as isize)
181-
//! }
182173
//!
183-
//! #[cold]
184-
//! #[inline(never)]
185-
//! fn raise_type_error(msg: &str) -> *mut PyObject {
186-
//! unsafe {
187-
//! let err_msg =
188-
//! PyUnicode_FromStringAndSize(msg.as_ptr() as *const c_char, msg.len() as isize);
189-
//! PyErr_SetObject(PyExc_TypeError, err_msg);
190-
//! Py_DECREF(err_msg);
191-
//! };
192-
//! std::ptr::null_mut()
174+
//! match arg1.checked_add(arg2) {
175+
//! Some(sum) => {
176+
//! let string = sum.to_string();
177+
//! PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as isize)
178+
//! }
179+
//! None => {
180+
//! PyErr_SetString(
181+
//! PyExc_OverflowError,
182+
//! "arguments too large to add\0".as_ptr().cast::<c_char>(),
183+
//! );
184+
//! std::ptr::null_mut()
185+
//! }
186+
//! }
193187
//! }
194188
//! ```
195189
//!

pyo3-ffi/src/methodobject.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ pub struct PyMethodDef {
9494
pub ml_doc: *const c_char,
9595
}
9696

97+
impl PyMethodDef {
98+
pub const fn zeroed() -> PyMethodDef {
99+
PyMethodDef {
100+
ml_name: ptr::null(),
101+
ml_meth: PyMethodDefPointer {
102+
Void: ptr::null_mut(),
103+
},
104+
ml_flags: 0,
105+
ml_doc: ptr::null(),
106+
}
107+
}
108+
}
109+
97110
impl Default for PyMethodDef {
98111
fn default() -> PyMethodDef {
99112
PyMethodDef {
@@ -147,6 +160,12 @@ impl PyMethodDefPointer {
147160
pub fn is_null(&self) -> bool {
148161
self.as_ptr().is_null()
149162
}
163+
164+
pub const fn zeroed() -> PyMethodDefPointer {
165+
PyMethodDefPointer {
166+
Void: ptr::null_mut(),
167+
}
168+
}
150169
}
151170

152171
impl PartialEq for PyMethodDefPointer {

tests/ui/not_send_auto_trait.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
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]`
2-
--> tests/ui/not_send_auto_trait.rs:4:8
2+
--> tests/ui/not_send_auto_trait.rs:4:22
33
|
44
4 | py.allow_threads(|| { drop(py); });
5-
| ^^^^^^^^^^^^^ -- within this `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]`
6-
| |
7-
| within `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]`, the trait `Ungil` is not implemented for `pyo3::Python<'_>`
5+
| ------------- --^^^^^^^^^^^^^^
6+
| | |
7+
| | within `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]`, the trait `Ungil` is not implemented for `pyo3::Python<'_>`
8+
| | within this `[closure@$DIR/tests/ui/not_send_auto_trait.rs:4:22: 4:24]`
9+
| required by a bound introduced by this call
810
|
911
= note: required because it appears within the type `&pyo3::Python<'_>`
1012
note: required because it's used within this closure

tests/ui/not_send_auto_trait2.stderr

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
error[E0277]: the trait bound `PyAny: Ungil` is not satisfied in `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]`
2-
--> tests/ui/not_send_auto_trait2.rs:8:12
2+
--> tests/ui/not_send_auto_trait2.rs:8:26
33
|
4-
8 | py.allow_threads(|| {
5-
| ^^^^^^^^^^^^^ -- within this `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]`
6-
| |
7-
| within `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]`, the trait `Ungil` is not implemented for `PyAny`
4+
8 | py.allow_threads(|| {
5+
| ------------- ^-
6+
| | |
7+
| ____________|_____________within this `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]`
8+
| | |
9+
| | required by a bound introduced by this call
10+
9 | | println!("{:?}", string);
11+
10 | | });
12+
| |_________^ within `[closure@$DIR/tests/ui/not_send_auto_trait2.rs:8:26: 8:28]`, the trait `Ungil` is not implemented for `PyAny`
813
|
914
= note: required because it appears within the type `PyString`
1015
= note: required because it appears within the type `&PyString`

tests/ui/send_wrapper.stderr

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
error[E0277]: the trait bound `PyAny: Ungil` is not satisfied in `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]`
2-
--> tests/ui/send_wrapper.rs:11:12
2+
--> tests/ui/send_wrapper.rs:11:26
33
|
4-
11 | py.allow_threads(|| {
5-
| ^^^^^^^^^^^^^ -- within this `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]`
6-
| |
7-
| within `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]`, the trait `Ungil` is not implemented for `PyAny`
4+
11 | py.allow_threads(|| {
5+
| ------------- ^-
6+
| | |
7+
| ____________|_____________within this `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]`
8+
| | |
9+
| | required by a bound introduced by this call
10+
12 | | let smuggled: &PyString = *wrapped;
11+
13 | | println!("{:?}", smuggled);
12+
14 | | });
13+
| |_________^ within `[closure@$DIR/tests/ui/send_wrapper.rs:11:26: 11:28]`, the trait `Ungil` is not implemented for `PyAny`
814
|
915
= note: required because it appears within the type `PyString`
1016
= note: required because it appears within the type `&PyString`

0 commit comments

Comments
 (0)