From 5eed73f1c054ad651128142886856bbf673bb9d0 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sun, 18 Jun 2023 21:59:04 +0200 Subject: [PATCH] Rework pyobject_native_type_info! to expect callables Most native types have static type objects which just need to be turned into a pointer using addr_of_mut!, but sometimes like for exceptions we do call a function which lazily initializes a type object. This makes the pyobject_native_type_info! macro expect callable and passes it the GIL token so that we do not need to call Python::assume_gil_acquired. The case of static type objects is handled by the pyobject_native_static_type_object! helper macro. --- src/exceptions.rs | 8 ++++---- src/types/any.rs | 2 +- src/types/boolobject.rs | 2 +- src/types/bytearray.rs | 2 +- src/types/bytes.rs | 2 +- src/types/capsule.rs | 2 +- src/types/code.rs | 2 +- src/types/complex.rs | 2 +- src/types/datetime.rs | 10 +++++----- src/types/dict.rs | 8 ++++---- src/types/floatob.rs | 2 +- src/types/frame.rs | 2 +- src/types/frozenset.rs | 4 ++-- src/types/function.rs | 4 ++-- src/types/list.rs | 2 +- src/types/mod.rs | 12 ++++++++++-- src/types/module.rs | 2 +- src/types/num.rs | 2 +- src/types/pysuper.rs | 5 ++++- src/types/set.rs | 4 ++-- src/types/slice.rs | 2 +- src/types/string.rs | 2 +- src/types/traceback.rs | 2 +- src/types/tuple.rs | 2 +- src/types/typeobject.rs | 2 +- 25 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/exceptions.rs b/src/exceptions.rs index 9cbc8587..a345274c 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -94,7 +94,7 @@ macro_rules! import_exception { $crate::pyobject_native_type_core!( $name, - *$name::type_object_raw($crate::Python::assume_gil_acquired()), + $name::type_object_raw, #module=::std::option::Option::Some(stringify!($module)) ); @@ -233,7 +233,7 @@ macro_rules! create_exception_type_object { ($module: expr, $name: ident, $base: ty, $doc: expr) => { $crate::pyobject_native_type_core!( $name, - *$name::type_object_raw($crate::Python::assume_gil_acquired()), + $name::type_object_raw, #module=::std::option::Option::Some(stringify!($module)) ); @@ -266,7 +266,7 @@ macro_rules! impl_native_exception ( pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); - $crate::pyobject_native_type!($name, $layout, *($crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject)); + $crate::pyobject_native_type!($name, $layout, |_py| unsafe { $crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject }); ); ($name:ident, $exc_name:ident, $doc:expr) => ( impl_native_exception!($name, $exc_name, $doc, $crate::ffi::PyBaseExceptionObject); @@ -282,7 +282,7 @@ macro_rules! impl_windows_native_exception ( pub struct $name($crate::PyAny); $crate::impl_exception_boilerplate!($name); - $crate::pyobject_native_type!($name, $layout, *($crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject)); + $crate::pyobject_native_type!($name, $layout, |_py| unsafe { $crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject }); ); ($name:ident, $exc_name:ident, $doc:expr) => ( impl_windows_native_exception!($name, $exc_name, $doc, $crate::ffi::PyBaseExceptionObject); diff --git a/src/types/any.rs b/src/types/any.rs index 35d1f98b..c9dbd4c4 100644 --- a/src/types/any.rs +++ b/src/types/any.rs @@ -54,7 +54,7 @@ pyobject_native_type_base!(PyAny); pyobject_native_type_info!( PyAny, - ffi::PyBaseObject_Type, + pyobject_native_static_type_object!(ffi::PyBaseObject_Type), Some("builtins"), #checkfunction=PyObject_Check ); diff --git a/src/types/boolobject.rs b/src/types/boolobject.rs index 919810d2..270eadee 100644 --- a/src/types/boolobject.rs +++ b/src/types/boolobject.rs @@ -8,7 +8,7 @@ use crate::{ #[repr(transparent)] pub struct PyBool(PyAny); -pyobject_native_type!(PyBool, ffi::PyObject, ffi::PyBool_Type, #checkfunction=ffi::PyBool_Check); +pyobject_native_type!(PyBool, ffi::PyObject, pyobject_native_static_type_object!(ffi::PyBool_Type), #checkfunction=ffi::PyBool_Check); impl PyBool { /// Depending on `val`, returns `true` or `false`. diff --git a/src/types/bytearray.rs b/src/types/bytearray.rs index c11af6d7..9c03ddec 100644 --- a/src/types/bytearray.rs +++ b/src/types/bytearray.rs @@ -7,7 +7,7 @@ use std::slice; #[repr(transparent)] pub struct PyByteArray(PyAny); -pyobject_native_type_core!(PyByteArray, ffi::PyByteArray_Type, #checkfunction=ffi::PyByteArray_Check); +pyobject_native_type_core!(PyByteArray, pyobject_native_static_type_object!(ffi::PyByteArray_Type), #checkfunction=ffi::PyByteArray_Check); impl PyByteArray { /// Creates a new Python bytearray object. diff --git a/src/types/bytes.rs b/src/types/bytes.rs index ae40c08e..a215ce92 100644 --- a/src/types/bytes.rs +++ b/src/types/bytes.rs @@ -13,7 +13,7 @@ use super::bytearray::PyByteArray; #[repr(transparent)] pub struct PyBytes(PyAny); -pyobject_native_type_core!(PyBytes, ffi::PyBytes_Type, #checkfunction=ffi::PyBytes_Check); +pyobject_native_type_core!(PyBytes, pyobject_native_static_type_object!(ffi::PyBytes_Type), #checkfunction=ffi::PyBytes_Check); impl PyBytes { /// Creates a new Python bytestring object. diff --git a/src/types/capsule.rs b/src/types/capsule.rs index 152ac0ff..55484dce 100644 --- a/src/types/capsule.rs +++ b/src/types/capsule.rs @@ -41,7 +41,7 @@ use std::os::raw::{c_char, c_int, c_void}; #[repr(transparent)] pub struct PyCapsule(PyAny); -pyobject_native_type_core!(PyCapsule, ffi::PyCapsule_Type, #checkfunction=ffi::PyCapsule_CheckExact); +pyobject_native_type_core!(PyCapsule, pyobject_native_static_type_object!(ffi::PyCapsule_Type), #checkfunction=ffi::PyCapsule_CheckExact); impl PyCapsule { /// Constructs a new capsule whose contents are `value`, associated with `name`. diff --git a/src/types/code.rs b/src/types/code.rs index c0d0ce83..8956deb1 100644 --- a/src/types/code.rs +++ b/src/types/code.rs @@ -7,6 +7,6 @@ pub struct PyCode(PyAny); pyobject_native_type_core!( PyCode, - ffi::PyCode_Type, + pyobject_native_static_type_object!(ffi::PyCode_Type), #checkfunction=ffi::PyCode_Check ); diff --git a/src/types/complex.rs b/src/types/complex.rs index 415cc5d2..fec137a6 100644 --- a/src/types/complex.rs +++ b/src/types/complex.rs @@ -14,7 +14,7 @@ pub struct PyComplex(PyAny); pyobject_native_type!( PyComplex, ffi::PyComplexObject, - ffi::PyComplex_Type, + pyobject_native_static_type_object!(ffi::PyComplex_Type), #checkfunction=ffi::PyComplex_Check ); diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 89de91f0..7b112b44 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -173,7 +173,7 @@ pub struct PyDate(PyAny); pyobject_native_type!( PyDate, crate::ffi::PyDateTime_Date, - *ensure_datetime_api(Python::assume_gil_acquired()).DateType, + |py| ensure_datetime_api(py).DateType, #module=Some("datetime"), #checkfunction=PyDate_Check ); @@ -228,7 +228,7 @@ pub struct PyDateTime(PyAny); pyobject_native_type!( PyDateTime, crate::ffi::PyDateTime_DateTime, - *ensure_datetime_api(Python::assume_gil_acquired()).DateTimeType, + |py| ensure_datetime_api(py).DateTimeType, #module=Some("datetime"), #checkfunction=PyDateTime_Check ); @@ -377,7 +377,7 @@ pub struct PyTime(PyAny); pyobject_native_type!( PyTime, crate::ffi::PyDateTime_Time, - *ensure_datetime_api(Python::assume_gil_acquired()).TimeType, + |py| ensure_datetime_api(py).TimeType, #module=Some("datetime"), #checkfunction=PyTime_Check ); @@ -477,7 +477,7 @@ pub struct PyTzInfo(PyAny); pyobject_native_type!( PyTzInfo, crate::ffi::PyObject, - *ensure_datetime_api(Python::assume_gil_acquired()).TZInfoType, + |py| ensure_datetime_api(py).TZInfoType, #module=Some("datetime"), #checkfunction=PyTZInfo_Check ); @@ -493,7 +493,7 @@ pub struct PyDelta(PyAny); pyobject_native_type!( PyDelta, crate::ffi::PyDateTime_Delta, - *ensure_datetime_api(Python::assume_gil_acquired()).DeltaType, + |py| ensure_datetime_api(py).DeltaType, #module=Some("datetime"), #checkfunction=PyDelta_Check ); diff --git a/src/types/dict.rs b/src/types/dict.rs index 0aedb13a..cb1036cf 100644 --- a/src/types/dict.rs +++ b/src/types/dict.rs @@ -14,7 +14,7 @@ pub struct PyDict(PyAny); pyobject_native_type!( PyDict, ffi::PyDictObject, - ffi::PyDict_Type, + pyobject_native_static_type_object!(ffi::PyDict_Type), #checkfunction=ffi::PyDict_Check ); @@ -26,7 +26,7 @@ pub struct PyDictKeys(PyAny); #[cfg(not(PyPy))] pyobject_native_type_core!( PyDictKeys, - ffi::PyDictKeys_Type, + pyobject_native_static_type_object!(ffi::PyDictKeys_Type), #checkfunction=ffi::PyDictKeys_Check ); @@ -38,7 +38,7 @@ pub struct PyDictValues(PyAny); #[cfg(not(PyPy))] pyobject_native_type_core!( PyDictValues, - ffi::PyDictValues_Type, + pyobject_native_static_type_object!(ffi::PyDictValues_Type), #checkfunction=ffi::PyDictValues_Check ); @@ -50,7 +50,7 @@ pub struct PyDictItems(PyAny); #[cfg(not(PyPy))] pyobject_native_type_core!( PyDictItems, - ffi::PyDictItems_Type, + pyobject_native_static_type_object!(ffi::PyDictItems_Type), #checkfunction=ffi::PyDictItems_Check ); diff --git a/src/types/floatob.rs b/src/types/floatob.rs index 82db228d..1e188079 100644 --- a/src/types/floatob.rs +++ b/src/types/floatob.rs @@ -17,7 +17,7 @@ pub struct PyFloat(PyAny); pyobject_native_type!( PyFloat, ffi::PyFloatObject, - ffi::PyFloat_Type, + pyobject_native_static_type_object!(ffi::PyFloat_Type), #checkfunction=ffi::PyFloat_Check ); diff --git a/src/types/frame.rs b/src/types/frame.rs index 160f3b3b..0ab873b8 100644 --- a/src/types/frame.rs +++ b/src/types/frame.rs @@ -7,6 +7,6 @@ pub struct PyFrame(PyAny); pyobject_native_type_core!( PyFrame, - ffi::PyFrame_Type, + pyobject_native_static_type_object!(ffi::PyFrame_Type), #checkfunction=ffi::PyFrame_Check ); diff --git a/src/types/frozenset.rs b/src/types/frozenset.rs index ecfbbb43..cc5b1da4 100644 --- a/src/types/frozenset.rs +++ b/src/types/frozenset.rs @@ -48,14 +48,14 @@ pub struct PyFrozenSet(PyAny); pyobject_native_type!( PyFrozenSet, ffi::PySetObject, - ffi::PyFrozenSet_Type, + pyobject_native_static_type_object!(ffi::PyFrozenSet_Type), #checkfunction=ffi::PyFrozenSet_Check ); #[cfg(PyPy)] pyobject_native_type_core!( PyFrozenSet, - ffi::PyFrozenSet_Type, + pyobject_native_static_type_object!(ffi::PyFrozenSet_Type), #checkfunction=ffi::PyFrozenSet_Check ); diff --git a/src/types/function.rs b/src/types/function.rs index 1f2c3545..46949704 100644 --- a/src/types/function.rs +++ b/src/types/function.rs @@ -14,7 +14,7 @@ use std::ffi::CStr; #[repr(transparent)] pub struct PyCFunction(PyAny); -pyobject_native_type_core!(PyCFunction, ffi::PyCFunction_Type, #checkfunction=ffi::PyCFunction_Check); +pyobject_native_type_core!(PyCFunction, pyobject_native_static_type_object!(ffi::PyCFunction_Type), #checkfunction=ffi::PyCFunction_Check); impl PyCFunction { /// Create a new built-in function with keywords (*args and/or **kwargs). @@ -180,4 +180,4 @@ unsafe impl Send for ClosureDestructor {} pub struct PyFunction(PyAny); #[cfg(all(not(Py_LIMITED_API), not(all(PyPy, not(Py_3_8)))))] -pyobject_native_type_core!(PyFunction, ffi::PyFunction_Type, #checkfunction=ffi::PyFunction_Check); +pyobject_native_type_core!(PyFunction, pyobject_native_static_type_object!(ffi::PyFunction_Type), #checkfunction=ffi::PyFunction_Check); diff --git a/src/types/list.rs b/src/types/list.rs index bdbdd419..1b52a614 100644 --- a/src/types/list.rs +++ b/src/types/list.rs @@ -10,7 +10,7 @@ use crate::{AsPyPointer, IntoPyPointer, Py, PyAny, PyObject, Python, ToPyObject} #[repr(transparent)] pub struct PyList(PyAny); -pyobject_native_type_core!(PyList, ffi::PyList_Type, #checkfunction=ffi::PyList_Check); +pyobject_native_type_core!(PyList, pyobject_native_static_type_object!(ffi::PyList_Type), #checkfunction=ffi::PyList_Check); #[inline] #[track_caller] diff --git a/src/types/mod.rs b/src/types/mod.rs index 99faba9b..6fbc5d2e 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -177,6 +177,14 @@ macro_rules! pyobject_native_type_named ( }; ); +#[doc(hidden)] +#[macro_export] +macro_rules! pyobject_native_static_type_object( + ($typeobject:expr) => { + |_py| unsafe { ::std::ptr::addr_of_mut!($typeobject) } + }; +); + #[doc(hidden)] #[macro_export] macro_rules! pyobject_native_type_info( @@ -188,8 +196,8 @@ macro_rules! pyobject_native_type_info( const MODULE: ::std::option::Option<&'static str> = $module; #[inline] - fn type_object_raw(_py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { - unsafe { ::std::ptr::addr_of_mut!($typeobject) } + fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject { + $typeobject(py) } $( diff --git a/src/types/module.rs b/src/types/module.rs index b6b25eac..02881a0e 100644 --- a/src/types/module.rs +++ b/src/types/module.rs @@ -18,7 +18,7 @@ use std::str; #[repr(transparent)] pub struct PyModule(PyAny); -pyobject_native_type_core!(PyModule, ffi::PyModule_Type, #checkfunction=ffi::PyModule_Check); +pyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), #checkfunction=ffi::PyModule_Check); impl PyModule { /// Creates a new module object with the `__name__` attribute set to `name`. diff --git a/src/types/num.rs b/src/types/num.rs index 52251715..26748f7d 100644 --- a/src/types/num.rs +++ b/src/types/num.rs @@ -9,4 +9,4 @@ use crate::{ffi, PyAny}; #[repr(transparent)] pub struct PyLong(PyAny); -pyobject_native_type_core!(PyLong, ffi::PyLong_Type, #checkfunction=ffi::PyLong_Check); +pyobject_native_type_core!(PyLong, pyobject_native_static_type_object!(ffi::PyLong_Type), #checkfunction=ffi::PyLong_Check); diff --git a/src/types/pysuper.rs b/src/types/pysuper.rs index 98a47957..cc531f60 100644 --- a/src/types/pysuper.rs +++ b/src/types/pysuper.rs @@ -8,7 +8,10 @@ use crate::{PyAny, PyResult}; #[repr(transparent)] pub struct PySuper(PyAny); -pyobject_native_type_core!(PySuper, ffi::PySuper_Type); +pyobject_native_type_core!( + PySuper, + pyobject_native_static_type_object!(ffi::PySuper_Type) +); impl PySuper { /// Constructs a new super object. More read about super object: [docs](https://docs.python.org/3/library/functions.html#super) diff --git a/src/types/set.rs b/src/types/set.rs index cf043d99..76771862 100644 --- a/src/types/set.rs +++ b/src/types/set.rs @@ -15,14 +15,14 @@ pub struct PySet(PyAny); pyobject_native_type!( PySet, ffi::PySetObject, - ffi::PySet_Type, + pyobject_native_static_type_object!(ffi::PySet_Type), #checkfunction=ffi::PySet_Check ); #[cfg(PyPy)] pyobject_native_type_core!( PySet, - ffi::PySet_Type, + pyobject_native_static_type_object!(ffi::PySet_Type), #checkfunction=ffi::PySet_Check ); diff --git a/src/types/slice.rs b/src/types/slice.rs index e82b535a..2f1e796c 100644 --- a/src/types/slice.rs +++ b/src/types/slice.rs @@ -12,7 +12,7 @@ pub struct PySlice(PyAny); pyobject_native_type!( PySlice, ffi::PySliceObject, - ffi::PySlice_Type, + pyobject_native_static_type_object!(ffi::PySlice_Type), #checkfunction=ffi::PySlice_Check ); diff --git a/src/types/string.rs b/src/types/string.rs index 05b7109f..997d27fb 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -127,7 +127,7 @@ impl<'a> PyStringData<'a> { #[repr(transparent)] pub struct PyString(PyAny); -pyobject_native_type_core!(PyString, ffi::PyUnicode_Type, #checkfunction=ffi::PyUnicode_Check); +pyobject_native_type_core!(PyString, pyobject_native_static_type_object!(ffi::PyUnicode_Type), #checkfunction=ffi::PyUnicode_Check); impl PyString { /// Creates a new Python string object. diff --git a/src/types/traceback.rs b/src/types/traceback.rs index 82916558..36a04e59 100644 --- a/src/types/traceback.rs +++ b/src/types/traceback.rs @@ -9,7 +9,7 @@ pub struct PyTraceback(PyAny); pyobject_native_type_core!( PyTraceback, - ffi::PyTraceBack_Type, + pyobject_native_static_type_object!(ffi::PyTraceBack_Type), #checkfunction=ffi::PyTraceBack_Check ); diff --git a/src/types/tuple.rs b/src/types/tuple.rs index 5f00b93d..14c32a27 100644 --- a/src/types/tuple.rs +++ b/src/types/tuple.rs @@ -53,7 +53,7 @@ fn new_from_iter( #[repr(transparent)] pub struct PyTuple(PyAny); -pyobject_native_type_core!(PyTuple, ffi::PyTuple_Type, #checkfunction=ffi::PyTuple_Check); +pyobject_native_type_core!(PyTuple, pyobject_native_static_type_object!(ffi::PyTuple_Type), #checkfunction=ffi::PyTuple_Check); impl PyTuple { /// Constructs a new tuple with the given elements. diff --git a/src/types/typeobject.rs b/src/types/typeobject.rs index ca4a5cdb..105d6ef0 100644 --- a/src/types/typeobject.rs +++ b/src/types/typeobject.rs @@ -5,7 +5,7 @@ use crate::{ffi, AsPyPointer, PyAny, PyTypeInfo, Python}; #[repr(transparent)] pub struct PyType(PyAny); -pyobject_native_type_core!(PyType, ffi::PyType_Type, #checkfunction=ffi::PyType_Check); +pyobject_native_type_core!(PyType, pyobject_native_static_type_object!(ffi::PyType_Type), #checkfunction=ffi::PyType_Check); impl PyType { /// Creates a new type object.