pymethods: cleanup macros generating setdel slots
This commit is contained in:
parent
92e2156161
commit
75c0116f6a
|
@ -108,229 +108,148 @@ impl<T> PyClassCallImpl<T> for &'_ PyClassImplCollector<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait PyClass__setattr__SlotFragment<T>: Sized {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn __setattr__implemented(self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn __setattr__(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
_value: NonNull<ffi::PyObject>,
|
||||
) -> PyResult<()> {
|
||||
Err(PyAttributeError::new_err("can't set attribute"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyClass__setattr__SlotFragment<T> for &'_ PyClassImplCollector<T> {}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait PyClass__delattr__SlotFragment<T>: Sized {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn __delattr__implemented(self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn __delattr__(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
) -> PyResult<()> {
|
||||
Err(PyAttributeError::new_err("can't delete attribute"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyClass__delattr__SlotFragment<T> for &'_ PyClassImplCollector<T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! generate_pyclass_setattr_slot {
|
||||
($cls:ty) => {{
|
||||
use ::std::option::Option::*;
|
||||
use $crate::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
if collector.__setattr__implemented() || collector.__delattr__implemented() {
|
||||
unsafe extern "C" fn __wrap(
|
||||
_slf: *mut $crate::ffi::PyObject,
|
||||
attr: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
) -> ::std::os::raw::c_int {
|
||||
$crate::callback::handle_panic(|py| {
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
$crate::callback::convert(py, {
|
||||
if let Some(value) = ::std::ptr::NonNull::new(value) {
|
||||
collector.__setattr__(_slf, attr, value)
|
||||
} else {
|
||||
collector.__delattr__(_slf, attr)
|
||||
}
|
||||
})
|
||||
})
|
||||
macro_rules! slot_fragment_trait {
|
||||
($trait_name:ident, $implemented_name:ident, $($default_method:tt)*) => {
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait $trait_name<T>: Sized {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn $implemented_name(self) -> bool {
|
||||
false
|
||||
}
|
||||
Some($crate::ffi::PyType_Slot {
|
||||
slot: $crate::ffi::Py_tp_setattro,
|
||||
pfunc: __wrap as $crate::ffi::setattrofunc as _,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
||||
$($default_method)*
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait PyClass__set__SlotFragment<T>: Sized {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn __set__implemented(self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn __set__(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
_value: NonNull<ffi::PyObject>,
|
||||
) -> PyResult<()> {
|
||||
Err(PyNotImplementedError::new_err("can't set descriptor"))
|
||||
impl<T> $trait_name<T> for &'_ PyClassImplCollector<T> {}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyClass__set__SlotFragment<T> for &'_ PyClassImplCollector<T> {}
|
||||
/// Macro which expands to three items
|
||||
/// - Trait for a __setitem__ dunder
|
||||
/// - Trait for the corresponding __delitem__ dunder
|
||||
/// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders
|
||||
macro_rules! define_pyclass_setattr_slot {
|
||||
(
|
||||
$set_trait:ident,
|
||||
$del_trait:ident,
|
||||
$set_implemented:ident,
|
||||
$del_implemented:ident,
|
||||
$set:ident,
|
||||
$del:ident,
|
||||
$set_error:expr,
|
||||
$del_error:expr,
|
||||
$generate_macro:ident,
|
||||
$slot:ident,
|
||||
$func_ty:ident,
|
||||
) => {
|
||||
slot_fragment_trait! {
|
||||
$set_trait,
|
||||
$set_implemented,
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait PyClass__delete__SlotFragment<T>: Sized {
|
||||
#[allow(non_snake_case)]
|
||||
#[inline]
|
||||
fn __delete__implemented(self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn __delete__(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
) -> PyResult<()> {
|
||||
Err(PyNotImplementedError::new_err("can't delete descriptor"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyClass__delete__SlotFragment<T> for &'_ PyClassImplCollector<T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! generate_pyclass_setdescr_slot {
|
||||
($cls:ty) => {{
|
||||
use ::std::option::Option::*;
|
||||
use $crate::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
if collector.__set__implemented() || collector.__delete__implemented() {
|
||||
unsafe extern "C" fn __wrap(
|
||||
_slf: *mut $crate::ffi::PyObject,
|
||||
attr: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
) -> ::std::os::raw::c_int {
|
||||
$crate::callback::handle_panic(|py| {
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
$crate::callback::convert(py, {
|
||||
if let Some(value) = ::std::ptr::NonNull::new(value) {
|
||||
collector.__set__(_slf, attr, value)
|
||||
} else {
|
||||
collector.__delete__(_slf, attr)
|
||||
}
|
||||
})
|
||||
})
|
||||
/// # Safety: _slf and _attr must be valid non-null Python objects
|
||||
#[inline]
|
||||
unsafe fn $set(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
_value: NonNull<ffi::PyObject>,
|
||||
) -> PyResult<()> {
|
||||
$set_error
|
||||
}
|
||||
Some($crate::ffi::PyType_Slot {
|
||||
slot: $crate::ffi::Py_tp_descr_set,
|
||||
pfunc: __wrap as $crate::ffi::descrsetfunc as _,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait PyClass__setitem__SlotFragment<T>: Sized {
|
||||
#[inline]
|
||||
#[allow(non_snake_case)]
|
||||
fn __setitem__implemented(self) -> bool {
|
||||
false
|
||||
}
|
||||
slot_fragment_trait! {
|
||||
$del_trait,
|
||||
$del_implemented,
|
||||
|
||||
#[inline]
|
||||
unsafe fn __setitem__(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
_value: NonNull<ffi::PyObject>,
|
||||
) -> PyResult<()> {
|
||||
Err(PyNotImplementedError::new_err("can't set item"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyClass__setitem__SlotFragment<T> for &'_ PyClassImplCollector<T> {}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub trait PyClass__delitem__SlotFragment<T>: Sized {
|
||||
#[allow(non_snake_case)]
|
||||
#[inline]
|
||||
fn __delitem__implemented(self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn __delitem__(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
) -> PyResult<()> {
|
||||
Err(PyNotImplementedError::new_err("can't delete item"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyClass__delitem__SlotFragment<T> for &'_ PyClassImplCollector<T> {}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! generate_pyclass_setitem_slot {
|
||||
($cls:ty) => {{
|
||||
use ::std::option::Option::*;
|
||||
use $crate::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
if collector.__setitem__implemented() || collector.__delitem__implemented() {
|
||||
unsafe extern "C" fn __wrap(
|
||||
_slf: *mut $crate::ffi::PyObject,
|
||||
attr: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
) -> ::std::os::raw::c_int {
|
||||
$crate::callback::handle_panic(|py| {
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
$crate::callback::convert(py, {
|
||||
if let Some(value) = ::std::ptr::NonNull::new(value) {
|
||||
collector.__setitem__(_slf, attr, value)
|
||||
} else {
|
||||
collector.__delitem__(_slf, attr)
|
||||
}
|
||||
})
|
||||
})
|
||||
/// # Safety: _slf and _attr must be valid non-null Python objects
|
||||
#[inline]
|
||||
unsafe fn $del(
|
||||
self,
|
||||
_slf: *mut ffi::PyObject,
|
||||
_attr: *mut ffi::PyObject,
|
||||
) -> PyResult<()> {
|
||||
$del_error
|
||||
}
|
||||
Some($crate::ffi::PyType_Slot {
|
||||
slot: $crate::ffi::Py_mp_ass_subscript,
|
||||
pfunc: __wrap as $crate::ffi::objobjargproc as _,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! $generate_macro {
|
||||
($cls:ty) => {{
|
||||
use ::std::option::Option::*;
|
||||
use $crate::class::impl_::*;
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
if collector.$set_implemented() || collector.$del_implemented() {
|
||||
unsafe extern "C" fn __wrap(
|
||||
_slf: *mut $crate::ffi::PyObject,
|
||||
attr: *mut $crate::ffi::PyObject,
|
||||
value: *mut $crate::ffi::PyObject,
|
||||
) -> ::std::os::raw::c_int {
|
||||
$crate::callback::handle_panic(|py| {
|
||||
let collector = PyClassImplCollector::<$cls>::new();
|
||||
$crate::callback::convert(py, {
|
||||
if let Some(value) = ::std::ptr::NonNull::new(value) {
|
||||
collector.$set(_slf, attr, value)
|
||||
} else {
|
||||
collector.$del(_slf, attr)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
Some($crate::ffi::PyType_Slot {
|
||||
slot: $crate::ffi::$slot,
|
||||
pfunc: __wrap as $crate::ffi::$func_ty as _,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_pyclass_setattr_slot! {
|
||||
PyClass__setattr__SlotFragment,
|
||||
PyClass__delattr__SlotFragment,
|
||||
__setattr__implemented,
|
||||
__delattr__implemented,
|
||||
__setattr__,
|
||||
__delattr__,
|
||||
Err(PyAttributeError::new_err("can't set attribute")),
|
||||
Err(PyAttributeError::new_err("can't delete attribute")),
|
||||
generate_pyclass_setattr_slot,
|
||||
Py_tp_setattro,
|
||||
setattrofunc,
|
||||
}
|
||||
|
||||
define_pyclass_setattr_slot! {
|
||||
PyClass__set__SlotFragment,
|
||||
PyClass__delete__SlotFragment,
|
||||
__set__implemented,
|
||||
__delete__implemented,
|
||||
__set__,
|
||||
__delete__,
|
||||
Err(PyNotImplementedError::new_err("can't set descriptor")),
|
||||
Err(PyNotImplementedError::new_err("can't delete descriptor")),
|
||||
generate_pyclass_setdescr_slot,
|
||||
Py_tp_descr_set,
|
||||
descrsetfunc,
|
||||
}
|
||||
|
||||
define_pyclass_setattr_slot! {
|
||||
PyClass__setitem__SlotFragment,
|
||||
PyClass__delitem__SlotFragment,
|
||||
__setitem__implemented,
|
||||
__delitem__implemented,
|
||||
__setitem__,
|
||||
__delitem__,
|
||||
Err(PyNotImplementedError::new_err("can't set item")),
|
||||
Err(PyNotImplementedError::new_err("can't delete item")),
|
||||
generate_pyclass_setitem_slot,
|
||||
Py_mp_ass_subscript,
|
||||
objobjargproc,
|
||||
}
|
||||
|
||||
pub trait PyClassAllocImpl<T> {
|
||||
|
|
Loading…
Reference in New Issue