Index: third_party/cython/src/Cython/Compiler/TypeSlots.py |
diff --git a/third_party/cython/src/Cython/Compiler/TypeSlots.py b/third_party/cython/src/Cython/Compiler/TypeSlots.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..176160226aaab4a1c2632a248c8487c4f1da78b8 |
--- /dev/null |
+++ b/third_party/cython/src/Cython/Compiler/TypeSlots.py |
@@ -0,0 +1,837 @@ |
+# |
+# Tables describing slots in the CPython type object |
+# and associated know-how. |
+# |
+ |
+import Naming |
+import PyrexTypes |
+import StringEncoding |
+ |
+invisible = ['__cinit__', '__dealloc__', '__richcmp__', |
+ '__nonzero__', '__bool__'] |
+ |
+class Signature(object): |
+ # Method slot signature descriptor. |
+ # |
+ # has_dummy_arg boolean |
+ # has_generic_args boolean |
+ # fixed_arg_format string |
+ # ret_format string |
+ # error_value string |
+ # |
+ # The formats are strings made up of the following |
+ # characters: |
+ # |
+ # 'O' Python object |
+ # 'T' Python object of the type of 'self' |
+ # 'v' void |
+ # 'p' void * |
+ # 'P' void ** |
+ # 'i' int |
+ # 'b' bint |
+ # 'I' int * |
+ # 'l' long |
+ # 'f' float |
+ # 'd' double |
+ # 'h' Py_hash_t |
+ # 'z' Py_ssize_t |
+ # 'Z' Py_ssize_t * |
+ # 's' char * |
+ # 'S' char ** |
+ # 'r' int used only to signal exception |
+ # 'B' Py_buffer * |
+ # '-' dummy 'self' argument (not used) |
+ # '*' rest of args passed as generic Python |
+ # arg tuple and kw dict (must be last |
+ # char in format string) |
+ |
+ format_map = { |
+ 'O': PyrexTypes.py_object_type, |
+ 'v': PyrexTypes.c_void_type, |
+ 'p': PyrexTypes.c_void_ptr_type, |
+ 'P': PyrexTypes.c_void_ptr_ptr_type, |
+ 'i': PyrexTypes.c_int_type, |
+ 'b': PyrexTypes.c_bint_type, |
+ 'I': PyrexTypes.c_int_ptr_type, |
+ 'l': PyrexTypes.c_long_type, |
+ 'f': PyrexTypes.c_float_type, |
+ 'd': PyrexTypes.c_double_type, |
+ 'h': PyrexTypes.c_py_hash_t_type, |
+ 'z': PyrexTypes.c_py_ssize_t_type, |
+ 'Z': PyrexTypes.c_py_ssize_t_ptr_type, |
+ 's': PyrexTypes.c_char_ptr_type, |
+ 'S': PyrexTypes.c_char_ptr_ptr_type, |
+ 'r': PyrexTypes.c_returncode_type, |
+ 'B': PyrexTypes.c_py_buffer_ptr_type, |
+ # 'T', '-' and '*' are handled otherwise |
+ # and are not looked up in here |
+ } |
+ |
+ type_to_format_map = dict([(type_, format_) |
+ for format_, type_ in format_map.iteritems()]) |
+ |
+ error_value_map = { |
+ 'O': "NULL", |
+ 'T': "NULL", |
+ 'i': "-1", |
+ 'b': "-1", |
+ 'l': "-1", |
+ 'r': "-1", |
+ 'h': "-1", |
+ 'z': "-1", |
+ } |
+ |
+ def __init__(self, arg_format, ret_format): |
+ self.has_dummy_arg = 0 |
+ self.has_generic_args = 0 |
+ if arg_format[:1] == '-': |
+ self.has_dummy_arg = 1 |
+ arg_format = arg_format[1:] |
+ if arg_format[-1:] == '*': |
+ self.has_generic_args = 1 |
+ arg_format = arg_format[:-1] |
+ self.fixed_arg_format = arg_format |
+ self.ret_format = ret_format |
+ self.error_value = self.error_value_map.get(ret_format, None) |
+ self.exception_check = ret_format != 'r' and self.error_value is not None |
+ self.is_staticmethod = False |
+ |
+ def num_fixed_args(self): |
+ return len(self.fixed_arg_format) |
+ |
+ def is_self_arg(self, i): |
+ # argument is 'self' for methods or 'class' for classmethods |
+ return self.fixed_arg_format[i] == 'T' |
+ |
+ def returns_self_type(self): |
+ # return type is same as 'self' argument type |
+ return self.ret_format == 'T' |
+ |
+ def fixed_arg_type(self, i): |
+ return self.format_map[self.fixed_arg_format[i]] |
+ |
+ def return_type(self): |
+ return self.format_map[self.ret_format] |
+ |
+ def format_from_type(self, arg_type): |
+ if arg_type.is_pyobject: |
+ arg_type = PyrexTypes.py_object_type |
+ return self.type_to_format_map[arg_type] |
+ |
+ def exception_value(self): |
+ return self.error_value_map.get(self.ret_format) |
+ |
+ def function_type(self, self_arg_override=None): |
+ # Construct a C function type descriptor for this signature |
+ args = [] |
+ for i in xrange(self.num_fixed_args()): |
+ if self_arg_override is not None and self.is_self_arg(i): |
+ assert isinstance(self_arg_override, PyrexTypes.CFuncTypeArg) |
+ args.append(self_arg_override) |
+ else: |
+ arg_type = self.fixed_arg_type(i) |
+ args.append(PyrexTypes.CFuncTypeArg("", arg_type, None)) |
+ if self_arg_override is not None and self.returns_self_type(): |
+ ret_type = self_arg_override.type |
+ else: |
+ ret_type = self.return_type() |
+ exc_value = self.exception_value() |
+ return PyrexTypes.CFuncType( |
+ ret_type, args, exception_value=exc_value, |
+ exception_check=self.exception_check) |
+ |
+ def method_flags(self): |
+ if self.ret_format == "O": |
+ full_args = self.fixed_arg_format |
+ if self.has_dummy_arg: |
+ full_args = "O" + full_args |
+ if full_args in ["O", "T"]: |
+ if self.has_generic_args: |
+ return [method_varargs, method_keywords] |
+ else: |
+ return [method_noargs] |
+ elif full_args in ["OO", "TO"] and not self.has_generic_args: |
+ return [method_onearg] |
+ |
+ if self.is_staticmethod: |
+ return [method_varargs, method_keywords] |
+ return None |
+ |
+ |
+class SlotDescriptor(object): |
+ # Abstract base class for type slot descriptors. |
+ # |
+ # slot_name string Member name of the slot in the type object |
+ # is_initialised_dynamically Is initialised by code in the module init function |
+ # is_inherited Is inherited by subtypes (see PyType_Ready()) |
+ # py3 Indicates presence of slot in Python 3 |
+ # py2 Indicates presence of slot in Python 2 |
+ # ifdef Full #ifdef string that slot is wrapped in. Using this causes py3, py2 and flags to be ignored.) |
+ |
+ def __init__(self, slot_name, dynamic=False, inherited=False, |
+ py3=True, py2=True, ifdef=None): |
+ self.slot_name = slot_name |
+ self.is_initialised_dynamically = dynamic |
+ self.is_inherited = inherited |
+ self.ifdef = ifdef |
+ self.py3 = py3 |
+ self.py2 = py2 |
+ |
+ def preprocessor_guard_code(self): |
+ ifdef = self.ifdef |
+ py2 = self.py2 |
+ py3 = self.py3 |
+ guard = None |
+ if ifdef: |
+ guard = ("#if %s" % ifdef) |
+ elif not py3 or py3 == '<RESERVED>': |
+ guard = ("#if PY_MAJOR_VERSION < 3") |
+ elif not py2: |
+ guard = ("#if PY_MAJOR_VERSION >= 3") |
+ return guard |
+ |
+ def generate(self, scope, code): |
+ end_pypy_guard = False |
+ if self.is_initialised_dynamically: |
+ value = "0" |
+ else: |
+ value = self.slot_code(scope) |
+ if value == "0" and self.is_inherited: |
+ # PyPy currently has a broken PyType_Ready() that fails to |
+ # inherit some slots. To work around this, we explicitly |
+ # set inherited slots here, but only in PyPy since CPython |
+ # handles this better than we do. |
+ inherited_value = value |
+ current_scope = scope |
+ while (inherited_value == "0" |
+ and current_scope.parent_type |
+ and current_scope.parent_type.base_type |
+ and current_scope.parent_type.base_type.scope): |
+ current_scope = current_scope.parent_type.base_type.scope |
+ inherited_value = self.slot_code(current_scope) |
+ if inherited_value != "0": |
+ code.putln("#if CYTHON_COMPILING_IN_PYPY") |
+ code.putln("%s, /*%s*/" % (inherited_value, self.slot_name)) |
+ code.putln("#else") |
+ end_pypy_guard = True |
+ preprocessor_guard = self.preprocessor_guard_code() |
+ if preprocessor_guard: |
+ code.putln(preprocessor_guard) |
+ code.putln("%s, /*%s*/" % (value, self.slot_name)) |
+ if self.py3 == '<RESERVED>': |
+ code.putln("#else") |
+ code.putln("0, /*reserved*/") |
+ if preprocessor_guard: |
+ code.putln("#endif") |
+ if end_pypy_guard: |
+ code.putln("#endif") |
+ |
+ # Some C implementations have trouble statically |
+ # initialising a global with a pointer to an extern |
+ # function, so we initialise some of the type slots |
+ # in the module init function instead. |
+ |
+ def generate_dynamic_init_code(self, scope, code): |
+ if self.is_initialised_dynamically: |
+ value = self.slot_code(scope) |
+ if value != "0": |
+ code.putln("%s.%s = %s;" % ( |
+ scope.parent_type.typeobj_cname, |
+ self.slot_name, |
+ value |
+ ) |
+ ) |
+ |
+ |
+class FixedSlot(SlotDescriptor): |
+ # Descriptor for a type slot with a fixed value. |
+ # |
+ # value string |
+ |
+ def __init__(self, slot_name, value, py3=True, py2=True, ifdef=None): |
+ SlotDescriptor.__init__(self, slot_name, py3=py3, py2=py2, ifdef=ifdef) |
+ self.value = value |
+ |
+ def slot_code(self, scope): |
+ return self.value |
+ |
+ |
+class EmptySlot(FixedSlot): |
+ # Descriptor for a type slot whose value is always 0. |
+ |
+ def __init__(self, slot_name, py3=True, py2=True, ifdef=None): |
+ FixedSlot.__init__(self, slot_name, "0", py3=py3, py2=py2, ifdef=ifdef) |
+ |
+ |
+class MethodSlot(SlotDescriptor): |
+ # Type slot descriptor for a user-definable method. |
+ # |
+ # signature Signature |
+ # method_name string The __xxx__ name of the method |
+ # alternatives [string] Alternative list of __xxx__ names for the method |
+ |
+ def __init__(self, signature, slot_name, method_name, fallback=None, |
+ py3=True, py2=True, ifdef=None, inherited=True): |
+ SlotDescriptor.__init__(self, slot_name, py3=py3, py2=py2, |
+ ifdef=ifdef, inherited=inherited) |
+ self.signature = signature |
+ self.slot_name = slot_name |
+ self.method_name = method_name |
+ self.alternatives = [] |
+ method_name_to_slot[method_name] = self |
+ # |
+ if fallback: |
+ self.alternatives.append(fallback) |
+ for alt in (self.py2, self.py3): |
+ if isinstance(alt, (tuple, list)): |
+ slot_name, method_name = alt |
+ self.alternatives.append(method_name) |
+ method_name_to_slot[method_name] = self |
+ |
+ def slot_code(self, scope): |
+ entry = scope.lookup_here(self.method_name) |
+ if entry and entry.func_cname: |
+ return entry.func_cname |
+ for method_name in self.alternatives: |
+ entry = scope.lookup_here(method_name) |
+ if entry and entry.func_cname: |
+ return entry.func_cname |
+ return "0" |
+ |
+ |
+class InternalMethodSlot(SlotDescriptor): |
+ # Type slot descriptor for a method which is always |
+ # synthesized by Cython. |
+ # |
+ # slot_name string Member name of the slot in the type object |
+ |
+ def __init__(self, slot_name, **kargs): |
+ SlotDescriptor.__init__(self, slot_name, **kargs) |
+ |
+ def slot_code(self, scope): |
+ return scope.mangle_internal(self.slot_name) |
+ |
+ |
+class GCDependentSlot(InternalMethodSlot): |
+ # Descriptor for a slot whose value depends on whether |
+ # the type participates in GC. |
+ |
+ def __init__(self, slot_name, **kargs): |
+ InternalMethodSlot.__init__(self, slot_name, **kargs) |
+ |
+ def slot_code(self, scope): |
+ if not scope.needs_gc(): |
+ return "0" |
+ if not scope.has_cyclic_pyobject_attrs: |
+ # if the type does not have GC relevant object attributes, it can |
+ # delegate GC methods to its parent - iff the parent functions |
+ # are defined in the same module |
+ parent_type_scope = scope.parent_type.base_type.scope |
+ if scope.parent_scope is parent_type_scope.parent_scope: |
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) |
+ if entry.visibility != 'extern': |
+ return self.slot_code(parent_type_scope) |
+ return InternalMethodSlot.slot_code(self, scope) |
+ |
+ |
+class GCClearReferencesSlot(GCDependentSlot): |
+ |
+ def slot_code(self, scope): |
+ if scope.needs_tp_clear(): |
+ return GCDependentSlot.slot_code(self, scope) |
+ return "0" |
+ |
+ |
+class ConstructorSlot(InternalMethodSlot): |
+ # Descriptor for tp_new and tp_dealloc. |
+ |
+ def __init__(self, slot_name, method, **kargs): |
+ InternalMethodSlot.__init__(self, slot_name, **kargs) |
+ self.method = method |
+ |
+ def slot_code(self, scope): |
+ if (self.slot_name != 'tp_new' |
+ and scope.parent_type.base_type |
+ and not scope.has_pyobject_attrs |
+ and not scope.has_memoryview_attrs |
+ and not scope.lookup_here(self.method)): |
+ # if the type does not have object attributes, it can |
+ # delegate GC methods to its parent - iff the parent |
+ # functions are defined in the same module |
+ parent_type_scope = scope.parent_type.base_type.scope |
+ if scope.parent_scope is parent_type_scope.parent_scope: |
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) |
+ if entry.visibility != 'extern': |
+ return self.slot_code(parent_type_scope) |
+ return InternalMethodSlot.slot_code(self, scope) |
+ |
+ |
+class SyntheticSlot(InternalMethodSlot): |
+ # Type slot descriptor for a synthesized method which |
+ # dispatches to one or more user-defined methods depending |
+ # on its arguments. If none of the relevant methods are |
+ # defined, the method will not be synthesized and an |
+ # alternative default value will be placed in the type |
+ # slot. |
+ |
+ def __init__(self, slot_name, user_methods, default_value, **kargs): |
+ InternalMethodSlot.__init__(self, slot_name, **kargs) |
+ self.user_methods = user_methods |
+ self.default_value = default_value |
+ |
+ def slot_code(self, scope): |
+ if scope.defines_any(self.user_methods): |
+ return InternalMethodSlot.slot_code(self, scope) |
+ else: |
+ return self.default_value |
+ |
+ |
+class TypeFlagsSlot(SlotDescriptor): |
+ # Descriptor for the type flags slot. |
+ |
+ def slot_code(self, scope): |
+ value = "Py_TPFLAGS_DEFAULT" |
+ if scope.directives['type_version_tag']: |
+ # it's not in 'Py_TPFLAGS_DEFAULT' in Py2 |
+ value += "|Py_TPFLAGS_HAVE_VERSION_TAG" |
+ else: |
+ # it's enabled in 'Py_TPFLAGS_DEFAULT' in Py3 |
+ value = "(%s&~Py_TPFLAGS_HAVE_VERSION_TAG)" % value |
+ value += "|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_NEWBUFFER" |
+ if not scope.parent_type.is_final_type: |
+ value += "|Py_TPFLAGS_BASETYPE" |
+ if scope.needs_gc(): |
+ value += "|Py_TPFLAGS_HAVE_GC" |
+ return value |
+ |
+ |
+class DocStringSlot(SlotDescriptor): |
+ # Descriptor for the docstring slot. |
+ |
+ def slot_code(self, scope): |
+ if scope.doc is not None: |
+ if scope.doc.is_unicode: |
+ doc = scope.doc.utf8encode() |
+ else: |
+ doc = scope.doc.byteencode() |
+ return '__Pyx_DOCSTR("%s")' % StringEncoding.escape_byte_string(doc) |
+ else: |
+ return "0" |
+ |
+ |
+class SuiteSlot(SlotDescriptor): |
+ # Descriptor for a substructure of the type object. |
+ # |
+ # sub_slots [SlotDescriptor] |
+ |
+ def __init__(self, sub_slots, slot_type, slot_name): |
+ SlotDescriptor.__init__(self, slot_name) |
+ self.sub_slots = sub_slots |
+ self.slot_type = slot_type |
+ substructures.append(self) |
+ |
+ def is_empty(self, scope): |
+ for slot in self.sub_slots: |
+ if slot.slot_code(scope) != "0": |
+ return False |
+ return True |
+ |
+ def substructure_cname(self, scope): |
+ return "%s%s_%s" % (Naming.pyrex_prefix, self.slot_name, scope.class_name) |
+ |
+ def slot_code(self, scope): |
+ if not self.is_empty(scope): |
+ return "&%s" % self.substructure_cname(scope) |
+ return "0" |
+ |
+ def generate_substructure(self, scope, code): |
+ if not self.is_empty(scope): |
+ code.putln("") |
+ code.putln( |
+ "static %s %s = {" % ( |
+ self.slot_type, |
+ self.substructure_cname(scope))) |
+ for slot in self.sub_slots: |
+ slot.generate(scope, code) |
+ code.putln("};") |
+ |
+substructures = [] # List of all SuiteSlot instances |
+ |
+class MethodTableSlot(SlotDescriptor): |
+ # Slot descriptor for the method table. |
+ |
+ def slot_code(self, scope): |
+ if scope.pyfunc_entries: |
+ return scope.method_table_cname |
+ else: |
+ return "0" |
+ |
+ |
+class MemberTableSlot(SlotDescriptor): |
+ # Slot descriptor for the table of Python-accessible attributes. |
+ |
+ def slot_code(self, scope): |
+ return "0" |
+ |
+ |
+class GetSetSlot(SlotDescriptor): |
+ # Slot descriptor for the table of attribute get & set methods. |
+ |
+ def slot_code(self, scope): |
+ if scope.property_entries: |
+ return scope.getset_table_cname |
+ else: |
+ return "0" |
+ |
+ |
+class BaseClassSlot(SlotDescriptor): |
+ # Slot descriptor for the base class slot. |
+ |
+ def __init__(self, name): |
+ SlotDescriptor.__init__(self, name, dynamic = 1) |
+ |
+ def generate_dynamic_init_code(self, scope, code): |
+ base_type = scope.parent_type.base_type |
+ if base_type: |
+ code.putln("%s.%s = %s;" % ( |
+ scope.parent_type.typeobj_cname, |
+ self.slot_name, |
+ base_type.typeptr_cname)) |
+ |
+ |
+# The following dictionary maps __xxx__ method names to slot descriptors. |
+ |
+method_name_to_slot = {} |
+ |
+## The following slots are (or could be) initialised with an |
+## extern function pointer. |
+# |
+#slots_initialised_from_extern = ( |
+# "tp_free", |
+#) |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# Utility functions for accessing slot table data structures |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+def get_special_method_signature(name): |
+ # Given a method name, if it is a special method, |
+ # return its signature, else return None. |
+ slot = method_name_to_slot.get(name) |
+ if slot: |
+ return slot.signature |
+ else: |
+ return None |
+ |
+ |
+def get_property_accessor_signature(name): |
+ # Return signature of accessor for an extension type |
+ # property, else None. |
+ return property_accessor_signatures.get(name) |
+ |
+ |
+def get_base_slot_function(scope, slot): |
+ # Returns the function implementing this slot in the baseclass. |
+ # This is useful for enabling the compiler to optimize calls |
+ # that recursively climb the class hierarchy. |
+ base_type = scope.parent_type.base_type |
+ if scope.parent_scope is base_type.scope.parent_scope: |
+ parent_slot = slot.slot_code(base_type.scope) |
+ if parent_slot != '0': |
+ entry = scope.parent_scope.lookup_here(scope.parent_type.base_type.name) |
+ if entry.visibility != 'extern': |
+ return parent_slot |
+ return None |
+ |
+ |
+def get_slot_function(scope, slot): |
+ # Returns the function implementing this slot in the baseclass. |
+ # This is useful for enabling the compiler to optimize calls |
+ # that recursively climb the class hierarchy. |
+ slot_code = slot.slot_code(scope) |
+ if slot_code != '0': |
+ entry = scope.parent_scope.lookup_here(scope.parent_type.name) |
+ if entry.visibility != 'extern': |
+ return slot_code |
+ return None |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# Signatures for generic Python functions and methods. |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+pyfunction_signature = Signature("-*", "O") |
+pymethod_signature = Signature("T*", "O") |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# Signatures for simple Python functions. |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+pyfunction_noargs = Signature("-", "O") |
+pyfunction_onearg = Signature("-O", "O") |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# Signatures for the various kinds of function that |
+# can appear in the type object and its substructures. |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+unaryfunc = Signature("T", "O") # typedef PyObject * (*unaryfunc)(PyObject *); |
+binaryfunc = Signature("OO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *); |
+ibinaryfunc = Signature("TO", "O") # typedef PyObject * (*binaryfunc)(PyObject *, PyObject *); |
+ternaryfunc = Signature("OOO", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *); |
+iternaryfunc = Signature("TOO", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *); |
+callfunc = Signature("T*", "O") # typedef PyObject * (*ternaryfunc)(PyObject *, PyObject *, PyObject *); |
+inquiry = Signature("T", "i") # typedef int (*inquiry)(PyObject *); |
+lenfunc = Signature("T", "z") # typedef Py_ssize_t (*lenfunc)(PyObject *); |
+ |
+ # typedef int (*coercion)(PyObject **, PyObject **); |
+intargfunc = Signature("Ti", "O") # typedef PyObject *(*intargfunc)(PyObject *, int); |
+ssizeargfunc = Signature("Tz", "O") # typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t); |
+intintargfunc = Signature("Tii", "O") # typedef PyObject *(*intintargfunc)(PyObject *, int, int); |
+ssizessizeargfunc = Signature("Tzz", "O") # typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t); |
+intobjargproc = Signature("TiO", 'r') # typedef int(*intobjargproc)(PyObject *, int, PyObject *); |
+ssizeobjargproc = Signature("TzO", 'r') # typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *); |
+intintobjargproc = Signature("TiiO", 'r') # typedef int(*intintobjargproc)(PyObject *, int, int, PyObject *); |
+ssizessizeobjargproc = Signature("TzzO", 'r') # typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *); |
+ |
+intintargproc = Signature("Tii", 'r') |
+ssizessizeargproc = Signature("Tzz", 'r') |
+objargfunc = Signature("TO", "O") |
+objobjargproc = Signature("TOO", 'r') # typedef int (*objobjargproc)(PyObject *, PyObject *, PyObject *); |
+readbufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*readbufferproc)(PyObject *, Py_ssize_t, void **); |
+writebufferproc = Signature("TzP", "z") # typedef Py_ssize_t (*writebufferproc)(PyObject *, Py_ssize_t, void **); |
+segcountproc = Signature("TZ", "z") # typedef Py_ssize_t (*segcountproc)(PyObject *, Py_ssize_t *); |
+charbufferproc = Signature("TzS", "z") # typedef Py_ssize_t (*charbufferproc)(PyObject *, Py_ssize_t, char **); |
+objargproc = Signature("TO", 'r') # typedef int (*objobjproc)(PyObject *, PyObject *); |
+ # typedef int (*visitproc)(PyObject *, void *); |
+ # typedef int (*traverseproc)(PyObject *, visitproc, void *); |
+ |
+destructor = Signature("T", "v") # typedef void (*destructor)(PyObject *); |
+# printfunc = Signature("TFi", 'r') # typedef int (*printfunc)(PyObject *, FILE *, int); |
+ # typedef PyObject *(*getattrfunc)(PyObject *, char *); |
+getattrofunc = Signature("TO", "O") # typedef PyObject *(*getattrofunc)(PyObject *, PyObject *); |
+ # typedef int (*setattrfunc)(PyObject *, char *, PyObject *); |
+setattrofunc = Signature("TOO", 'r') # typedef int (*setattrofunc)(PyObject *, PyObject *, PyObject *); |
+delattrofunc = Signature("TO", 'r') |
+cmpfunc = Signature("TO", "i") # typedef int (*cmpfunc)(PyObject *, PyObject *); |
+reprfunc = Signature("T", "O") # typedef PyObject *(*reprfunc)(PyObject *); |
+hashfunc = Signature("T", "h") # typedef Py_hash_t (*hashfunc)(PyObject *); |
+ # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); |
+richcmpfunc = Signature("OOi", "O") # typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); |
+getiterfunc = Signature("T", "O") # typedef PyObject *(*getiterfunc) (PyObject *); |
+iternextfunc = Signature("T", "O") # typedef PyObject *(*iternextfunc) (PyObject *); |
+descrgetfunc = Signature("TOO", "O") # typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *); |
+descrsetfunc = Signature("TOO", 'r') # typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); |
+descrdelfunc = Signature("TO", 'r') |
+initproc = Signature("T*", 'r') # typedef int (*initproc)(PyObject *, PyObject *, PyObject *); |
+ # typedef PyObject *(*newfunc)(struct _typeobject *, PyObject *, PyObject *); |
+ # typedef PyObject *(*allocfunc)(struct _typeobject *, int); |
+ |
+getbufferproc = Signature("TBi", "r") # typedef int (*getbufferproc)(PyObject *, Py_buffer *, int); |
+releasebufferproc = Signature("TB", "v") # typedef void (*releasebufferproc)(PyObject *, Py_buffer *); |
+ |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# Signatures for accessor methods of properties. |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+property_accessor_signatures = { |
+ '__get__': Signature("T", "O"), |
+ '__set__': Signature("TO", 'r'), |
+ '__del__': Signature("T", 'r') |
+} |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# Descriptor tables for the slots of the various type object |
+# substructures, in the order they appear in the structure. |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+PyNumberMethods = ( |
+ MethodSlot(binaryfunc, "nb_add", "__add__"), |
+ MethodSlot(binaryfunc, "nb_subtract", "__sub__"), |
+ MethodSlot(binaryfunc, "nb_multiply", "__mul__"), |
+ MethodSlot(binaryfunc, "nb_divide", "__div__", py3 = False), |
+ MethodSlot(binaryfunc, "nb_remainder", "__mod__"), |
+ MethodSlot(binaryfunc, "nb_divmod", "__divmod__"), |
+ MethodSlot(ternaryfunc, "nb_power", "__pow__"), |
+ MethodSlot(unaryfunc, "nb_negative", "__neg__"), |
+ MethodSlot(unaryfunc, "nb_positive", "__pos__"), |
+ MethodSlot(unaryfunc, "nb_absolute", "__abs__"), |
+ MethodSlot(inquiry, "nb_nonzero", "__nonzero__", py3 = ("nb_bool", "__bool__")), |
+ MethodSlot(unaryfunc, "nb_invert", "__invert__"), |
+ MethodSlot(binaryfunc, "nb_lshift", "__lshift__"), |
+ MethodSlot(binaryfunc, "nb_rshift", "__rshift__"), |
+ MethodSlot(binaryfunc, "nb_and", "__and__"), |
+ MethodSlot(binaryfunc, "nb_xor", "__xor__"), |
+ MethodSlot(binaryfunc, "nb_or", "__or__"), |
+ EmptySlot("nb_coerce", py3 = False), |
+ MethodSlot(unaryfunc, "nb_int", "__int__", fallback="__long__"), |
+ MethodSlot(unaryfunc, "nb_long", "__long__", fallback="__int__", py3 = "<RESERVED>"), |
+ MethodSlot(unaryfunc, "nb_float", "__float__"), |
+ MethodSlot(unaryfunc, "nb_oct", "__oct__", py3 = False), |
+ MethodSlot(unaryfunc, "nb_hex", "__hex__", py3 = False), |
+ |
+ # Added in release 2.0 |
+ MethodSlot(ibinaryfunc, "nb_inplace_add", "__iadd__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_subtract", "__isub__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_multiply", "__imul__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_divide", "__idiv__", py3 = False), |
+ MethodSlot(ibinaryfunc, "nb_inplace_remainder", "__imod__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_power", "__ipow__"), # actually ternaryfunc!!! |
+ MethodSlot(ibinaryfunc, "nb_inplace_lshift", "__ilshift__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_rshift", "__irshift__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_and", "__iand__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_xor", "__ixor__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_or", "__ior__"), |
+ |
+ # Added in release 2.2 |
+ # The following require the Py_TPFLAGS_HAVE_CLASS flag |
+ MethodSlot(binaryfunc, "nb_floor_divide", "__floordiv__"), |
+ MethodSlot(binaryfunc, "nb_true_divide", "__truediv__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_floor_divide", "__ifloordiv__"), |
+ MethodSlot(ibinaryfunc, "nb_inplace_true_divide", "__itruediv__"), |
+ |
+ # Added in release 2.5 |
+ MethodSlot(unaryfunc, "nb_index", "__index__", ifdef = "PY_VERSION_HEX >= 0x02050000") |
+) |
+ |
+PySequenceMethods = ( |
+ MethodSlot(lenfunc, "sq_length", "__len__"), |
+ EmptySlot("sq_concat"), # nb_add used instead |
+ EmptySlot("sq_repeat"), # nb_multiply used instead |
+ SyntheticSlot("sq_item", ["__getitem__"], "0"), #EmptySlot("sq_item"), # mp_subscript used instead |
+ MethodSlot(ssizessizeargfunc, "sq_slice", "__getslice__"), |
+ EmptySlot("sq_ass_item"), # mp_ass_subscript used instead |
+ SyntheticSlot("sq_ass_slice", ["__setslice__", "__delslice__"], "0"), |
+ MethodSlot(cmpfunc, "sq_contains", "__contains__"), |
+ EmptySlot("sq_inplace_concat"), # nb_inplace_add used instead |
+ EmptySlot("sq_inplace_repeat"), # nb_inplace_multiply used instead |
+) |
+ |
+PyMappingMethods = ( |
+ MethodSlot(lenfunc, "mp_length", "__len__"), |
+ MethodSlot(objargfunc, "mp_subscript", "__getitem__"), |
+ SyntheticSlot("mp_ass_subscript", ["__setitem__", "__delitem__"], "0"), |
+) |
+ |
+PyBufferProcs = ( |
+ MethodSlot(readbufferproc, "bf_getreadbuffer", "__getreadbuffer__", py3 = False), |
+ MethodSlot(writebufferproc, "bf_getwritebuffer", "__getwritebuffer__", py3 = False), |
+ MethodSlot(segcountproc, "bf_getsegcount", "__getsegcount__", py3 = False), |
+ MethodSlot(charbufferproc, "bf_getcharbuffer", "__getcharbuffer__", py3 = False), |
+ |
+ MethodSlot(getbufferproc, "bf_getbuffer", "__getbuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000"), |
+ MethodSlot(releasebufferproc, "bf_releasebuffer", "__releasebuffer__", ifdef = "PY_VERSION_HEX >= 0x02060000") |
+) |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# The main slot table. This table contains descriptors for all the |
+# top-level type slots, beginning with tp_dealloc, in the order they |
+# appear in the type object. |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+slot_table = ( |
+ ConstructorSlot("tp_dealloc", '__dealloc__'), |
+ EmptySlot("tp_print"), #MethodSlot(printfunc, "tp_print", "__print__"), |
+ EmptySlot("tp_getattr"), |
+ EmptySlot("tp_setattr"), |
+ MethodSlot(cmpfunc, "tp_compare", "__cmp__", py3 = '<RESERVED>'), |
+ MethodSlot(reprfunc, "tp_repr", "__repr__"), |
+ |
+ SuiteSlot(PyNumberMethods, "PyNumberMethods", "tp_as_number"), |
+ SuiteSlot(PySequenceMethods, "PySequenceMethods", "tp_as_sequence"), |
+ SuiteSlot(PyMappingMethods, "PyMappingMethods", "tp_as_mapping"), |
+ |
+ MethodSlot(hashfunc, "tp_hash", "__hash__", inherited=False), # Py3 checks for __richcmp__ |
+ MethodSlot(callfunc, "tp_call", "__call__"), |
+ MethodSlot(reprfunc, "tp_str", "__str__"), |
+ |
+ SyntheticSlot("tp_getattro", ["__getattr__","__getattribute__"], "0"), #"PyObject_GenericGetAttr"), |
+ SyntheticSlot("tp_setattro", ["__setattr__", "__delattr__"], "0"), #"PyObject_GenericSetAttr"), |
+ |
+ SuiteSlot(PyBufferProcs, "PyBufferProcs", "tp_as_buffer"), |
+ |
+ TypeFlagsSlot("tp_flags"), |
+ DocStringSlot("tp_doc"), |
+ |
+ GCDependentSlot("tp_traverse"), |
+ GCClearReferencesSlot("tp_clear"), |
+ |
+ # Later -- synthesize a method to split into separate ops? |
+ MethodSlot(richcmpfunc, "tp_richcompare", "__richcmp__", inherited=False), # Py3 checks for __hash__ |
+ |
+ EmptySlot("tp_weaklistoffset"), |
+ |
+ MethodSlot(getiterfunc, "tp_iter", "__iter__"), |
+ MethodSlot(iternextfunc, "tp_iternext", "__next__"), |
+ |
+ MethodTableSlot("tp_methods"), |
+ MemberTableSlot("tp_members"), |
+ GetSetSlot("tp_getset"), |
+ |
+ BaseClassSlot("tp_base"), #EmptySlot("tp_base"), |
+ EmptySlot("tp_dict"), |
+ |
+ SyntheticSlot("tp_descr_get", ["__get__"], "0"), |
+ SyntheticSlot("tp_descr_set", ["__set__", "__delete__"], "0"), |
+ |
+ EmptySlot("tp_dictoffset"), |
+ |
+ MethodSlot(initproc, "tp_init", "__init__"), |
+ EmptySlot("tp_alloc"), #FixedSlot("tp_alloc", "PyType_GenericAlloc"), |
+ InternalMethodSlot("tp_new"), |
+ EmptySlot("tp_free"), |
+ |
+ EmptySlot("tp_is_gc"), |
+ EmptySlot("tp_bases"), |
+ EmptySlot("tp_mro"), |
+ EmptySlot("tp_cache"), |
+ EmptySlot("tp_subclasses"), |
+ EmptySlot("tp_weaklist"), |
+ EmptySlot("tp_del"), |
+ EmptySlot("tp_version_tag", ifdef="PY_VERSION_HEX >= 0x02060000"), |
+ EmptySlot("tp_finalize", ifdef="PY_VERSION_HEX >= 0x030400a1"), |
+) |
+ |
+#------------------------------------------------------------------------------------------ |
+# |
+# Descriptors for special methods which don't appear directly |
+# in the type object or its substructures. These methods are |
+# called from slot functions synthesized by Cython. |
+# |
+#------------------------------------------------------------------------------------------ |
+ |
+MethodSlot(initproc, "", "__cinit__") |
+MethodSlot(destructor, "", "__dealloc__") |
+MethodSlot(objobjargproc, "", "__setitem__") |
+MethodSlot(objargproc, "", "__delitem__") |
+MethodSlot(ssizessizeobjargproc, "", "__setslice__") |
+MethodSlot(ssizessizeargproc, "", "__delslice__") |
+MethodSlot(getattrofunc, "", "__getattr__") |
+MethodSlot(setattrofunc, "", "__setattr__") |
+MethodSlot(delattrofunc, "", "__delattr__") |
+MethodSlot(descrgetfunc, "", "__get__") |
+MethodSlot(descrsetfunc, "", "__set__") |
+MethodSlot(descrdelfunc, "", "__delete__") |
+ |
+ |
+# Method flags for python-exposed methods. |
+ |
+method_noargs = "METH_NOARGS" |
+method_onearg = "METH_O" |
+method_varargs = "METH_VARARGS" |
+method_keywords = "METH_KEYWORDS" |
+method_coexist = "METH_COEXIST" |