8
from . import PyrexTypes
9
from .Errors import error, warn_once
13
invisible = ['__cinit__', '__dealloc__', '__richcmp__',
14
'__nonzero__', '__bool__']
16
richcmp_special_methods = ['__eq__', '__ne__', '__lt__', '__gt__', '__le__', '__ge__']
57
'O': PyrexTypes.py_object_type,
58
'v': PyrexTypes.c_void_type,
59
'p': PyrexTypes.c_void_ptr_type,
60
'P': PyrexTypes.c_void_ptr_ptr_type,
61
'i': PyrexTypes.c_int_type,
62
'b': PyrexTypes.c_bint_type,
63
'I': PyrexTypes.c_int_ptr_type,
64
'l': PyrexTypes.c_long_type,
65
'f': PyrexTypes.c_float_type,
66
'd': PyrexTypes.c_double_type,
67
'h': PyrexTypes.c_py_hash_t_type,
68
'z': PyrexTypes.c_py_ssize_t_type,
69
'Z': PyrexTypes.c_py_ssize_t_ptr_type,
70
's': PyrexTypes.c_char_ptr_type,
71
'S': PyrexTypes.c_char_ptr_ptr_type,
72
'r': PyrexTypes.c_returncode_type,
73
'B': PyrexTypes.c_py_buffer_ptr_type,
74
'?': PyrexTypes.py_object_type
79
type_to_format_map = {type_: format_ for format_, type_ in format_map.items()}
95
def __init__(self, arg_format, ret_format, nogil=False):
96
self.has_dummy_arg = False
97
self.has_generic_args = False
98
self.optional_object_arg_count = 0
99
if arg_format[:1] == '-':
100
self.has_dummy_arg = True
101
arg_format = arg_format[1:]
102
if arg_format[-1:] == '*':
103
self.has_generic_args = True
104
arg_format = arg_format[:-1]
105
if arg_format[-1:] == '?':
106
self.optional_object_arg_count += 1
107
self.fixed_arg_format = arg_format
108
self.ret_format = ret_format
109
self.error_value = self.error_value_map.get(ret_format, None)
110
self.exception_check = ret_format != 'r' and self.error_value is not None
111
self.is_staticmethod = False
115
return '<Signature[%s(%s%s)]>' % (
117
', '.join(self.fixed_arg_format),
118
'*' if self.has_generic_args else '')
120
def min_num_fixed_args(self):
121
return self.max_num_fixed_args() - self.optional_object_arg_count
123
def max_num_fixed_args(self):
124
return len(self.fixed_arg_format)
126
def is_self_arg(self, i):
128
return self.fixed_arg_format[i] == 'T'
130
def returns_self_type(self):
132
return self.ret_format == 'T'
134
def fixed_arg_type(self, i):
135
return self.format_map[self.fixed_arg_format[i]]
137
def return_type(self):
138
return self.format_map[self.ret_format]
140
def format_from_type(self, arg_type):
141
if arg_type.is_pyobject:
142
arg_type = PyrexTypes.py_object_type
143
return self.type_to_format_map[arg_type]
145
def exception_value(self):
146
return self.error_value_map.get(self.ret_format)
148
def function_type(self, self_arg_override=None):
151
for i in range(self.max_num_fixed_args()):
152
if self_arg_override is not None and self.is_self_arg(i):
153
assert isinstance(self_arg_override, PyrexTypes.CFuncTypeArg)
154
args.append(self_arg_override)
156
arg_type = self.fixed_arg_type(i)
157
args.append(PyrexTypes.CFuncTypeArg("", arg_type, None))
158
if self_arg_override is not None and self.returns_self_type():
159
ret_type = self_arg_override.type
161
ret_type = self.return_type()
162
exc_value = self.exception_value()
163
return PyrexTypes.CFuncType(
164
ret_type, args, exception_value=exc_value,
165
exception_check=self.exception_check,
168
def method_flags(self):
169
if self.ret_format == "O":
170
full_args = self.fixed_arg_format
171
if self.has_dummy_arg:
172
full_args = "O" + full_args
173
if full_args in ["O", "T"]:
174
if not self.has_generic_args:
175
return [method_noargs]
176
elif self.use_fastcall:
177
return [method_fastcall, method_keywords]
179
return [method_varargs, method_keywords]
180
elif full_args in ["OO", "TO"] and not self.has_generic_args:
181
return [method_onearg]
183
if self.is_staticmethod:
184
if self.use_fastcall:
185
return [method_fastcall, method_keywords]
187
return [method_varargs, method_keywords]
190
def method_function_type(self):
192
mflags = self.method_flags()
193
kw = "WithKeywords" if (method_keywords in mflags) else ""
195
if m == method_noargs or m == method_onearg:
197
if m == method_varargs:
198
return "PyCFunction" + kw
199
if m == method_fastcall:
200
return "__Pyx_PyCFunction_FastCall" + kw
203
def with_fastcall(self):
205
sig = copy.copy(self)
206
sig.use_fastcall = True
213
if self.use_fastcall:
229
def __init__(self, slot_name, dynamic=False, inherited=False,
230
ifdef=None, is_binop=False,
232
self.slot_name = slot_name
233
self.is_initialised_dynamically = dynamic
234
self.is_inherited = inherited
236
self.used_ifdef = used_ifdef
237
self.is_binop = is_binop
239
def slot_code(self, scope):
240
raise NotImplementedError()
242
def spec_value(self, scope):
243
return self.slot_code(scope)
245
def preprocessor_guard_code(self):
249
guard = "#if %s" % ifdef
252
def generate_spec(self, scope, code):
253
if self.is_initialised_dynamically:
255
value = self.spec_value(scope)
258
preprocessor_guard = self.preprocessor_guard_code()
259
if not preprocessor_guard:
260
if self.slot_name.startswith(('bf_', 'am_')):
263
preprocessor_guard = "#if defined(Py_%s)" % self.slot_name
264
if preprocessor_guard:
265
code.putln(preprocessor_guard)
269
code.putln(f"#if {self.used_ifdef}")
270
code.putln("{Py_%s, (void *)%s}," % (self.slot_name, value))
273
if preprocessor_guard:
276
def generate(self, scope, code):
277
preprocessor_guard = self.preprocessor_guard_code()
278
if preprocessor_guard:
279
code.putln(preprocessor_guard)
281
end_pypy_guard = False
282
if self.is_initialised_dynamically:
285
value = self.slot_code(scope)
286
if value == "0" and self.is_inherited:
291
inherited_value = value
292
current_scope = scope
293
while (inherited_value == "0"
294
and current_scope.parent_type
295
and current_scope.parent_type.base_type
296
and current_scope.parent_type.base_type.scope):
297
current_scope = current_scope.parent_type.base_type.scope
298
inherited_value = self.slot_code(current_scope)
299
if inherited_value != "0":
301
is_buffer_slot = int(self.slot_name in ("bf_getbuffer", "bf_releasebuffer"))
302
code.putln("#if CYTHON_COMPILING_IN_PYPY || %d" % is_buffer_slot)
303
code.putln("%s, /*%s*/" % (inherited_value, self.slot_name))
305
end_pypy_guard = True
308
code.putln("#if %s" % self.used_ifdef)
309
code.putln("%s, /*%s*/" % (value, self.slot_name))
312
code.putln("NULL, /*%s*/" % self.slot_name)
318
if preprocessor_guard:
326
def generate_dynamic_init_code(self, scope, code):
327
if self.is_initialised_dynamically:
328
self.generate_set_slot_code(
329
self.slot_code(scope), scope, code)
331
def generate_set_slot_code(self, value, scope, code):
335
if scope.parent_type.typeptr_cname:
336
target = "%s->%s" % (scope.parent_type.typeptr_cname, self.slot_name)
338
assert scope.parent_type.typeobj_cname
339
target = "%s.%s" % (scope.parent_type.typeobj_cname, self.slot_name)
341
code.putln("%s = %s;" % (target, value))
344
class FixedSlot(SlotDescriptor):
349
def __init__(self, slot_name, value, ifdef=None):
350
SlotDescriptor.__init__(self, slot_name, ifdef=ifdef)
353
def slot_code(self, scope):
357
class EmptySlot(FixedSlot):
360
def __init__(self, slot_name, ifdef=None):
361
FixedSlot.__init__(self, slot_name, "0", ifdef=ifdef)
364
class MethodSlot(SlotDescriptor):
371
def __init__(self, signature, slot_name, method_name, method_name_to_slot,
372
fallback=None, ifdef=None, inherited=True):
373
SlotDescriptor.__init__(self, slot_name,
374
ifdef=ifdef, inherited=inherited)
375
self.signature = signature
376
self.slot_name = slot_name
377
self.method_name = method_name
378
self.alternatives = []
379
method_name_to_slot[method_name] = self
382
self.alternatives.append(fallback)
384
def slot_code(self, scope):
385
entry = scope.lookup_here(self.method_name)
386
if entry and entry.is_special and entry.func_cname:
387
for method_name in self.alternatives:
388
alt_entry = scope.lookup_here(method_name)
390
warn_once(alt_entry.pos,
391
f"{method_name} was removed in Python 3; ignoring it and using {self.method_name} instead",
393
return entry.func_cname
394
for method_name in self.alternatives:
395
entry = scope.lookup_here(method_name)
396
if entry and entry.is_special and entry.func_cname:
398
f"{method_name} was removed in Python 3; use {self.method_name} instead",
400
return entry.func_cname
404
class InternalMethodSlot(SlotDescriptor):
410
def __init__(self, slot_name, **kargs):
411
SlotDescriptor.__init__(self, slot_name, **kargs)
413
def slot_code(self, scope):
414
return scope.mangle_internal(self.slot_name)
417
class GCDependentSlot(InternalMethodSlot):
421
def __init__(self, slot_name, **kargs):
422
InternalMethodSlot.__init__(self, slot_name, **kargs)
424
def slot_code(self, scope):
425
if not scope.needs_gc():
427
if not scope.has_cyclic_pyobject_attrs:
431
parent_type_scope = scope.parent_type.base_type.scope
432
if scope.parent_scope is parent_type_scope.parent_scope:
433
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
434
if entry.visibility != 'extern':
435
return self.slot_code(parent_type_scope)
436
return InternalMethodSlot.slot_code(self, scope)
439
class GCClearReferencesSlot(GCDependentSlot):
441
def slot_code(self, scope):
442
if scope.needs_tp_clear():
443
return GCDependentSlot.slot_code(self, scope)
447
class ConstructorSlot(InternalMethodSlot):
450
def __init__(self, slot_name, method=None, **kargs):
451
InternalMethodSlot.__init__(self, slot_name, **kargs)
454
def _needs_own(self, scope):
455
if (scope.parent_type.base_type
456
and not scope.has_pyobject_attrs
457
and not scope.has_memoryview_attrs
458
and not scope.has_cpp_constructable_attrs
459
and not (self.slot_name == 'tp_new' and scope.parent_type.vtabslot_cname)):
460
entry = scope.lookup_here(self.method) if self.method else None
461
if not (entry and entry.is_special):
466
def _parent_slot_function(self, scope):
467
parent_type_scope = scope.parent_type.base_type.scope
468
if scope.parent_scope is parent_type_scope.parent_scope:
469
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
470
if entry.visibility != 'extern':
471
return self.slot_code(parent_type_scope)
474
def slot_code(self, scope):
475
if not self._needs_own(scope):
479
slot_code = self._parent_slot_function(scope)
480
return slot_code or '0'
481
return InternalMethodSlot.slot_code(self, scope)
483
def spec_value(self, scope):
484
slot_function = self.slot_code(scope)
485
if self.slot_name == "tp_dealloc" and slot_function != scope.mangle_internal("tp_dealloc"):
490
def generate_dynamic_init_code(self, scope, code):
491
if self.slot_code(scope) != '0':
495
base_type = scope.parent_type.base_type
496
if base_type.typeptr_cname:
497
src = '%s->%s' % (base_type.typeptr_cname, self.slot_name)
498
elif base_type.is_extension_type and base_type.typeobj_cname:
499
src = '%s.%s' % (base_type.typeobj_cname, self.slot_name)
503
self.generate_set_slot_code(src, scope, code)
506
class SyntheticSlot(InternalMethodSlot):
514
def __init__(self, slot_name, user_methods, default_value, **kargs):
515
InternalMethodSlot.__init__(self, slot_name, **kargs)
516
self.user_methods = user_methods
517
self.default_value = default_value
519
def slot_code(self, scope):
520
if scope.defines_any_special(self.user_methods):
521
return InternalMethodSlot.slot_code(self, scope)
523
return self.default_value
525
def spec_value(self, scope):
526
return self.slot_code(scope)
529
class BinopSlot(SyntheticSlot):
530
def __init__(self, signature, slot_name, left_method, method_name_to_slot, **kargs):
531
assert left_method.startswith('__')
532
right_method = '__r' + left_method[2:]
533
SyntheticSlot.__init__(
534
self, slot_name, [left_method, right_method], "0", is_binop=True, **kargs)
536
self.left_slot = MethodSlot(signature, "", left_method, method_name_to_slot, **kargs)
537
self.right_slot = MethodSlot(signature, "", right_method, method_name_to_slot, **kargs)
540
class RichcmpSlot(MethodSlot):
541
def slot_code(self, scope):
542
entry = scope.lookup_here(self.method_name)
543
if entry and entry.is_special and entry.func_cname:
544
return entry.func_cname
545
elif scope.defines_any_special(richcmp_special_methods):
546
return scope.mangle_internal(self.slot_name)
551
class TypeFlagsSlot(SlotDescriptor):
554
def slot_code(self, scope):
555
value = "Py_TPFLAGS_DEFAULT"
556
if scope.directives['type_version_tag']:
558
value += "|Py_TPFLAGS_HAVE_VERSION_TAG"
561
value = "(%s&~Py_TPFLAGS_HAVE_VERSION_TAG)" % value
562
value += "|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER"
563
if not scope.parent_type.is_final_type:
564
value += "|Py_TPFLAGS_BASETYPE"
566
value += "|Py_TPFLAGS_HAVE_GC"
567
if scope.may_have_finalize():
568
value += "|Py_TPFLAGS_HAVE_FINALIZE"
569
if scope.parent_type.has_sequence_flag:
570
value += "|Py_TPFLAGS_SEQUENCE"
573
def generate_spec(self, scope, code):
578
class DocStringSlot(SlotDescriptor):
581
def slot_code(self, scope):
586
doc = doc.as_utf8_string()
587
return "PyDoc_STR(%s)" % doc.as_c_string_literal()
590
class SuiteSlot(SlotDescriptor):
595
def __init__(self, sub_slots, slot_type, slot_name, substructures, ifdef=None, cast_cname=None):
596
SlotDescriptor.__init__(self, slot_name, ifdef=ifdef)
597
self.sub_slots = sub_slots
598
self.slot_type = slot_type
599
self.cast_cname = cast_cname
600
substructures.append(self)
602
def is_empty(self, scope):
603
for slot in self.sub_slots:
604
if slot.slot_code(scope) != "0":
608
def substructure_cname(self, scope):
609
return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name)
611
def slot_code(self, scope):
612
if not self.is_empty(scope):
615
cast = f"({self.cast_cname}*)"
616
return f"{cast}&{self.substructure_cname(scope)}"
619
def generate_substructure(self, scope, code):
620
if not self.is_empty(scope):
623
code.putln("#if %s" % self.ifdef)
625
"static %s %s = {" % (
627
self.substructure_cname(scope)))
628
for slot in self.sub_slots:
629
slot.generate(scope, code)
634
def generate_spec(self, scope, code):
635
for slot in self.sub_slots:
636
slot.generate_spec(scope, code)
638
class MethodTableSlot(SlotDescriptor):
641
def slot_code(self, scope):
642
if scope.pyfunc_entries:
643
return scope.method_table_cname
648
class MemberTableSlot(SlotDescriptor):
651
def slot_code(self, scope):
655
def get_member_specs(self, scope):
657
get_slot_by_name("tp_dictoffset", scope.directives).members_slot_value(scope),
661
def is_empty(self, scope):
662
for member_entry in self.get_member_specs(scope):
667
def substructure_cname(self, scope):
668
return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name)
670
def generate_substructure_spec(self, scope, code):
671
if self.is_empty(scope):
673
from .Code import UtilityCode
674
code.globalstate.use_utility_code(UtilityCode.load_cached("IncludeStructmemberH", "ModuleSetupCode.c"))
676
code.putln("static struct PyMemberDef %s[] = {" % self.substructure_cname(scope))
677
for member_entry in self.get_member_specs(scope):
679
code.putln(member_entry)
680
code.putln("{NULL, 0, 0, 0, NULL}")
683
def spec_value(self, scope):
684
if self.is_empty(scope):
686
return self.substructure_cname(scope)
689
class GetSetSlot(SlotDescriptor):
692
def slot_code(self, scope):
693
if scope.property_entries:
694
return scope.getset_table_cname
699
class BaseClassSlot(SlotDescriptor):
702
def __init__(self, name):
703
SlotDescriptor.__init__(self, name, dynamic=True)
705
def generate_dynamic_init_code(self, scope, code):
706
base_type = scope.parent_type.base_type
708
code.putln("%s->%s = %s;" % (
709
scope.parent_type.typeptr_cname,
711
base_type.typeptr_cname))
714
class DictOffsetSlot(SlotDescriptor):
717
def slot_code(self, scope):
718
dict_entry = scope.lookup_here("__dict__") if not scope.is_closure_class_scope else None
719
if dict_entry and dict_entry.is_variable:
720
from . import Builtin
721
if dict_entry.type is not Builtin.dict_type:
722
error(dict_entry.pos, "__dict__ slot must be of type 'dict'")
724
type = scope.parent_type
725
if type.typedef_flag:
726
objstruct = type.objstruct_cname
728
objstruct = "struct %s" % type.objstruct_cname
729
return ("offsetof(%s, %s)" % (
735
def members_slot_value(self, scope):
736
dict_offset = self.slot_code(scope)
737
if dict_offset == "0":
739
return '{"__dictoffset__", T_PYSSIZET, %s, READONLY, NULL},' % dict_offset
755
def get_property_accessor_signature(name):
758
return property_accessor_signatures.get(name)
761
def get_base_slot_function(scope, slot):
765
base_type = scope.parent_type.base_type
766
if base_type and scope.parent_scope is base_type.scope.parent_scope:
767
parent_slot = slot.slot_code(base_type.scope)
768
if parent_slot != '0':
769
entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name)
770
if entry.visibility != 'extern':
775
def get_slot_function(scope, slot):
779
slot_code = slot.slot_code(scope)
781
entry = scope.parent_scope.lookup_here(scope.parent_type.name)
782
if entry.visibility != 'extern':
787
def get_slot_by_name(slot_name, compiler_directives):
789
for slot in get_slot_table(compiler_directives).slot_table:
790
if slot.slot_name == slot_name:
792
assert False, "Slot not found: %s" % slot_name
795
def get_slot_code_by_name(scope, slot_name):
796
slot = get_slot_by_name(slot_name, scope.directives)
797
return slot.slot_code(scope)
799
def is_binop_number_slot(name):
801
Tries to identify __add__/__radd__ and friends (so the METH_COEXIST flag can be applied).
803
There's no great consequence if it inadvertently identifies a few other methods
804
so just use a simple rule rather than an exact list.
806
slot_table = get_slot_table(None)
807
for meth in get_slot_table(None).PyNumberMethods:
808
if meth.is_binop and name in meth.user_methods:
819
pyfunction_signature = Signature("-*", "O")
820
pymethod_signature = Signature("T*", "O")
828
pyfunction_noargs = Signature("-", "O")
829
pyfunction_onearg = Signature("-O", "O")
838
unaryfunc = Signature("T", "O")
839
binaryfunc = Signature("OO", "O")
840
ibinaryfunc = Signature("TO", "O")
841
powternaryfunc = Signature("OO?", "O")
842
ipowternaryfunc = Signature("TO?", "O")
843
callfunc = Signature("T*", "O")
844
inquiry = Signature("T", "i")
845
lenfunc = Signature("T", "z")
848
intargfunc = Signature("Ti", "O")
849
ssizeargfunc = Signature("Tz", "O")
850
intintargfunc = Signature("Tii", "O")
851
ssizessizeargfunc = Signature("Tzz", "O")
852
intobjargproc = Signature("TiO", 'r')
853
ssizeobjargproc = Signature("TzO", 'r')
854
intintobjargproc = Signature("TiiO", 'r')
855
ssizessizeobjargproc = Signature("TzzO", 'r')
857
intintargproc = Signature("Tii", 'r')
858
ssizessizeargproc = Signature("Tzz", 'r')
859
objargfunc = Signature("TO", "O")
860
objobjargproc = Signature("TOO", 'r')
861
readbufferproc = Signature("TzP", "z")
862
writebufferproc = Signature("TzP", "z")
863
segcountproc = Signature("TZ", "z")
864
charbufferproc = Signature("TzS", "z")
865
objargproc = Signature("TO", 'r')
869
destructor = Signature("T", "v")
872
getattrofunc = Signature("TO", "O")
874
setattrofunc = Signature("TOO", 'r')
875
delattrofunc = Signature("TO", 'r')
876
cmpfunc = Signature("TO", "i")
877
reprfunc = Signature("T", "O")
878
hashfunc = Signature("T", "h")
879
richcmpfunc = Signature("TOi", "O")
880
getiterfunc = Signature("T", "O")
881
iternextfunc = Signature("T", "O")
882
descrgetfunc = Signature("TOO", "O")
883
descrsetfunc = Signature("TOO", 'r')
884
descrdelfunc = Signature("TO", 'r')
885
initproc = Signature("T*", 'r')
889
getbufferproc = Signature("TBi", "r")
890
releasebufferproc = Signature("TB", "v")
893
sendfunc = PyrexTypes.CPtrType(PyrexTypes.CFuncType(
894
return_type=PyrexTypes.PySendResult_type,
896
PyrexTypes.CFuncTypeArg("iter", PyrexTypes.py_object_type),
897
PyrexTypes.CFuncTypeArg("value", PyrexTypes.py_object_type),
898
PyrexTypes.CFuncTypeArg("result", PyrexTypes.CPtrType(PyrexTypes.py_objptr_type)),
900
exception_value="PYGEN_ERROR",
901
exception_check=True,
911
property_accessor_signatures = {
912
'__get__': Signature("T", "O"),
913
'__set__': Signature("TO", 'r'),
914
'__del__': Signature("T", 'r')
930
def __init__(self, old_binops):
932
method_name_to_slot = {}
933
self._get_slot_by_method_name = method_name_to_slot.get
934
self.substructures = []
936
bf = binaryfunc if old_binops else ibinaryfunc
937
ptf = powternaryfunc if old_binops else ipowternaryfunc
941
self.PyNumberMethods = (
942
BinopSlot(bf, "nb_add", "__add__", method_name_to_slot),
943
BinopSlot(bf, "nb_subtract", "__sub__", method_name_to_slot),
944
BinopSlot(bf, "nb_multiply", "__mul__", method_name_to_slot),
945
BinopSlot(bf, "nb_remainder", "__mod__", method_name_to_slot),
946
BinopSlot(bf, "nb_divmod", "__divmod__", method_name_to_slot),
947
BinopSlot(ptf, "nb_power", "__pow__", method_name_to_slot),
948
MethodSlot(unaryfunc, "nb_negative", "__neg__", method_name_to_slot),
949
MethodSlot(unaryfunc, "nb_positive", "__pos__", method_name_to_slot),
950
MethodSlot(unaryfunc, "nb_absolute", "__abs__", method_name_to_slot),
951
MethodSlot(inquiry, "nb_bool", "__bool__", method_name_to_slot,
952
fallback="__nonzero__"),
953
MethodSlot(unaryfunc, "nb_invert", "__invert__", method_name_to_slot),
954
BinopSlot(bf, "nb_lshift", "__lshift__", method_name_to_slot),
955
BinopSlot(bf, "nb_rshift", "__rshift__", method_name_to_slot),
956
BinopSlot(bf, "nb_and", "__and__", method_name_to_slot),
957
BinopSlot(bf, "nb_xor", "__xor__", method_name_to_slot),
958
BinopSlot(bf, "nb_or", "__or__", method_name_to_slot),
959
MethodSlot(unaryfunc, "nb_int", "__int__", method_name_to_slot, fallback="__long__"),
960
EmptySlot("nb_long (reserved)"),
961
MethodSlot(unaryfunc, "nb_float", "__float__", method_name_to_slot),
964
MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__", method_name_to_slot),
965
MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__", method_name_to_slot),
966
MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__", method_name_to_slot),
967
MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__", method_name_to_slot),
968
MethodSlot(ptf, "nb_inplace_power", "__ipow__", method_name_to_slot),
969
MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__", method_name_to_slot),
970
MethodSlot(ibinaryfunc, "nb_inplace_rshift", "__irshift__", method_name_to_slot),
971
MethodSlot(ibinaryfunc, "nb_inplace_and", "__iand__", method_name_to_slot),
972
MethodSlot(ibinaryfunc, "nb_inplace_xor", "__ixor__", method_name_to_slot),
973
MethodSlot(ibinaryfunc, "nb_inplace_or", "__ior__", method_name_to_slot),
977
BinopSlot(bf, "nb_floor_divide", "__floordiv__", method_name_to_slot),
978
BinopSlot(bf, "nb_true_divide", "__truediv__", method_name_to_slot),
979
MethodSlot(ibinaryfunc, "nb_inplace_floor_divide", "__ifloordiv__", method_name_to_slot),
980
MethodSlot(ibinaryfunc, "nb_inplace_true_divide", "__itruediv__", method_name_to_slot),
983
MethodSlot(unaryfunc, "nb_index", "__index__", method_name_to_slot),
986
BinopSlot(bf, "nb_matrix_multiply", "__matmul__", method_name_to_slot,
987
ifdef="PY_VERSION_HEX >= 0x03050000"),
988
MethodSlot(ibinaryfunc, "nb_inplace_matrix_multiply", "__imatmul__", method_name_to_slot,
989
ifdef="PY_VERSION_HEX >= 0x03050000"),
992
self.PySequenceMethods = (
993
MethodSlot(lenfunc, "sq_length", "__len__", method_name_to_slot),
994
EmptySlot("sq_concat"),
995
EmptySlot("sq_repeat"),
996
SyntheticSlot("sq_item", ["__getitem__"], "0"),
997
MethodSlot(ssizessizeargfunc, "sq_slice", "__getslice__", method_name_to_slot),
998
EmptySlot("sq_ass_item"),
999
SyntheticSlot("sq_ass_slice", ["__setslice__", "__delslice__"], "0"),
1000
MethodSlot(cmpfunc, "sq_contains", "__contains__", method_name_to_slot),
1001
EmptySlot("sq_inplace_concat"),
1002
EmptySlot("sq_inplace_repeat"),
1005
self.PyMappingMethods = (
1006
MethodSlot(lenfunc, "mp_length", "__len__", method_name_to_slot),
1007
MethodSlot(objargfunc, "mp_subscript", "__getitem__", method_name_to_slot),
1008
SyntheticSlot("mp_ass_subscript", ["__setitem__", "__delitem__"], "0"),
1011
self.PyBufferProcs = (
1012
MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", method_name_to_slot),
1013
MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", method_name_to_slot)
1016
self.PyAsyncMethods = (
1017
MethodSlot(unaryfunc, "am_await", "__await__", method_name_to_slot),
1018
MethodSlot(unaryfunc, "am_aiter", "__aiter__", method_name_to_slot),
1019
MethodSlot(unaryfunc, "am_anext", "__anext__", method_name_to_slot),
1022
EmptySlot("am_send"),
1026
ConstructorSlot("tp_dealloc", '__dealloc__'),
1027
EmptySlot("tp_print", ifdef="PY_VERSION_HEX < 0x030800b4"),
1028
EmptySlot("tp_vectorcall_offset", ifdef="PY_VERSION_HEX >= 0x030800b4"),
1029
EmptySlot("tp_getattr"),
1030
EmptySlot("tp_setattr"),
1032
SuiteSlot(self. PyAsyncMethods, "__Pyx_PyAsyncMethodsStruct", "tp_as_async",
1033
self.substructures, cast_cname="PyAsyncMethods"),
1035
MethodSlot(reprfunc, "tp_repr", "__repr__", method_name_to_slot),
1037
SuiteSlot(self.PyNumberMethods, "PyNumberMethods", "tp_as_number", self.substructures),
1038
SuiteSlot(self.PySequenceMethods, "PySequenceMethods", "tp_as_sequence", self.substructures),
1039
SuiteSlot(self.PyMappingMethods, "PyMappingMethods", "tp_as_mapping", self.substructures),
1041
MethodSlot(hashfunc, "tp_hash", "__hash__", method_name_to_slot,
1043
MethodSlot(callfunc, "tp_call", "__call__", method_name_to_slot),
1044
MethodSlot(reprfunc, "tp_str", "__str__", method_name_to_slot),
1046
SyntheticSlot("tp_getattro", ["__getattr__","__getattribute__"], "0"),
1047
SyntheticSlot("tp_setattro", ["__setattr__", "__delattr__"], "0"),
1049
SuiteSlot(self.PyBufferProcs, "PyBufferProcs", "tp_as_buffer", self.substructures),
1051
TypeFlagsSlot("tp_flags"),
1052
DocStringSlot("tp_doc"),
1054
GCDependentSlot("tp_traverse"),
1055
GCClearReferencesSlot("tp_clear"),
1057
RichcmpSlot(richcmpfunc, "tp_richcompare", "__richcmp__", method_name_to_slot,
1060
EmptySlot("tp_weaklistoffset"),
1062
MethodSlot(getiterfunc, "tp_iter", "__iter__", method_name_to_slot),
1063
MethodSlot(iternextfunc, "tp_iternext", "__next__", method_name_to_slot),
1065
MethodTableSlot("tp_methods"),
1066
MemberTableSlot("tp_members"),
1067
GetSetSlot("tp_getset"),
1069
BaseClassSlot("tp_base"),
1070
EmptySlot("tp_dict"),
1072
SyntheticSlot("tp_descr_get", ["__get__"], "0"),
1073
SyntheticSlot("tp_descr_set", ["__set__", "__delete__"], "0"),
1075
DictOffsetSlot("tp_dictoffset", ifdef="!CYTHON_USE_TYPE_SPECS"),
1077
MethodSlot(initproc, "tp_init", "__init__", method_name_to_slot),
1078
EmptySlot("tp_alloc"),
1079
ConstructorSlot("tp_new", "__cinit__"),
1080
EmptySlot("tp_free"),
1082
EmptySlot("tp_is_gc"),
1083
EmptySlot("tp_bases"),
1084
EmptySlot("tp_mro"),
1085
EmptySlot("tp_cache"),
1086
EmptySlot("tp_subclasses"),
1087
EmptySlot("tp_weaklist"),
1088
EmptySlot("tp_del"),
1089
EmptySlot("tp_version_tag"),
1090
SyntheticSlot("tp_finalize", ["__del__"], "0",
1091
used_ifdef="CYTHON_USE_TP_FINALIZE"),
1092
EmptySlot("tp_vectorcall", ifdef="PY_VERSION_HEX >= 0x030800b1 && (!CYTHON_COMPILING_IN_PYPY || PYPY_VERSION_NUM >= 0x07030800)"),
1093
EmptySlot("tp_print", ifdef="__PYX_NEED_TP_PRINT_SLOT == 1"),
1094
EmptySlot("tp_watched", ifdef="PY_VERSION_HEX >= 0x030C0000"),
1095
EmptySlot("tp_versions_used", ifdef="PY_VERSION_HEX >= 0x030d00A4"),
1097
EmptySlot("tp_pypy_flags", ifdef="CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000"),
1108
MethodSlot(initproc, "", "__cinit__", method_name_to_slot)
1109
MethodSlot(destructor, "", "__dealloc__", method_name_to_slot)
1110
MethodSlot(destructor, "", "__del__", method_name_to_slot)
1111
MethodSlot(objobjargproc, "", "__setitem__", method_name_to_slot)
1112
MethodSlot(objargproc, "", "__delitem__", method_name_to_slot)
1113
MethodSlot(ssizessizeobjargproc, "", "__setslice__", method_name_to_slot)
1114
MethodSlot(ssizessizeargproc, "", "__delslice__", method_name_to_slot)
1115
MethodSlot(getattrofunc, "", "__getattr__", method_name_to_slot)
1116
MethodSlot(getattrofunc, "", "__getattribute__", method_name_to_slot)
1117
MethodSlot(setattrofunc, "", "__setattr__", method_name_to_slot)
1118
MethodSlot(delattrofunc, "", "__delattr__", method_name_to_slot)
1119
MethodSlot(descrgetfunc, "", "__get__", method_name_to_slot)
1120
MethodSlot(descrsetfunc, "", "__set__", method_name_to_slot)
1121
MethodSlot(descrdelfunc, "", "__delete__", method_name_to_slot)
1129
MethodSlot(inquiry, "", "__nonzero__", method_name_to_slot)
1130
MethodSlot(unaryfunc, "", "__long__", method_name_to_slot)
1132
def get_special_method_signature(self, name):
1135
slot = self._get_slot_by_method_name(name)
1137
return slot.signature
1138
elif name in richcmp_special_methods:
1143
def get_slot_by_method_name(self, method_name):
1145
return self._get_slot_by_method_name(method_name)
1149
return iter(self.slot_table)
1152
_slot_table_dict = {}
1154
def get_slot_table(compiler_directives):
1155
if not compiler_directives:
1158
from .Options import get_directive_defaults
1159
compiler_directives = get_directive_defaults()
1161
old_binops = compiler_directives['c_api_binop_methods']
1163
if key not in _slot_table_dict:
1164
_slot_table_dict[key] = SlotTable(old_binops=old_binops)
1165
return _slot_table_dict[key]
1169
special_method_names = set(get_slot_table(compiler_directives=None))
1174
method_noargs = "METH_NOARGS"
1175
method_onearg = "METH_O"
1176
method_varargs = "METH_VARARGS"
1177
method_fastcall = "__Pyx_METH_FASTCALL"
1178
method_keywords = "METH_KEYWORDS"
1179
method_coexist = "METH_COEXIST"