Skip to content

Commit eb8ff15

Browse files
committed
Renew PyProtoMethods for new ABI3-based type construction
1 parent f74b649 commit eb8ff15

11 files changed

+850
-871
lines changed

src/class/basic.rs

Lines changed: 76 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -133,94 +133,109 @@ pub trait PyObjectRichcmpProtocol<'p>: PyObjectProtocol<'p> {
133133
type Result: IntoPyCallbackOutput<PyObject>;
134134
}
135135

136-
/// All FFI functions for basic protocols.
137-
#[derive(Default)]
138-
pub struct PyObjectMethods {
139-
pub tp_str: Option<ffi::reprfunc>,
140-
pub tp_repr: Option<ffi::reprfunc>,
141-
pub tp_hash: Option<ffi::hashfunc>,
142-
pub tp_getattro: Option<ffi::getattrofunc>,
143-
pub tp_richcompare: Option<ffi::richcmpfunc>,
144-
pub tp_setattro: Option<ffi::setattrofunc>,
145-
pub nb_bool: Option<ffi::inquiry>,
146-
}
147-
136+
/// Extension trait for proc-macro backend.
148137
#[doc(hidden)]
149-
impl PyObjectMethods {
150-
// Set functions used by `#[pyproto]`.
151-
pub fn set_str<T>(&mut self)
138+
pub trait PyBasicSlots {
139+
fn get_str() -> ffi::PyType_Slot
152140
where
153-
T: for<'p> PyObjectStrProtocol<'p>,
141+
Self: for<'p> PyObjectStrProtocol<'p>,
154142
{
155-
self.tp_str = py_unary_func!(PyObjectStrProtocol, T::__str__);
143+
ffi::PyType_Slot {
144+
slot: ffi::Py_tp_str,
145+
pfunc: py_unary_func!(PyObjectStrProtocol, Self::__str__) as _,
146+
}
156147
}
157-
pub fn set_repr<T>(&mut self)
148+
149+
fn get_repr() -> ffi::PyType_Slot
158150
where
159-
T: for<'p> PyObjectReprProtocol<'p>,
151+
Self: for<'p> PyObjectReprProtocol<'p>,
160152
{
161-
self.tp_repr = py_unary_func!(PyObjectReprProtocol, T::__repr__);
153+
ffi::PyType_Slot {
154+
slot: ffi::Py_tp_repr,
155+
pfunc: py_unary_func!(PyObjectReprProtocol, Self::__repr__) as _,
156+
}
162157
}
163-
pub fn set_hash<T>(&mut self)
158+
159+
fn get_hash() -> ffi::PyType_Slot
164160
where
165-
T: for<'p> PyObjectHashProtocol<'p>,
161+
Self: for<'p> PyObjectHashProtocol<'p>,
166162
{
167-
self.tp_hash = py_unary_func!(PyObjectHashProtocol, T::__hash__, ffi::Py_hash_t);
163+
ffi::PyType_Slot {
164+
slot: ffi::Py_tp_hash,
165+
pfunc: py_unary_func!(PyObjectHashProtocol, Self::__hash__, ffi::Py_hash_t) as _,
166+
}
168167
}
169-
pub fn set_getattr<T>(&mut self)
168+
169+
fn get_getattr() -> ffi::PyType_Slot
170170
where
171-
T: for<'p> PyObjectGetAttrProtocol<'p>,
171+
Self: for<'p> PyObjectGetAttrProtocol<'p>,
172172
{
173-
self.tp_getattro = tp_getattro::<T>();
173+
ffi::PyType_Slot {
174+
slot: ffi::Py_tp_getattro,
175+
pfunc: tp_getattro::<Self>() as _,
176+
}
174177
}
175-
pub fn set_richcompare<T>(&mut self)
178+
179+
fn get_richcompare() -> ffi::PyType_Slot
176180
where
177-
T: for<'p> PyObjectRichcmpProtocol<'p>,
181+
Self: for<'p> PyObjectRichcmpProtocol<'p>,
178182
{
179-
self.tp_richcompare = tp_richcompare::<T>();
183+
ffi::PyType_Slot {
184+
slot: ffi::Py_tp_getattro,
185+
pfunc: tp_richcompare::<Self>() as _,
186+
}
180187
}
181-
pub fn set_setattr<T>(&mut self)
188+
189+
fn get_setattr() -> ffi::PyType_Slot
182190
where
183-
T: for<'p> PyObjectSetAttrProtocol<'p>,
191+
Self: for<'p> PyObjectSetAttrProtocol<'p>,
184192
{
185-
self.tp_setattro = py_func_set!(PyObjectSetAttrProtocol, T, __setattr__);
193+
ffi::PyType_Slot {
194+
slot: ffi::Py_tp_setattro,
195+
pfunc: py_func_set!(PyObjectSetAttrProtocol, Self::__setattr__) as _,
196+
}
186197
}
187-
pub fn set_delattr<T>(&mut self)
198+
199+
fn get_delattr() -> ffi::PyType_Slot
188200
where
189-
T: for<'p> PyObjectDelAttrProtocol<'p>,
201+
Self: for<'p> PyObjectDelAttrProtocol<'p>,
190202
{
191-
self.tp_setattro = py_func_del!(PyObjectDelAttrProtocol, T, __delattr__);
203+
ffi::PyType_Slot {
204+
slot: ffi::Py_tp_setattro,
205+
pfunc: py_func_del!(PyObjectDelAttrProtocol, Self::__delattr__) as _,
206+
}
192207
}
193-
pub fn set_setdelattr<T>(&mut self)
208+
209+
fn get_setdelattr() -> ffi::PyType_Slot
194210
where
195-
T: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
211+
Self: for<'p> PyObjectSetAttrProtocol<'p> + for<'p> PyObjectDelAttrProtocol<'p>,
196212
{
197-
self.tp_setattro = py_func_set_del!(
198-
PyObjectSetAttrProtocol,
199-
PyObjectDelAttrProtocol,
200-
T,
201-
__setattr__,
202-
__delattr__
203-
)
213+
ffi::PyType_Slot {
214+
slot: ffi::Py_tp_setattro,
215+
pfunc: py_func_set_del!(
216+
PyObjectSetAttrProtocol,
217+
PyObjectDelAttrProtocol,
218+
Self,
219+
__setattr__,
220+
__delattr__
221+
) as _,
222+
}
204223
}
205-
pub fn set_bool<T>(&mut self)
224+
225+
fn get_bool() -> ffi::PyType_Slot
206226
where
207-
T: for<'p> PyObjectBoolProtocol<'p>,
227+
Self: for<'p> PyObjectBoolProtocol<'p>,
208228
{
209-
self.nb_bool = py_unary_func!(PyObjectBoolProtocol, T::__bool__, c_int);
210-
}
211-
212-
pub(crate) fn update_slots(&self, slots: &mut crate::pyclass::TypeSlots) {
213-
slots.maybe_push(ffi::Py_tp_str, self.tp_str.map(|v| v as _));
214-
slots.maybe_push(ffi::Py_tp_repr, self.tp_repr.map(|v| v as _));
215-
slots.maybe_push(ffi::Py_tp_hash, self.tp_hash.map(|v| v as _));
216-
slots.maybe_push(ffi::Py_tp_getattro, self.tp_getattro.map(|v| v as _));
217-
slots.maybe_push(ffi::Py_tp_richcompare, self.tp_richcompare.map(|v| v as _));
218-
slots.maybe_push(ffi::Py_tp_setattro, self.tp_setattro.map(|v| v as _));
219-
slots.maybe_push(ffi::Py_nb_bool, self.nb_bool.map(|v| v as _));
229+
ffi::PyType_Slot {
230+
slot: ffi::Py_nb_bool,
231+
pfunc: py_unary_func!(PyObjectBoolProtocol, Self::__bool__, c_int) as _,
232+
}
220233
}
221234
}
222235

223-
fn tp_getattro<T>() -> Option<ffi::binaryfunc>
236+
impl<'p, T> PyBasicSlots for T where T: PyObjectProtocol<'p> {}
237+
238+
fn tp_getattro<T>() -> ffi::binaryfunc
224239
where
225240
T: for<'p> PyObjectGetAttrProtocol<'p>,
226241
{
@@ -247,10 +262,10 @@ where
247262
call_ref!(slf, __getattr__, arg).convert(py)
248263
})
249264
}
250-
Some(wrap::<T>)
265+
wrap::<T>
251266
}
252267

