pyo3_derive_backend/
defs.rs

1// Copyright (c) 2017-present PyO3 Project and Contributors
2use crate::proto_method::MethodProto;
3use std::collections::HashSet;
4
5/// Predicates for `#[pyproto]`.
6pub struct Proto {
7    /// The name of this protocol. E.g., Iter.
8    pub name: &'static str,
9    /// The name of slot table. E.g., PyIterMethods.
10    pub slot_table: &'static str,
11    /// The name of the setter used to set the table to `PyProtoRegistry`.
12    pub set_slot_table: &'static str,
13    /// All methods.
14    pub methods: &'static [MethodProto],
15    /// All methods registered as normal methods like `#[pymethods]`.
16    pub py_methods: &'static [PyMethod],
17    /// All methods registered to the slot table.
18    slot_setters: &'static [SlotSetter],
19}
20
21impl Proto {
22    pub(crate) fn get_proto<Q>(&self, query: Q) -> Option<&'static MethodProto>
23    where
24        Q: PartialEq<&'static str>,
25    {
26        self.methods.iter().find(|m| query == m.name())
27    }
28    pub(crate) fn get_method<Q>(&self, query: Q) -> Option<&'static PyMethod>
29    where
30        Q: PartialEq<&'static str>,
31    {
32        self.py_methods.iter().find(|m| query == m.name)
33    }
34    // Since the order matters, we expose only the iterator instead of the slice.
35    pub(crate) fn setters(
36        &self,
37        mut implemented_protocols: HashSet<String>,
38    ) -> impl Iterator<Item = &'static str> {
39        self.slot_setters.iter().filter_map(move |setter| {
40            // If any required method is not implemented, we skip this setter.
41            if setter
42                .proto_names
43                .iter()
44                .any(|name| !implemented_protocols.contains(*name))
45            {
46                return None;
47            }
48            // To use 'paired' setter in priority, we remove used protocols.
49            // For example, if set_add_radd is already used, we shouldn't use set_add and set_radd.
50            for name in setter.proto_names {
51                implemented_protocols.remove(*name);
52            }
53            Some(setter.set_function)
54        })
55    }
56}
57
58/// Represents a method registered as a normal method like `#[pymethods]`.
59// TODO(kngwyu): Currently only __radd__-like methods use METH_COEXIST to prevent
60// __add__-like methods from overriding them.
61pub struct PyMethod {
62    pub name: &'static str,
63    pub proto: &'static str,
64    pub can_coexist: bool,
65}
66
67impl PyMethod {
68    const fn coexist(name: &'static str, proto: &'static str) -> Self {
69        PyMethod {
70            name,
71            proto,
72            can_coexist: true,
73        }
74    }
75    const fn new(name: &'static str, proto: &'static str) -> Self {
76        PyMethod {
77            name,
78            proto,
79            can_coexist: false,
80        }
81    }
82}
83
84/// Represents a setter used to register a method to the method table.
85struct SlotSetter {
86    /// Protocols necessary for invoking this setter.
87    /// E.g., we need `__setattr__` and `__delattr__` for invoking `set_setdelitem`.
88    pub proto_names: &'static [&'static str],
89    /// The name of the setter called to the method table.
90    pub set_function: &'static str,
91}
92
93impl SlotSetter {
94    const fn new(names: &'static [&'static str], set_function: &'static str) -> Self {
95        SlotSetter {
96            proto_names: names,
97            set_function,
98        }
99    }
100}
101
102pub const OBJECT: Proto = Proto {
103    name: "Object",
104    slot_table: "pyo3::class::basic::PyObjectMethods",
105    set_slot_table: "set_basic_methods",
106    methods: &[
107        MethodProto::Binary {
108            name: "__getattr__",
109            arg: "Name",
110            proto: "pyo3::class::basic::PyObjectGetAttrProtocol",
111        },
112        MethodProto::Ternary {
113            name: "__setattr__",
114            arg1: "Name",
115            arg2: "Value",
116            proto: "pyo3::class::basic::PyObjectSetAttrProtocol",
117        },
118        MethodProto::Binary {
119            name: "__delattr__",
120            arg: "Name",
121            proto: "pyo3::class::basic::PyObjectDelAttrProtocol",
122        },
123        MethodProto::Unary {
124            name: "__str__",
125            proto: "pyo3::class::basic::PyObjectStrProtocol",
126        },
127        MethodProto::Unary {
128            name: "__repr__",
129            proto: "pyo3::class::basic::PyObjectReprProtocol",
130        },
131        MethodProto::Binary {
132            name: "__format__",
133            arg: "Format",
134            proto: "pyo3::class::basic::PyObjectFormatProtocol",
135        },
136        MethodProto::Unary {
137            name: "__hash__",
138            proto: "pyo3::class::basic::PyObjectHashProtocol",
139        },
140        MethodProto::Unary {
141            name: "__bytes__",
142            proto: "pyo3::class::basic::PyObjectBytesProtocol",
143        },
144        MethodProto::Binary {
145            name: "__richcmp__",
146            arg: "Other",
147            proto: "pyo3::class::basic::PyObjectRichcmpProtocol",
148        },
149        MethodProto::Unary {
150            name: "__bool__",
151            proto: "pyo3::class::basic::PyObjectBoolProtocol",
152        },
153    ],
154    py_methods: &[
155        PyMethod::new("__format__", "pyo3::class::basic::FormatProtocolImpl"),
156        PyMethod::new("__bytes__", "pyo3::class::basic::BytesProtocolImpl"),
157        PyMethod::new("__unicode__", "pyo3::class::basic::UnicodeProtocolImpl"),
158    ],
159    slot_setters: &[
160        SlotSetter::new(&["__str__"], "set_str"),
161        SlotSetter::new(&["__repr__"], "set_repr"),
162        SlotSetter::new(&["__hash__"], "set_hash"),
163        SlotSetter::new(&["__getattr__"], "set_getattr"),
164        SlotSetter::new(&["__richcmp__"], "set_richcompare"),
165        SlotSetter::new(&["__setattr__", "__delattr__"], "set_setdelattr"),
166        SlotSetter::new(&["__setattr__"], "set_setattr"),
167        SlotSetter::new(&["__delattr__"], "set_delattr"),
168        SlotSetter::new(&["__bool__"], "set_bool"),
169    ],
170};
171
172pub const ASYNC: Proto = Proto {
173    name: "Async",
174    slot_table: "pyo3::ffi::PyAsyncMethods",
175    set_slot_table: "set_async_methods",
176    methods: &[
177        MethodProto::UnaryS {
178            name: "__await__",
179            arg: "Receiver",
180            proto: "pyo3::class::pyasync::PyAsyncAwaitProtocol",
181        },
182        MethodProto::UnaryS {
183            name: "__aiter__",
184            arg: "Receiver",
185            proto: "pyo3::class::pyasync::PyAsyncAiterProtocol",
186        },
187        MethodProto::UnaryS {
188            name: "__anext__",
189            arg: "Receiver",
190            proto: "pyo3::class::pyasync::PyAsyncAnextProtocol",
191        },
192        MethodProto::Unary {
193            name: "__aenter__",
194            proto: "pyo3::class::pyasync::PyAsyncAenterProtocol",
195        },
196        MethodProto::Quaternary {
197            name: "__aexit__",
198            arg1: "ExcType",
199            arg2: "ExcValue",
200            arg3: "Traceback",
201            proto: "pyo3::class::pyasync::PyAsyncAexitProtocol",
202        },
203    ],
204    py_methods: &[
205        PyMethod::new(
206            "__aenter__",
207            "pyo3::class::pyasync::PyAsyncAenterProtocolImpl",
208        ),
209        PyMethod::new(
210            "__aexit__",
211            "pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
212        ),
213    ],
214    slot_setters: &[
215        SlotSetter::new(&["__await__"], "set_await"),
216        SlotSetter::new(&["__aiter__"], "set_aiter"),
217        SlotSetter::new(&["__anext__"], "set_anext"),
218    ],
219};
220
221pub const BUFFER: Proto = Proto {
222    name: "Buffer",
223    slot_table: "pyo3::ffi::PyBufferProcs",
224    set_slot_table: "set_buffer_methods",
225    methods: &[
226        MethodProto::Unary {
227            name: "bf_getbuffer",
228            proto: "pyo3::class::buffer::PyBufferGetBufferProtocol",
229        },
230        MethodProto::Unary {
231            name: "bf_releasebuffer",
232            proto: "pyo3::class::buffer::PyBufferReleaseBufferProtocol",
233        },
234    ],
235    py_methods: &[],
236    slot_setters: &[
237        SlotSetter::new(&["bf_getbuffer"], "set_getbuffer"),
238        SlotSetter::new(&["bf_releasebuffer"], "set_releasebuffer"),
239    ],
240};
241
242pub const CONTEXT: Proto = Proto {
243    name: "Context",
244    slot_table: "",
245    set_slot_table: "",
246    methods: &[
247        MethodProto::Unary {
248            name: "__enter__",
249            proto: "pyo3::class::context::PyContextEnterProtocol",
250        },
251        MethodProto::Quaternary {
252            name: "__exit__",
253            arg1: "ExcType",
254            arg2: "ExcValue",
255            arg3: "Traceback",
256            proto: "pyo3::class::context::PyContextExitProtocol",
257        },
258    ],
259    py_methods: &[
260        PyMethod::new(
261            "__enter__",
262            "pyo3::class::context::PyContextEnterProtocolImpl",
263        ),
264        PyMethod::new(
265            "__exit__",
266            "pyo3::class::context::PyContextExitProtocolImpl",
267        ),
268    ],
269    slot_setters: &[],
270};
271
272pub const GC: Proto = Proto {
273    name: "GC",
274    slot_table: "pyo3::class::gc::PyGCMethods",
275    set_slot_table: "set_gc_methods",
276    methods: &[
277        MethodProto::Free {
278            name: "__traverse__",
279            proto: "pyo3::class::gc::PyGCTraverseProtocol",
280        },
281        MethodProto::Free {
282            name: "__clear__",
283            proto: "pyo3::class::gc::PyGCClearProtocol",
284        },
285    ],
286    py_methods: &[],
287    slot_setters: &[
288        SlotSetter::new(&["__traverse__"], "set_traverse"),
289        SlotSetter::new(&["__clear__"], "set_clear"),
290    ],
291};
292
293pub const DESCR: Proto = Proto {
294    name: "Descriptor",
295    slot_table: "pyo3::class::descr::PyDescrMethods",
296    set_slot_table: "set_descr_methods",
297    methods: &[
298        MethodProto::TernaryS {
299            name: "__get__",
300            arg1: "Receiver",
301            arg2: "Inst",
302            arg3: "Owner",
303            proto: "pyo3::class::descr::PyDescrGetProtocol",
304        },
305        MethodProto::TernaryS {
306            name: "__set__",
307            arg1: "Receiver",
308            arg2: "Inst",
309            arg3: "Value",
310            proto: "pyo3::class::descr::PyDescrSetProtocol",
311        },
312        MethodProto::Binary {
313            name: "__det__",
314            arg: "Inst",
315            proto: "pyo3::class::descr::PyDescrDelProtocol",
316        },
317        MethodProto::Binary {
318            name: "__set_name__",
319            arg: "Inst",
320            proto: "pyo3::class::descr::PyDescrSetNameProtocol",
321        },
322    ],
323    py_methods: &[
324        PyMethod::new("__del__", "pyo3::class::context::PyDescrDelProtocolImpl"),
325        PyMethod::new(
326            "__set_name__",
327            "pyo3::class::context::PyDescrNameProtocolImpl",
328        ),
329    ],
330    slot_setters: &[
331        SlotSetter::new(&["__get__"], "set_descr_get"),
332        SlotSetter::new(&["__set__"], "set_descr_set"),
333    ],
334};
335
336pub const ITER: Proto = Proto {
337    name: "Iter",
338    slot_table: "pyo3::class::iter::PyIterMethods",
339    set_slot_table: "set_iter_methods",
340    py_methods: &[],
341    methods: &[
342        MethodProto::UnaryS {
343            name: "__iter__",
344            arg: "Receiver",
345            proto: "pyo3::class::iter::PyIterIterProtocol",
346        },
347        MethodProto::UnaryS {
348            name: "__next__",
349            arg: "Receiver",
350            proto: "pyo3::class::iter::PyIterNextProtocol",
351        },
352    ],
353    slot_setters: &[
354        SlotSetter::new(&["__iter__"], "set_iter"),
355        SlotSetter::new(&["__next__"], "set_iternext"),
356    ],
357};
358
359pub const MAPPING: Proto = Proto {
360    name: "Mapping",
361    slot_table: "pyo3::ffi::PyMappingMethods",
362    set_slot_table: "set_mapping_methods",
363    methods: &[
364        MethodProto::Unary {
365            name: "__len__",
366            proto: "pyo3::class::mapping::PyMappingLenProtocol",
367        },
368        MethodProto::Binary {
369            name: "__getitem__",
370            arg: "Key",
371            proto: "pyo3::class::mapping::PyMappingGetItemProtocol",
372        },
373        MethodProto::Ternary {
374            name: "__setitem__",
375            arg1: "Key",
376            arg2: "Value",
377            proto: "pyo3::class::mapping::PyMappingSetItemProtocol",
378        },
379        MethodProto::Binary {
380            name: "__delitem__",
381            arg: "Key",
382            proto: "pyo3::class::mapping::PyMappingDelItemProtocol",
383        },
384        MethodProto::Unary {
385            name: "__reversed__",
386            proto: "pyo3::class::mapping::PyMappingReversedProtocol",
387        },
388    ],
389    py_methods: &[PyMethod::new(
390        "__reversed__",
391        "pyo3::class::mapping::PyMappingReversedProtocolImpl",
392    )],
393    slot_setters: &[
394        SlotSetter::new(&["__len__"], "set_length"),
395        SlotSetter::new(&["__getitem__"], "set_getitem"),
396        SlotSetter::new(&["__setitem__", "__delitem__"], "set_setdelitem"),
397        SlotSetter::new(&["__setitem__"], "set_setitem"),
398        SlotSetter::new(&["__delitem__"], "set_delitem"),
399    ],
400};
401
402pub const SEQ: Proto = Proto {
403    name: "Sequence",
404    slot_table: "pyo3::ffi::PySequenceMethods",
405    set_slot_table: "set_sequence_methods",
406    methods: &[
407        MethodProto::Unary {
408            name: "__len__",
409            proto: "pyo3::class::sequence::PySequenceLenProtocol",
410        },
411        MethodProto::Binary {
412            name: "__getitem__",
413            arg: "Index",
414            proto: "pyo3::class::sequence::PySequenceGetItemProtocol",
415        },
416        MethodProto::Ternary {
417            name: "__setitem__",
418            arg1: "Index",
419            arg2: "Value",
420            proto: "pyo3::class::sequence::PySequenceSetItemProtocol",
421        },
422        MethodProto::Binary {
423            name: "__delitem__",
424            arg: "Index",
425            proto: "pyo3::class::sequence::PySequenceDelItemProtocol",
426        },
427        MethodProto::Binary {
428            name: "__contains__",
429            arg: "Item",
430            proto: "pyo3::class::sequence::PySequenceContainsProtocol",
431        },
432        MethodProto::Binary {
433            name: "__concat__",
434            arg: "Other",
435            proto: "pyo3::class::sequence::PySequenceConcatProtocol",
436        },
437        MethodProto::Binary {
438            name: "__repeat__",
439            arg: "Index",
440            proto: "pyo3::class::sequence::PySequenceRepeatProtocol",
441        },
442        MethodProto::Binary {
443            name: "__inplace_concat__",
444            arg: "Other",
445            proto: "pyo3::class::sequence::PySequenceInplaceConcatProtocol",
446        },
447        MethodProto::Binary {
448            name: "__inplace_repeat__",
449            arg: "Index",
450            proto: "pyo3::class::sequence::PySequenceInplaceRepeatProtocol",
451        },
452    ],
453    py_methods: &[],
454    slot_setters: &[
455        SlotSetter::new(&["__len__"], "set_len"),
456        SlotSetter::new(&["__concat__"], "set_concat"),
457        SlotSetter::new(&["__repeat__"], "set_repeat"),
458        SlotSetter::new(&["__getitem__"], "set_getitem"),
459        SlotSetter::new(&["__setitem__", "__delitem__"], "set_setdelitem"),
460        SlotSetter::new(&["__setitem__"], "set_setitem"),
461        SlotSetter::new(&["__delitem__"], "set_delitem"),
462        SlotSetter::new(&["__contains__"], "set_contains"),
463        SlotSetter::new(&["__inplace_concat__"], "set_inplace_concat"),
464        SlotSetter::new(&["__inplace_repeat__"], "set_inplace_repeat"),
465    ],
466};
467
468pub const NUM: Proto = Proto {
469    name: "Number",
470    slot_table: "pyo3::ffi::PyNumberMethods",
471    set_slot_table: "set_number_methods",
472    methods: &[
473        MethodProto::BinaryS {
474            name: "__add__",
475            arg1: "Left",
476            arg2: "Right",
477            proto: "pyo3::class::number::PyNumberAddProtocol",
478        },
479        MethodProto::BinaryS {
480            name: "__sub__",
481            arg1: "Left",
482            arg2: "Right",
483            proto: "pyo3::class::number::PyNumberSubProtocol",
484        },
485        MethodProto::BinaryS {
486            name: "__mul__",
487            arg1: "Left",
488            arg2: "Right",
489            proto: "pyo3::class::number::PyNumberMulProtocol",
490        },
491        MethodProto::BinaryS {
492            name: "__matmul__",
493            arg1: "Left",
494            arg2: "Right",
495            proto: "pyo3::class::number::PyNumberMatmulProtocol",
496        },
497        MethodProto::BinaryS {
498            name: "__truediv__",
499            arg1: "Left",
500            arg2: "Right",
501            proto: "pyo3::class::number::PyNumberTruedivProtocol",
502        },
503        MethodProto::BinaryS {
504            name: "__floordiv__",
505            arg1: "Left",
506            arg2: "Right",
507            proto: "pyo3::class::number::PyNumberFloordivProtocol",
508        },
509        MethodProto::BinaryS {
510            name: "__mod__",
511            arg1: "Left",
512            arg2: "Right",
513            proto: "pyo3::class::number::PyNumberModProtocol",
514        },
515        MethodProto::BinaryS {
516            name: "__divmod__",
517            arg1: "Left",
518            arg2: "Right",
519            proto: "pyo3::class::number::PyNumberDivmodProtocol",
520        },
521        MethodProto::TernaryS {
522            name: "__pow__",
523            arg1: "Left",
524            arg2: "Right",
525            arg3: "Modulo",
526            proto: "pyo3::class::number::PyNumberPowProtocol",
527        },
528        MethodProto::BinaryS {
529            name: "__lshift__",
530            arg1: "Left",
531            arg2: "Right",
532            proto: "pyo3::class::number::PyNumberLShiftProtocol",
533        },
534        MethodProto::BinaryS {
535            name: "__rshift__",
536            arg1: "Left",
537            arg2: "Right",
538            proto: "pyo3::class::number::PyNumberRShiftProtocol",
539        },
540        MethodProto::BinaryS {
541            name: "__and__",
542            arg1: "Left",
543            arg2: "Right",
544            proto: "pyo3::class::number::PyNumberAndProtocol",
545        },
546        MethodProto::BinaryS {
547            name: "__xor__",
548            arg1: "Left",
549            arg2: "Right",
550            proto: "pyo3::class::number::PyNumberXorProtocol",
551        },
552        MethodProto::BinaryS {
553            name: "__or__",
554            arg1: "Left",
555            arg2: "Right",
556            proto: "pyo3::class::number::PyNumberOrProtocol",
557        },
558        MethodProto::Binary {
559            name: "__radd__",
560            arg: "Other",
561            proto: "pyo3::class::number::PyNumberRAddProtocol",
562        },
563        MethodProto::Binary {
564            name: "__rsub__",
565            arg: "Other",
566            proto: "pyo3::class::number::PyNumberRSubProtocol",
567        },
568        MethodProto::Binary {
569            name: "__rmul__",
570            arg: "Other",
571            proto: "pyo3::class::number::PyNumberRMulProtocol",
572        },
573        MethodProto::Binary {
574            name: "__rmatmul__",
575            arg: "Other",
576            proto: "pyo3::class::number::PyNumberRMatmulProtocol",
577        },
578        MethodProto::Binary {
579            name: "__rtruediv__",
580            arg: "Other",
581            proto: "pyo3::class::number::PyNumberRTruedivProtocol",
582        },
583        MethodProto::Binary {
584            name: "__rfloordiv__",
585            arg: "Other",
586            proto: "pyo3::class::number::PyNumberRFloordivProtocol",
587        },
588        MethodProto::Binary {
589            name: "__rmod__",
590            arg: "Other",
591            proto: "pyo3::class::number::PyNumberRModProtocol",
592        },
593        MethodProto::Binary {
594            name: "__rdivmod__",
595            arg: "Other",
596            proto: "pyo3::class::number::PyNumberRDivmodProtocol",
597        },
598        MethodProto::Ternary {
599            name: "__rpow__",
600            arg1: "Other",
601            arg2: "Modulo",
602            proto: "pyo3::class::number::PyNumberRPowProtocol",
603        },
604        MethodProto::Binary {
605            name: "__rlshift__",
606            arg: "Other",
607            proto: "pyo3::class::number::PyNumberRLShiftProtocol",
608        },
609        MethodProto::Binary {
610            name: "__rrshift__",
611            arg: "Other",
612            proto: "pyo3::class::number::PyNumberRRShiftProtocol",
613        },
614        MethodProto::Binary {
615            name: "__rand__",
616            arg: "Other",
617            proto: "pyo3::class::number::PyNumberRAndProtocol",
618        },
619        MethodProto::Binary {
620            name: "__rxor__",
621            arg: "Other",
622            proto: "pyo3::class::number::PyNumberRXorProtocol",
623        },
624        MethodProto::Binary {
625            name: "__ror__",
626            arg: "Other",
627            proto: "pyo3::class::number::PyNumberROrProtocol",
628        },
629        MethodProto::Binary {
630            name: "__iadd__",
631            arg: "Other",
632            proto: "pyo3::class::number::PyNumberIAddProtocol",
633        },
634        MethodProto::Binary {
635            name: "__isub__",
636            arg: "Other",
637            proto: "pyo3::class::number::PyNumberISubProtocol",
638        },
639        MethodProto::Binary {
640            name: "__imul__",
641            arg: "Other",
642            proto: "pyo3::class::number::PyNumberIMulProtocol",
643        },
644        MethodProto::Binary {
645            name: "__imatmul__",
646            arg: "Other",
647            proto: "pyo3::class::number::PyNumberIMatmulProtocol",
648        },
649        MethodProto::Binary {
650            name: "__itruediv__",
651            arg: "Other",
652            proto: "pyo3::class::number::PyNumberITruedivProtocol",
653        },
654        MethodProto::Binary {
655            name: "__ifloordiv__",
656            arg: "Other",
657            proto: "pyo3::class::number::PyNumberIFloordivProtocol",
658        },
659        MethodProto::Binary {
660            name: "__imod__",
661            arg: "Other",
662            proto: "pyo3::class::number::PyNumberIModProtocol",
663        },
664        MethodProto::Binary {
665            name: "__ipow__",
666            arg: "Other",
667            proto: "pyo3::class::number::PyNumberIPowProtocol",
668        },
669        MethodProto::Binary {
670            name: "__ilshift__",
671            arg: "Other",
672            proto: "pyo3::class::number::PyNumberILShiftProtocol",
673        },
674        MethodProto::Binary {
675            name: "__irshift__",
676            arg: "Other",
677            proto: "pyo3::class::number::PyNumberIRShiftProtocol",
678        },
679        MethodProto::Binary {
680            name: "__iand__",
681            arg: "Other",
682            proto: "pyo3::class::number::PyNumberIAndProtocol",
683        },
684        MethodProto::Binary {
685            name: "__ixor__",
686            arg: "Other",
687            proto: "pyo3::class::number::PyNumberIXorProtocol",
688        },
689        MethodProto::Binary {
690            name: "__ior__",
691            arg: "Other",
692            proto: "pyo3::class::number::PyNumberIOrProtocol",
693        },
694        MethodProto::Unary {
695            name: "__neg__",
696            proto: "pyo3::class::number::PyNumberNegProtocol",
697        },
698        MethodProto::Unary {
699            name: "__pos__",
700            proto: "pyo3::class::number::PyNumberPosProtocol",
701        },
702        MethodProto::Unary {
703            name: "__abs__",
704            proto: "pyo3::class::number::PyNumberAbsProtocol",
705        },
706        MethodProto::Unary {
707            name: "__invert__",
708            proto: "pyo3::class::number::PyNumberInvertProtocol",
709        },
710        MethodProto::Unary {
711            name: "__complex__",
712            proto: "pyo3::class::number::PyNumberComplexProtocol",
713        },
714        MethodProto::Unary {
715            name: "__int__",
716            proto: "pyo3::class::number::PyNumberIntProtocol",
717        },
718        MethodProto::Unary {
719            name: "__float__",
720            proto: "pyo3::class::number::PyNumberFloatProtocol",
721        },
722        MethodProto::Unary {
723            name: "__index__",
724            proto: "pyo3::class::number::PyNumberIndexProtocol",
725        },
726        MethodProto::Binary {
727            name: "__round__",
728            arg: "NDigits",
729            proto: "pyo3::class::number::PyNumberRoundProtocol",
730        },
731    ],
732    py_methods: &[
733        PyMethod::coexist("__radd__", "pyo3::class::number::PyNumberRAddProtocolImpl"),
734        PyMethod::coexist("__rsub__", "pyo3::class::number::PyNumberRSubProtocolImpl"),
735        PyMethod::coexist("__rmul__", "pyo3::class::number::PyNumberRMulProtocolImpl"),
736        PyMethod::coexist(
737            "__rmatmul__",
738            "pyo3::class::number::PyNumberRMatmulProtocolImpl",
739        ),
740        PyMethod::coexist(
741            "__rtruediv__",
742            "pyo3::class::number::PyNumberRTruedivProtocolImpl",
743        ),
744        PyMethod::coexist(
745            "__rfloordiv__",
746            "pyo3::class::number::PyNumberRFloordivProtocolImpl",
747        ),
748        PyMethod::coexist("__rmod__", "pyo3::class::number::PyNumberRModProtocolImpl"),
749        PyMethod::coexist(
750            "__rdivmod__",
751            "pyo3::class::number::PyNumberRDivmodProtocolImpl",
752        ),
753        PyMethod::coexist("__rpow__", "pyo3::class::number::PyNumberRPowProtocolImpl"),
754        PyMethod::coexist(
755            "__rlshift__",
756            "pyo3::class::number::PyNumberRLShiftProtocolImpl",
757        ),
758        PyMethod::coexist(
759            "__rrshift__",
760            "pyo3::class::number::PyNumberRRShiftProtocolImpl",
761        ),
762        PyMethod::coexist("__rand__", "pyo3::class::number::PyNumberRAndProtocolImpl"),
763        PyMethod::coexist("__rxor__", "pyo3::class::number::PyNumberRXorProtocolImpl"),
764        PyMethod::coexist("__ror__", "pyo3::class::number::PyNumberROrProtocolImpl"),
765        PyMethod::new(
766            "__complex__",
767            "pyo3::class::number::PyNumberComplexProtocolImpl",
768        ),
769        PyMethod::new(
770            "__round__",
771            "pyo3::class::number::PyNumberRoundProtocolImpl",
772        ),
773    ],
774    slot_setters: &[
775        SlotSetter::new(&["__add__", "__radd__"], "set_add_radd"),
776        SlotSetter::new(&["__add__"], "set_add"),
777        SlotSetter::new(&["__radd__"], "set_radd"),
778        SlotSetter::new(&["__sub__", "__rsub__"], "set_sub_rsub"),
779        SlotSetter::new(&["__sub__"], "set_sub"),
780        SlotSetter::new(&["__rsub__"], "set_rsub"),
781        SlotSetter::new(&["__mul__", "__rmul__"], "set_mul_rmul"),
782        SlotSetter::new(&["__mul__"], "set_mul"),
783        SlotSetter::new(&["__rmul__"], "set_rmul"),
784        SlotSetter::new(&["__mod__"], "set_mod"),
785        SlotSetter::new(&["__divmod__", "__rdivmod__"], "set_divmod_rdivmod"),
786        SlotSetter::new(&["__divmod__"], "set_divmod"),
787        SlotSetter::new(&["__rdivmod__"], "set_rdivmod"),
788        SlotSetter::new(&["__pow__", "__rpow__"], "set_pow_rpow"),
789        SlotSetter::new(&["__pow__"], "set_pow"),
790        SlotSetter::new(&["__rpow__"], "set_rpow"),
791        SlotSetter::new(&["__neg__"], "set_neg"),
792        SlotSetter::new(&["__pos__"], "set_pos"),
793        SlotSetter::new(&["__abs__"], "set_abs"),
794        SlotSetter::new(&["__invert__"], "set_invert"),
795        SlotSetter::new(&["__lshift__", "__rlshift__"], "set_lshift_rlshift"),
796        SlotSetter::new(&["__lshift__"], "set_lshift"),
797        SlotSetter::new(&["__rlshift__"], "set_rlshift"),
798        SlotSetter::new(&["__rshift__", "__rrshift__"], "set_rshift_rrshift"),
799        SlotSetter::new(&["__rshift__"], "set_rshift"),
800        SlotSetter::new(&["__rrshift__"], "set_rrshift"),
801        SlotSetter::new(&["__and__", "__rand__"], "set_and_rand"),
802        SlotSetter::new(&["__and__"], "set_and"),
803        SlotSetter::new(&["__rand__"], "set_rand"),
804        SlotSetter::new(&["__xor__", "__rxor__"], "set_xor_rxor"),
805        SlotSetter::new(&["__xor__"], "set_xor"),
806        SlotSetter::new(&["__rxor__"], "set_rxor"),
807        SlotSetter::new(&["__or__", "__ror__"], "set_or_ror"),
808        SlotSetter::new(&["__or__"], "set_or"),
809        SlotSetter::new(&["__ror__"], "set_ror"),
810        SlotSetter::new(&["__int__"], "set_int"),
811        SlotSetter::new(&["__float__"], "set_float"),
812        SlotSetter::new(&["__iadd__"], "set_iadd"),
813        SlotSetter::new(&["__isub__"], "set_isub"),
814        SlotSetter::new(&["__imul__"], "set_imul"),
815        SlotSetter::new(&["__imod__"], "set_imod"),
816        SlotSetter::new(&["__ipow__"], "set_ipow"),
817        SlotSetter::new(&["__ilshift__"], "set_ilshift"),
818        SlotSetter::new(&["__irshift__"], "set_irshift"),
819        SlotSetter::new(&["__iand__"], "set_iand"),
820        SlotSetter::new(&["__ixor__"], "set_ixor"),
821        SlotSetter::new(&["__ior__"], "set_ior"),
822        SlotSetter::new(&["__floordiv__", "__rfloordiv__"], "set_floordiv_rfloordiv"),
823        SlotSetter::new(&["__floordiv__"], "set_floordiv"),
824        SlotSetter::new(&["__rfloordiv__"], "set_rfloordiv"),
825        SlotSetter::new(&["__truediv__", "__rtruediv__"], "set_truediv_rtruediv"),
826        SlotSetter::new(&["__truediv__"], "set_truediv"),
827        SlotSetter::new(&["__rtruediv__"], "set_rtruediv"),
828        SlotSetter::new(&["__ifloordiv__"], "set_ifloordiv"),
829        SlotSetter::new(&["__itruediv__"], "set_itruediv"),
830        SlotSetter::new(&["__index__"], "set_index"),
831        SlotSetter::new(&["__matmul__", "__rmatmul__"], "set_matmul_rmatmul"),
832        SlotSetter::new(&["__matmul__"], "set_matmul"),
833        SlotSetter::new(&["__rmatmul__"], "set_rmatmul"),
834        SlotSetter::new(&["__imatmul__"], "set_imatmul"),
835    ],
836};