1 # 2 # Tables describing slots in the CPython type object 3 # and associated know-how. 4 # 5 6 import Naming 7 import PyrexTypes 8 import StringEncoding 9 10 invisible = ['__cinit__', '__dealloc__', '__richcmp__', 11 '__nonzero__', '__bool__'] 12 13 class Signature(object): 14 # Method slot signature descriptor. 15 # 16 # has_dummy_arg boolean 17 # has_generic_args boolean 18 # fixed_arg_format string 19 # ret_format string 20 # error_value string 21 # 22 # The formats are strings made up of the following 23 # characters: 24 # 25 # 'O' Python object 26 # 'T' Python object of the type of 'self' 27 # 'v' void 28 # 'p' void * 29 # 'P' void ** 30 # 'i' int 31 # 'b' bint 32 # 'I' int * 33 # 'l' long 34 # 'f' float 35 # 'd' double 36 # 'h' Py_hash_t 37 # 'z' Py_ssize_t 38 # 'Z' Py_ssize_t * 39 # 's' char * 40 # 'S' char ** 41 # 'r' int used only to signal exception 42 # 'B' Py_buffer * 43 # '-' dummy 'self' argument (not used) 44 # '*' rest of args passed as generic Python 45 # arg tuple and kw dict (must be last 46 # char in format string) 47 48 format_map = { 49 'O': PyrexTypes.py_object_type, 50 'v': PyrexTypes.c_void_type, 51 'p': PyrexTypes.c_void_ptr_type, 52 'P': PyrexTypes.c_void_ptr_ptr_type, 53 'i': PyrexTypes.c_int_type, 54 'b': PyrexTypes.c_bint_type, 55 'I': PyrexTypes.c_int_ptr_type, 56 'l': PyrexTypes.c_long_type, 57 'f': PyrexTypes.c_float_type, 58 'd': PyrexTypes.c_double_type, 59 'h': PyrexTypes.c_py_hash_t_type, 60 'z': PyrexTypes.c_py_ssize_t_type, 61 'Z': PyrexTypes.c_py_ssize_t_ptr_type, 62 's': PyrexTypes.c_char_ptr_type, 63 'S': PyrexTypes.c_char_ptr_ptr_type, 64 'r': PyrexTypes.c_returncode_type, 65 'B': PyrexTypes.c_py_buffer_ptr_type, 66 # 'T', '-' and '*' are handled otherwise 67 # and are not looked up in here 68 } 69 70 type_to_format_map = dict([(type_, format_) 71 for format_, type_ in format_map.iteritems()]) 72 73 error_value_map = { 74 'O': "NULL", 75 'T': "NULL", 76 'i': "-1", 77 'b': "-1", 78 'l': "-1", 79 'r': "-1", 80 'h': "-1", 81 'z': "-1", 82 } 83 84 def __init__(self, arg_format, ret_format): 85 self.has_dummy_arg = 0 86 self.has_generic_args = 0 87 if arg_format[:1] == '-': 88 self.has_dummy_arg = 1 89 arg_format = arg_format[1:] 90 if arg_format[-1:] == '*': 91 self.has_generic_args = 1 92 arg_format = arg_format[:-1] 93 self.fixed_arg_format = arg_format 94 self.ret_format = ret_format 95 self.error_value = self.error_value_map.get(ret_format, None) 96 self.exception_check = ret_format != 'r' and self.error_value is not None 97 self.is_staticmethod = False 98 99 def num_fixed_args(self): 100 return len(self.fixed_arg_format) 101 102 def is_self_arg(self, i): 103 # argument is 'self' for methods or 'class' for classmethods 104 return self.fixed_arg_format[i] == 'T' 105 106 def returns_self_type(self): 107 # return type is same as 'self' argument type 108 return self.ret_format == 'T' 109 110 def fixed_arg_type(self, i): 111 return self.format_map[self.fixed_arg_format[i]] 112 113 def return_type(self): 114 return self.format_map[self.ret_format] 115 116 def format_from_type(self, arg_type): 117 if arg_type.is_pyobject: 118 arg_type = PyrexTypes.py_object_type 119 return self.type_to_format_map[arg_type] 120 121 def exception_value(self): 122 return self.error_value_map.get(self.ret_format) 123 124 def function_type(self, self_arg_override=None): 125 # Construct a C function type descriptor for this signature 126 args = [] 127 for i in xrange(self.num_fixed_args()): 128 if self_arg_override is not None and self.is_self_arg(i): 129 assert isinstance(self_arg_override, PyrexTypes.CFuncTypeArg) 130 args.append(self_arg_override) 131 else: 132 arg_type = self.fixed_arg_type(i) 133 args.append(PyrexTypes.CFuncTypeArg("", arg_type, None)) 134 if self_arg_override is not None and self.returns_self_type(): 135 ret_type = self_arg_override.type 136 else: 137 ret_type = self.return_type() 138 exc_value = self.exception_value() 139 return PyrexTypes.CFuncType( 140 ret_type, args, exception_value=exc_value, 141 exception_check=self.exception_check) 142 143 def method_flags(self): 144 if self.ret_format == "O": 145 full_args = self.fixed_arg_format 146 if self.has_dummy_arg: 147 full_args = "O" + full_args 148 if full_args in ["O", "T"]: 149 if self.has_generic_args: 150 return [method_varargs, method_keywords] 151 else: 152 return [method_noargs] 153 elif full_args in ["OO", "TO"] and not self.has_generic_args: 154 return [method_onearg] 155 156 if self.is_staticmethod: 157 return [method_varargs, method_keywords] 158 return None 159 160 161 class SlotDescriptor(object): 162 # Abstract base class for type slot descriptors. 163 # 164 # slot_name string Member name of the slot in the type object 165 # is_initialised_dynamically Is initialised by code in the module init function 166 # is_inherited Is inherited by subtypes (see PyType_Ready()) 167 # py3 Indicates presence of slot in Python 3 168 # py2 Indicates presence of slot in Python 2 169 # ifdef Full #ifdef string that slot is wrapped in. Using this causes py3, py2 and flags to be ignored.) 170 171 def __init__(self, slot_name, dynamic=False, inherited=False, 172 py3=True, py2=True, ifdef=None): 173 self.slot_name = slot_name 174 self.is_initialised_dynamically = dynamic 175 self.is_inherited = inherited 176 self.ifdef = ifdef 177 self.py3 = py3 178 self.py2 = py2 179 180 def preprocessor_guard_code(self): 181 ifdef = self.ifdef 182 py2 = self.py2 183 py3 = self.py3 184 guard = None 185 if ifdef: 186 guard = ("#if %s" % ifdef) 187 elif not py3 or py3 == '<RESERVED>': 188 guard = ("#if PY_MAJOR_VERSION < 3") 189 elif not py2: 190 guard = ("#if PY_MAJOR_VERSION >= 3") 191 return guard 192 193 def generate(self, scope, code): 194 end_pypy_guard = False 195 if self.is_initialised_dynamically: 196 value = "0" 197 else: 198 value = self.slot_code(scope) 199 if value == "0" and self.is_inherited: 200 # PyPy currently has a broken PyType_Ready() that fails to 201 # inherit some slots. To work around this, we explicitly 202 # set inherited slots here, but only in PyPy since CPython 203 # handles this better than we do. 204 inherited_value = value 205 current_scope = scope 206 while (inherited_value == "0" 207 and current_scope.parent_type 208 and current_scope.parent_type.base_type 209 and current_scope.parent_type.base_type.scope): 210 current_scope = current_scope.parent_type.base_type.scope 211 inherited_value = self.slot_code(current_scope) 212 if inherited_value != "0": 213 code.putln("#if CYTHON_COMPILING_IN_PYPY") 214 code.putln("%s, /*%s*/" % (inherited_value, self.slot_name)) 215 code.putln("#else") 216 end_pypy_guard = True 217 preprocessor_guard = self.preprocessor_guard_code() 218 if preprocessor_guard: 219 code.putln(preprocessor_guard) 220 code.putln("%s, /*%s*/" % (value, self.slot_name)) 221 if self.py3 == '<RESERVED>': 222 code.putln("#else") 223 code.putln("0, /*reserved*/") 224 if preprocessor_guard: 225 code.putln("#endif") 226 if end_pypy_guard: 227 code.putln("#endif") 228 229 # Some C implementations have trouble statically 230 # initialising a global with a pointer to an extern 231 # function, so we initialise some of the type slots 232 # in the module init function instead. 233 234 def generate_dynamic_init_code(self, scope, code): 235 if self.is_initialised_dynamically: 236 value = self.slot_code(scope) 237 if value != "0": 238 code.putln("%s.%s = %s;" % ( 239 scope.parent_type.typeobj_cname, 240 self.slot_name, 241 value 242 ) 243 ) 244 245 246 class FixedSlot(SlotDescriptor): 247 # Descriptor for a type slot with a fixed value. 248 # 249 # value string 250 251 def __init__(self, slot_name, value, py3=True, py2=True, ifdef=None): 252 SlotDescriptor.__init__(self, slot_name, py3=py3, py2=py2, ifdef=ifdef) 253 self.value = value 254 255 def slot_code(self, scope): 256 return self.value 257 258 259 class EmptySlot(FixedSlot): 260 # Descriptor for a type slot whose value is always 0. 261 262 def __init__(self, slot_name, py3=True, py2=True, ifdef=None): 263 FixedSlot.__init__(self, slot_name, "0", py3=py3, py2=py2, ifdef=ifdef) 264 265 266 class MethodSlot(SlotDescriptor): 267 # Type slot descriptor for a user-definable method. 268 # 269 # signature Signature 270 # method_name string The __xxx__ name of the method 271 # alternatives [string] Alternative list of __xxx__ names for the method 272 273 def __init__(self, signature, slot_name, method_name, fallback=None, 274 py3=True, py2=True, ifdef=None, inherited=True): 275 SlotDescriptor.__init__(self, slot_name, py3=py3, py2=py2, 276 ifdef=ifdef, inherited=inherited) 277 self.signature = signature 278 self.slot_name = slot_name 279 self.method_name = method_name 280 self.alternatives = [] 281 method_name_to_slot[method_name] = self 282 # 283 if fallback: 284 self.alternatives.append(fallback) 285 for alt in (self.py2, self.py3): 286 if isinstance(alt, (tuple, list)): 287 slot_name, method_name = alt 288 self.alternatives.append(method_name) 289 method_name_to_slot[method_name] = self 290 291 def slot_code(self, scope): 292 entry = scope.lookup_here(self.method_name) 293 if entry and entry.func_cname: 294 return entry.func_cname 295 for method_name in self.alternatives: 296 entry = scope.lookup_here(method_name) 297 if entry and entry.func_cname: 298 return entry.func_cname 299 return "0" 300 301 302 class InternalMethodSlot(SlotDescriptor): 303 # Type slot descriptor for a method which is always 304 # synthesized by Cython. 305 # 306 # slot_name string Member name of the slot in the type object 307 308 def __init__(self, slot_name, **kargs): 309 SlotDescriptor.__init__(self, slot_name, **kargs) 310 311 def slot_code(self, scope): 312 return scope.mangle_internal(self.slot_name) 313 314 315 class GCDependentSlot(InternalMethodSlot): 316 # Descriptor for a slot whose value depends on whether 317 # the type participates in GC. 318 319 def __init__(self, slot_name, **kargs): 320 InternalMethodSlot.__init__(self, slot_name, **kargs) 321 322 def slot_code(self, scope): 323 if not scope.needs_gc(): 324 return "0" 325 if not scope.has_cyclic_pyobject_attrs: 326 # if the type does not have GC relevant object attributes, it can 327 # delegate GC methods to its parent - iff the parent functions 328 # are defined in the same module 329 parent_type_scope = scope.parent_type.base_type.scope 330 if scope.parent_scope is parent_type_scope.parent_scope: 331 entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) 332 if entry.visibility != 'extern': 333 return self.slot_code(parent_type_scope) 334 return InternalMethodSlot.slot_code(self, scope) 335 336 337 class GCClearReferencesSlot(GCDependentSlot): 338 339 def slot_code(self, scope): 340 if scope.needs_tp_clear(): 341 return GCDependentSlot.slot_code(self, scope) 342 return "0" 343 344 345 class ConstructorSlot(InternalMethodSlot): 346 # Descriptor for tp_new and tp_dealloc. 347 348 def __init__(self, slot_name, method, **kargs): 349 InternalMethodSlot.__init__(self, slot_name, **kargs) 350 self.method = method 351 352 def slot_code(self, scope): 353 if (self.slot_name != 'tp_new' 354 and scope.parent_type.base_type 355 and not scope.has_pyobject_attrs 356 and not scope.has_memoryview_attrs 357 and not scope.lookup_here(self.method)): 358 # if the type does not have object attributes, it can 359 # delegate GC methods to its parent - iff the parent 360 # functions are defined in the same module 361 parent_type_scope = scope.parent_type.base_type.scope 362 if scope.parent_scope is parent_type_scope.parent_scope: 363 entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) 364 if entry.visibility != 'extern': 365 return self.slot_code(parent_type_scope) 366 return InternalMethodSlot.slot_code(self, scope) 367 368 369 class SyntheticSlot(InternalMethodSlot): 370 # Type slot descriptor for a synthesized method which 371 # dispatches to one or more user-defined methods depending 372 # on its arguments. If none of the relevant methods are 373 # defined, the method will not be synthesized and an 374 # alternative default value will be placed in the type 375 # slot. 376 377 def __init__(self, slot_name, user_methods, default_value, **kargs): 378 InternalMethodSlot.__init__(self, slot_name, **kargs) 379 self.user_methods = user_methods 380 self.default_value = default_value 381 382 def slot_code(self, scope): 383 if scope.defines_any(self.user_methods): 384 return InternalMethodSlot.slot_code(self, scope) 385 else: 386 return self.default_value 387 388 389 class TypeFlagsSlot(SlotDescriptor): 390 # Descriptor for the type flags slot. 391 392 def slot_code(self, scope): 393 value = "Py_TPFLAGS_DEFAULT" 394 if scope.directives['type_version_tag']: 395 # it's not in 'Py_TPFLAGS_DEFAULT' in Py2 396 value += "|Py_TPFLAGS_HAVE_VERSION_TAG" 397 else: 398 # it's enabled in 'Py_TPFLAGS_DEFAULT' in Py3 399 value = "(%s&~Py_TPFLAGS_HAVE_VERSION_TAG)" % value 400 value += "|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER" 401 if not scope.parent_type.is_final_type: 402 value += "|Py_TPFLAGS_BASETYPE" 403 if scope.needs_gc(): 404 value += "|Py_TPFLAGS_HAVE_GC" 405 return value 406 407 408 class DocStringSlot(SlotDescriptor): 409 # Descriptor for the docstring slot. 410 411 def slot_code(self, scope): 412 if scope.doc is not None: 413 if scope.doc.is_unicode: 414 doc = scope.doc.utf8encode() 415 else: 416 doc = scope.doc.byteencode() 417 return '__Pyx_DOCSTR("%s")' % StringEncoding.escape_byte_string(doc) 418 else: 419 return "0" 420 421 422 class SuiteSlot(SlotDescriptor): 423 # Descriptor for a substructure of the type object. 424 # 425 # sub_slots [SlotDescriptor] 426 427 def __init__(self, sub_slots, slot_type, slot_name): 428 SlotDescriptor.__init__(self, slot_name) 429 self.sub_slots = sub_slots 430 self.slot_type = slot_type 431 substructures.append(self) 432 433 def is_empty(self, scope): 434 for slot in self.sub_slots: 435 if slot.slot_code(scope) != "0": 436 return False 437 return True 438 439 def substructure_cname(self, scope): 440 return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name) 441 442 def slot_code(self, scope): 443 if not self.is_empty(scope): 444 return "&%s" % self.substructure_cname(scope) 445 return "0" 446 447 def generate_substructure(self, scope, code): 448 if not self.is_empty(scope): 449 code.putln("") 450 code.putln( 451 "static %s %s = {" % ( 452 self.slot_type, 453 self.substructure_cname(scope))) 454 for slot in self.sub_slots: 455 slot.generate(scope, code) 456 code.putln("};") 457 458 substructures = [] # List of all SuiteSlot instances 459 460 class MethodTableSlot(SlotDescriptor): 461 # Slot descriptor for the method table. 462 463 def slot_code(self, scope): 464 if scope.pyfunc_entries: 465 return scope.method_table_cname 466 else: 467 return "0" 468 469 470 class MemberTableSlot(SlotDescriptor): 471 # Slot descriptor for the table of Python-accessible attributes. 472 473 def slot_code(self, scope): 474 return "0" 475 476 477 class GetSetSlot(SlotDescriptor): 478 # Slot descriptor for the table of attribute get & set methods. 479 480 def slot_code(self, scope): 481 if scope.property_entries: 482 return scope.getset_table_cname 483 else: 484 return "0" 485 486 487 class BaseClassSlot(SlotDescriptor): 488 # Slot descriptor for the base class slot. 489 490 def __init__(self, name): 491 SlotDescriptor.__init__(self, name, dynamic = 1) 492 493 def generate_dynamic_init_code(self, scope, code): 494 base_type = scope.parent_type.base_type 495 if base_type: 496 code.putln("%s.%s = %s;" % ( 497 scope.parent_type.typeobj_cname, 498 self.slot_name, 499 base_type.typeptr_cname)) 500 501 502 # The following dictionary maps __xxx__ method names to slot descriptors. 503 504 method_name_to_slot = {} 505 506 ## The following slots are (or could be) initialised with an 507 ## extern function pointer. 508 # 509 #slots_initialised_from_extern = ( 510 # "tp_free", 511 #) 512 513 #------------------------------------------------------------------------------------------ 514 # 515 # Utility functions for accessing slot table data structures 516 # 517 #------------------------------------------------------------------------------------------ 518 519 def get_special_method_signature(name): 520 # Given a method name, if it is a special method, 521 # return its signature, else return None. 522 slot = method_name_to_slot.get(name) 523 if slot: 524 return slot.signature 525 else: 526 return None 527 528 529 def get_property_accessor_signature(name): 530 # Return signature of accessor for an extension type 531 # property, else None. 532 return property_accessor_signatures.get(name) 533 534 535 def get_base_slot_function(scope, slot): 536 # Returns the function implementing this slot in the baseclass. 537 # This is useful for enabling the compiler to optimize calls 538 # that recursively climb the class hierarchy. 539 base_type = scope.parent_type.base_type 540 if scope.parent_scope is base_type.scope.parent_scope: 541 parent_slot = slot.slot_code(base_type.scope) 542 if parent_slot != '0': 543 entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) 544 if entry.visibility != 'extern': 545 return parent_slot 546 return None 547 548 549 def get_slot_function(scope, slot): 550 # Returns the function implementing this slot in the baseclass. 551 # This is useful for enabling the compiler to optimize calls 552 # that recursively climb the class hierarchy. 553 slot_code = slot.slot_code(scope) 554 if slot_code != '0': 555 entry = scope.parent_scope.lookup_here(scope.parent_type.name) 556 if entry.visibility != 'extern': 557 return slot_code 558 return None 559 560 #------------------------------------------------------------------------------------------ 561 # 562 # Signatures for generic Python functions and methods. 563 # 564 #------------------------------------------------------------------------------------------ 565 566 pyfunction_signature = Signature("-*", "O") 567 pymethod_signature = Signature("T*", "O") 568 569 #------------------------------------------------------------------------------------------ 570 # 571 # Signatures for simple Python functions. 572 # 573 #------------------------------------------------------------------------------------------ 574 575 pyfunction_noargs = Signature("-", "O") 576 pyfunction_onearg = Signature("-O", "O") 577 578 #------------------------------------------------------------------------------------------ 579 # 580 # Signatures for the various kinds of function that 581 # can appear in the type object and its substructures. 582 # 583 #------------------------------------------------------------------------------------------ 584 585 unaryfunc = Signature("T", "O") # typedef PyObject * (*unaryfunc)(PyObject *); 586 binaryfunc = Signature("OO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *); 587 ibinaryfunc = Signature("TO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *); 588 ternaryfunc = Signature("OOO", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *); 589 iternaryfunc = Signature("TOO", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *); 590 callfunc = Signature("T*", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *); 591 inquiry = Signature("T", "i") # typedef int (*inquiry)(PyObject *); 592 lenfunc = Signature("T", "z") # typedef Py_ssize_t (*lenfunc)(PyObject *); 593 594 # typedef int (*coercion)(PyObject **, PyObject **); 595 intargfunc = Signature("Ti", "O") # typedef PyObject *(*intargfunc)(PyObject *, int); 596 ssizeargfunc = Signature("Tz", "O") # typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t); 597 intintargfunc = Signature("Tii", "O") # typedef PyObject *(*intintargfunc)(PyObject *, int, int); 598 ssizessizeargfunc = Signature("Tzz", "O") # typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t); 599 intobjargproc = Signature("TiO", 'r') # typedef int(*intobjargproc)(PyObject *, int, PyObject *); 600 ssizeobjargproc = Signature("TzO", 'r') # typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *); 601 intintobjargproc = Signature("TiiO", 'r') # typedef int(*intintobjargproc)(PyObject *, int, int, PyObject *); 602 ssizessizeobjargproc = Signature("TzzO", 'r') # typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); 603 604 intintargproc = Signature("Tii", 'r') 605 ssizessizeargproc = Signature("Tzz", 'r') 606 objargfunc = Signature("TO", "O") 607 objobjargproc = Signature("TOO", 'r') # typedef int (*objobjargproc)(PyObject *, PyObject *, PyObject *); 608 readbufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*readbufferproc)(PyObject *, Py_ssize_t, void **); 609 writebufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*writebufferproc)(PyObject *, Py_ssize_t, void **); 610 segcountproc = Signature("TZ", "z") # typedef Py_ssize_t (*segcountproc)(PyObject *, Py_ssize_t *); 611 charbufferproc = Signature("TzS", "z") # typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **); 612 objargproc = Signature("TO", 'r') # typedef int (*objobjproc)(PyObject *, PyObject *); 613 # typedef int (*visitproc)(PyObject *, void *); 614 # typedef int (*traverseproc)(PyObject *, visitproc, void *); 615 616 destructor = Signature("T", "v") # typedef void (*destructor)(PyObject *); 617 # printfunc = Signature("TFi", 'r') # typedef int (*printfunc)(PyObject *, FILE *, int); 618 # typedef PyObject *(*getattrfunc)(PyObject *, char *); 619 getattrofunc = Signature("TO", "O") # typedef PyObject *(*getattrofunc)(PyObject *, PyObject *); 620 # typedef int (*setattrfunc)(PyObject *, char *, PyObject *); 621 setattrofunc = Signature("TOO", 'r') # typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *); 622 delattrofunc = Signature("TO", 'r') 623 cmpfunc = Signature("TO", "i") # typedef int (*cmpfunc)(PyObject *, PyObject *); 624 reprfunc = Signature("T", "O") # typedef PyObject *(*reprfunc)(PyObject *); 625 hashfunc = Signature("T", "h") # typedef Py_hash_t (*hashfunc)(PyObject *); 626 # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); 627 richcmpfunc = Signature("OOi", "O") # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); 628 getiterfunc = Signature("T", "O") # typedef PyObject *(*getiterfunc) (PyObject *); 629 iternextfunc = Signature("T", "O") # typedef PyObject *(*iternextfunc) (PyObject *); 630 descrgetfunc = Signature("TOO", "O") # typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *); 631 descrsetfunc = Signature("TOO", 'r') # typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); 632 descrdelfunc = Signature("TO", 'r') 633 initproc = Signature("T*", 'r') # typedef int (*initproc)(PyObject *, PyObject *, PyObject *); 634 # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *); 635 # typedef PyObject *(*allocfunc)(struct _typeobject *, int); 636 637 getbufferproc = Signature("TBi", "r") # typedef int (*getbufferproc)(PyObject *, Py_buffer *, int); 638 releasebufferproc = Signature("TB", "v") # typedef void (*releasebufferproc)(PyObject *, Py_buffer *); 639 640 641 #------------------------------------------------------------------------------------------ 642 # 643 # Signatures for accessor methods of properties. 644 # 645 #------------------------------------------------------------------------------------------ 646 647 property_accessor_signatures = { 648 '__get__': Signature("T", "O"), 649 '__set__': Signature("TO", 'r'), 650 '__del__': Signature("T", 'r') 651 } 652 653 #------------------------------------------------------------------------------------------ 654 # 655 # Descriptor tables for the slots of the various type object 656 # substructures, in the order they appear in the structure. 657 # 658 #------------------------------------------------------------------------------------------ 659 660 PyNumberMethods = ( 661 MethodSlot(binaryfunc, "nb_add", "__add__"), 662 MethodSlot(binaryfunc, "nb_subtract", "__sub__"), 663 MethodSlot(binaryfunc, "nb_multiply", "__mul__"), 664 MethodSlot(binaryfunc, "nb_divide", "__div__", py3 = False), 665 MethodSlot(binaryfunc, "nb_remainder", "__mod__"), 666 MethodSlot(binaryfunc, "nb_divmod", "__divmod__"), 667 MethodSlot(ternaryfunc, "nb_power", "__pow__"), 668 MethodSlot(unaryfunc, "nb_negative", "__neg__"), 669 MethodSlot(unaryfunc, "nb_positive", "__pos__"), 670 MethodSlot(unaryfunc, "nb_absolute", "__abs__"), 671 MethodSlot(inquiry, "nb_nonzero", "__nonzero__", py3 = ("nb_bool", "__bool__")), 672 MethodSlot(unaryfunc, "nb_invert", "__invert__"), 673 MethodSlot(binaryfunc, "nb_lshift", "__lshift__"), 674 MethodSlot(binaryfunc, "nb_rshift", "__rshift__"), 675 MethodSlot(binaryfunc, "nb_and", "__and__"), 676 MethodSlot(binaryfunc, "nb_xor", "__xor__"), 677 MethodSlot(binaryfunc, "nb_or", "__or__"), 678 EmptySlot("nb_coerce", py3 = False), 679 MethodSlot(unaryfunc, "nb_int", "__int__", fallback="__long__"), 680 MethodSlot(unaryfunc, "nb_long", "__long__", fallback="__int__", py3 = "<RESERVED>"), 681 MethodSlot(unaryfunc, "nb_float", "__float__"), 682 MethodSlot(unaryfunc, "nb_oct", "__oct__", py3 = False), 683 MethodSlot(unaryfunc, "nb_hex", "__hex__", py3 = False), 684 685 # Added in release 2.0 686 MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__"), 687 MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__"), 688 MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__"), 689 MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", py3 = False), 690 MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__"), 691 MethodSlot(ibinaryfunc, "nb_inplace_power", "__ipow__"), # actually ternaryfunc!!! 692 MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__"), 693 MethodSlot(ibinaryfunc, "nb_inplace_rshift", "__irshift__"), 694 MethodSlot(ibinaryfunc, "nb_inplace_and", "__iand__"), 695 MethodSlot(ibinaryfunc, "nb_inplace_xor", "__ixor__"), 696 MethodSlot(ibinaryfunc, "nb_inplace_or", "__ior__"), 697 698 # Added in release 2.2 699 # The following require the Py_TPFLAGS_HAVE_CLASS flag 700 MethodSlot(binaryfunc, "nb_floor_divide", "__floordiv__"), 701 MethodSlot(binaryfunc, "nb_true_divide", "__truediv__"), 702 MethodSlot(ibinaryfunc, "nb_inplace_floor_divide", "__ifloordiv__"), 703 MethodSlot(ibinaryfunc, "nb_inplace_true_divide", "__itruediv__"), 704 705 # Added in release 2.5 706 MethodSlot(unaryfunc, "nb_index", "__index__", ifdef = "PY_VERSION_HEX >= 0x02050000") 707 ) 708 709 PySequenceMethods = ( 710 MethodSlot(lenfunc, "sq_length", "__len__"), 711 EmptySlot("sq_concat"), # nb_add used instead 712 EmptySlot("sq_repeat"), # nb_multiply used instead 713 SyntheticSlot("sq_item", ["__getitem__"], "0"), #EmptySlot("sq_item"), # mp_subscript used instead 714 MethodSlot(ssizessizeargfunc, "sq_slice", "__getslice__"), 715 EmptySlot("sq_ass_item"), # mp_ass_subscript used instead 716 SyntheticSlot("sq_ass_slice", ["__setslice__", "__delslice__"], "0"), 717 MethodSlot(cmpfunc, "sq_contains", "__contains__"), 718 EmptySlot("sq_inplace_concat"), # nb_inplace_add used instead 719 EmptySlot("sq_inplace_repeat"), # nb_inplace_multiply used instead 720 ) 721 722 PyMappingMethods = ( 723 MethodSlot(lenfunc, "mp_length", "__len__"), 724 MethodSlot(objargfunc, "mp_subscript", "__getitem__"), 725 SyntheticSlot("mp_ass_subscript", ["__setitem__", "__delitem__"], "0"), 726 ) 727 728 PyBufferProcs = ( 729 MethodSlot(readbufferproc, "bf_getreadbuffer", "__getreadbuffer__", py3 = False), 730 MethodSlot(writebufferproc, "bf_getwritebuffer", "__getwritebuffer__", py3 = False), 731 MethodSlot(segcountproc, "bf_getsegcount", "__getsegcount__", py3 = False), 732 MethodSlot(charbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3 = False), 733 734 MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000"), 735 MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000") 736 ) 737 738 #------------------------------------------------------------------------------------------ 739 # 740 # The main slot table. This table contains descriptors for all the 741 # top-level type slots, beginning with tp_dealloc, in the order they 742 # appear in the type object. 743 # 744 #------------------------------------------------------------------------------------------ 745 746 slot_table = ( 747 ConstructorSlot("tp_dealloc", '__dealloc__'), 748 EmptySlot("tp_print"), #MethodSlot(printfunc, "tp_print", "__print__"), 749 EmptySlot("tp_getattr"), 750 EmptySlot("tp_setattr"), 751 MethodSlot(cmpfunc, "tp_compare", "__cmp__", py3 = '<RESERVED>'), 752 MethodSlot(reprfunc, "tp_repr", "__repr__"), 753 754 SuiteSlot(PyNumberMethods, "PyNumberMethods", "tp_as_number"), 755 SuiteSlot(PySequenceMethods, "PySequenceMethods", "tp_as_sequence"), 756 SuiteSlot(PyMappingMethods, "PyMappingMethods", "tp_as_mapping"), 757 758 MethodSlot(hashfunc, "tp_hash", "__hash__", inherited=False), # Py3 checks for __richcmp__ 759 MethodSlot(callfunc, "tp_call", "__call__"), 760 MethodSlot(reprfunc, "tp_str", "__str__"), 761 762 SyntheticSlot("tp_getattro", ["__getattr__","__getattribute__"], "0"), #"PyObject_GenericGetAttr"), 763 SyntheticSlot("tp_setattro", ["__setattr__", "__delattr__"], "0"), #"PyObject_GenericSetAttr"), 764 765 SuiteSlot(PyBufferProcs, "PyBufferProcs", "tp_as_buffer"), 766 767 TypeFlagsSlot("tp_flags"), 768 DocStringSlot("tp_doc"), 769 770 GCDependentSlot("tp_traverse"), 771 GCClearReferencesSlot("tp_clear"), 772 773 # Later -- synthesize a method to split into separate ops? 774 MethodSlot(richcmpfunc, "tp_richcompare", "__richcmp__", inherited=False), # Py3 checks for __hash__ 775 776 EmptySlot("tp_weaklistoffset"), 777 778 MethodSlot(getiterfunc, "tp_iter", "__iter__"), 779 MethodSlot(iternextfunc, "tp_iternext", "__next__"), 780 781 MethodTableSlot("tp_methods"), 782 MemberTableSlot("tp_members"), 783 GetSetSlot("tp_getset"), 784 785 BaseClassSlot("tp_base"), #EmptySlot("tp_base"), 786 EmptySlot("tp_dict"), 787 788 SyntheticSlot("tp_descr_get", ["__get__"], "0"), 789 SyntheticSlot("tp_descr_set", ["__set__", "__delete__"], "0"), 790 791 EmptySlot("tp_dictoffset"), 792 793 MethodSlot(initproc, "tp_init", "__init__"), 794 EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"), 795 InternalMethodSlot("tp_new"), 796 EmptySlot("tp_free"), 797 798 EmptySlot("tp_is_gc"), 799 EmptySlot("tp_bases"), 800 EmptySlot("tp_mro"), 801 EmptySlot("tp_cache"), 802 EmptySlot("tp_subclasses"), 803 EmptySlot("tp_weaklist"), 804 EmptySlot("tp_del"), 805 EmptySlot("tp_version_tag", ifdef="PY_VERSION_HEX >= 0x02060000"), 806 EmptySlot("tp_finalize", ifdef="PY_VERSION_HEX >= 0x030400a1"), 807 ) 808 809 #------------------------------------------------------------------------------------------ 810 # 811 # Descriptors for special methods which don't appear directly 812 # in the type object or its substructures. These methods are 813 # called from slot functions synthesized by Cython. 814 # 815 #------------------------------------------------------------------------------------------ 816 817 MethodSlot(initproc, "", "__cinit__") 818 MethodSlot(destructor, "", "__dealloc__") 819 MethodSlot(objobjargproc, "", "__setitem__") 820 MethodSlot(objargproc, "", "__delitem__") 821 MethodSlot(ssizessizeobjargproc, "", "__setslice__") 822 MethodSlot(ssizessizeargproc, "", "__delslice__") 823 MethodSlot(getattrofunc, "", "__getattr__") 824 MethodSlot(setattrofunc, "", "__setattr__") 825 MethodSlot(delattrofunc, "", "__delattr__") 826 MethodSlot(descrgetfunc, "", "__get__") 827 MethodSlot(descrsetfunc, "", "__set__") 828 MethodSlot(descrdelfunc, "", "__delete__") 829 830 831 # Method flags for python-exposed methods. 832 833 method_noargs = "METH_NOARGS" 834 method_onearg = "METH_O" 835 method_varargs = "METH_VARARGS" 836 method_keywords = "METH_KEYWORDS" 837 method_coexist = "METH_COEXIST" 838