253-
fn tp_richcompare<T>() -> Option<ffi::richcmpfunc>
268+
fn tp_richcompare<T>() -> ffi::richcmpfunc
254269
where
255270
T: for<'p> PyObjectRichcmpProtocol<'p>,
256271
{
@@ -283,5 +298,5 @@ where
283298
slf.try_borrow()?.__richcmp__(arg, op).convert(py)
284299
})
285300
}
286-
Some(wrap::<T>)
301+
wrap::<T>
287302
}

src/class/descr.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use crate::callback::IntoPyCallbackOutput;
99
use crate::types::PyAny;
1010
use crate::{ffi, FromPyObject, PyClass, PyObject};
11-
use std::os::raw::c_int;
1211

1312
/// Descriptor interface
1413
#[allow(unused_variables)]
@@ -70,29 +69,28 @@ pub trait PyDescrSetNameProtocol<'p>: PyDescrProtocol<'p> {
7069
type Result: IntoPyCallbackOutput<()>;
7170
}
7271

73-
/// All FFI functions for description protocols.
74-
#[derive(Default)]
75-
pub struct PyDescrMethods {
76-
pub tp_descr_get: Option<ffi::descrgetfunc>,
77-
pub tp_descr_set: Option<ffi::descrsetfunc>,
78-
}
79-
72+
/// Extension trait for our proc-macro backend.
8073
#[doc(hidden)]
81-
impl PyDescrMethods {
82-
pub fn set_descr_get<T>(&mut self)
74+
pub trait PyDescrSlots {
75+
fn get_descr_get() -> ffi::PyType_Slot
8376
where
84-
T: for<'p> PyDescrGetProtocol<'p>,
77+
Self: for<'p> PyDescrGetProtocol<'p>,
8578
{
86-
self.tp_descr_get = py_ternarys_func!(PyDescrGetProtocol, T::__get__);
79+
ffi::PyType_Slot {
80+
slot: ffi::Py_tp_descr_get,
81+
pfunc: py_ternarys_func!(PyDescrGetProtocol, Self::__get__) as _,
82+
}
8783
}
88-
pub fn set_descr_set<T>(&mut self)
84+
85+
fn get_descr_set() -> ffi::PyType_Slot
8986
where
90-
T: for<'p> PyDescrSetProtocol<'p>,
87+
Self: for<'p> PyDescrSetProtocol<'p>,
9188
{
92-
self.tp_descr_set = py_ternarys_func!(PyDescrSetProtocol, T::__set__, c_int);
93-
}
94-
pub(crate) fn update_slots(&self, slots: &mut crate::pyclass::TypeSlots) {
95-
slots.maybe_push(ffi::Py_tp_descr_get, self.tp_descr_get.map(|v| v as _));
96-
slots.maybe_push(ffi::Py_tp_descr_set, self.tp_descr_set.map(|v| v as _));
89+
ffi::PyType_Slot {
90+
slot: ffi::Py_tp_descr_set,
91+
pfunc: py_ternarys_func!(PyDescrSetProtocol, Self::__set__) as _,
92+
}
9793
}
9894
}
95+
96+
impl<'p, T> PyDescrSlots for T where T: PyDescrProtocol<'p> {}

src/class/gc.rs

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,31 @@ pub trait PyGCProtocol<'p>: PyClass {
1818
pub trait PyGCTraverseProtocol<'p>: PyGCProtocol<'p> {}
1919
pub trait PyGCClearProtocol<'p>: PyGCProtocol<'p> {}
2020

21-
/// All FFI functions for gc protocols.
22-
#[derive(Default)]
23-
pub struct PyGCMethods {
24-
pub tp_traverse: Option<ffi::traverseproc>,
25-
pub tp_clear: Option<ffi::inquiry>,
26-
}
27-
21+
/// Extension trait for proc-macro backend.
2822
#[doc(hidden)]
29-
impl PyGCMethods {
30-
pub(crate) fn update_slots(&self, slots: &mut crate::pyclass::TypeSlots) {
31-
slots.maybe_push(ffi::Py_tp_traverse, self.tp_traverse.map(|v| v as _));
32-
slots.maybe_push(ffi::Py_tp_clear, self.tp_clear.map(|v| v as _));
33-
}
34-
35-
pub fn set_traverse<T>(&mut self)
23+
pub trait PyGCSlots {
24+
fn get_traverse() -> ffi::PyType_Slot
3625
where
37-
T: for<'p> PyGCTraverseProtocol<'p>,
26+
Self: for<'p> PyGCTraverseProtocol<'p>,
3827
{
39-
self.tp_traverse = tp_traverse::<T>();
28+
ffi::PyType_Slot {
29+
slot: ffi::Py_tp_traverse,
30+
pfunc: tp_traverse::<Self>() as _,
31+
}
4032
}
41-
42-
pub fn set_clear<T>(&mut self)
33+
fn get_clear() -> ffi::PyType_Slot
4334
where
44-
T: for<'p> PyGCClearProtocol<'p>,
35+
Self: for<'p> PyGCClearProtocol<'p>,
4536
{
46-
self.tp_clear = tp_clear::<T>();
37+
ffi::PyType_Slot {
38+
slot: ffi::Py_tp_clear,
39+
pfunc: tp_clear::<Self>() as _,
40+
}
4741
}
4842
}
4943

44+
impl<'p, T> PyGCSlots for T where T: PyGCProtocol<'p> {}
45+
5046
/// Object visitor for GC.
5147
#[derive(Clone)]
5248
pub struct PyVisit<'p> {
@@ -73,7 +69,7 @@ impl<'p> PyVisit<'p> {
7369
}
7470
}
7571

76-
fn tp_traverse<T>() -> Option<ffi::traverseproc>
72+
fn tp_traverse<T>() -> ffi::traverseproc
7773
where
7874
T: for<'p> PyGCTraverseProtocol<'p>,
7975
{
@@ -105,10 +101,10 @@ where
105101
}
106102
}
107103

108-
Some(tp_traverse::<T>)
104+
tp_traverse::<T>
109105
}
110106

111-
fn tp_clear<T>() -> Option<ffi::inquiry>
107+
fn tp_clear<T>() -> ffi::inquiry
112108
where
113109
T: for<'p> PyGCClearProtocol<'p>,
114110
{
@@ -123,5 +119,5 @@ where
123119
slf.borrow_mut().__clear__();
124120
0
125121
}
126-
Some(tp_clear::<T>)
122+
tp_clear::<T>
127123
}

src/class/iter.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,32 +71,31 @@ pub trait PyIterNextProtocol<'p>: PyIterProtocol<'p> {
7171
type Result: IntoPyCallbackOutput<PyIterNextOutput>;
7272
}
7373

74-
#[derive(Default)]
75-
pub struct PyIterMethods {
76-
pub tp_iter: Option<ffi::getiterfunc>,
77-
pub tp_iternext: Option<ffi::iternextfunc>,
78-
}
79-
74+
/// Extension trait for proc-macro backend.
8075
#[doc(hidden)]
81-
impl PyIterMethods {
82-
pub fn set_iter<T>(&mut self)
76+
pub trait PyIterSlots {
77+
fn get_iter() -> ffi::PyType_Slot
8378
where
84-
T: for<'p> PyIterIterProtocol<'p>,
79+
Self: for<'p> PyIterIterProtocol<'p>,
8580
{
86-
self.tp_iter = py_unarys_func!(PyIterIterProtocol, T::__iter__);
81+
ffi::PyType_Slot {
82+
slot: ffi::Py_tp_iter,
83+
pfunc: py_unarys_func!(PyIterIterProtocol, Self::__iter__) as _,
84+
}
8785
}
88-
pub fn set_iternext<T>(&mut self)
86+
fn get_iternext() -> ffi::PyType_Slot
8987
where
90-
T: for<'p> PyIterNextProtocol<'p>,
88+
Self: for<'p> PyIterNextProtocol<'p>,
9189
{
92-
self.tp_iternext = py_unarys_func!(PyIterNextProtocol, T::__next__);
93-
}
94-
pub(crate) fn update_slots(&self, slots: &mut crate::pyclass::TypeSlots) {
95-
slots.maybe_push(ffi::Py_tp_iter, self.tp_iter.map(|v| v as _));
96-
slots.maybe_push(ffi::Py_tp_iternext, self.tp_iternext.map(|v| v as _));
90+
ffi::PyType_Slot {
91+
slot: ffi::Py_tp_iternext,
92+
pfunc: py_unarys_func!(PyIterNextProtocol, Self::__next__) as _,
93+
}
9794
}
9895
}
9996

97+
impl<'p, T> PyIterSlots for T where T: PyIterProtocol<'p> {}
98+
10099
/// Output of `__next__` which can either `yield` the next value in the iteration, or
101100
/// `return` a value to raise `StopIteration` in Python.
102101
///

0 commit comments

Comments
 (0)