1""" 2The class PyTypeObject generates a PyTypeObject structure contents. 3""" 4 5class PyTypeObject(object): 6 TEMPLATE = ( 7 'PyTypeObject %(typestruct)s = {\n' 8 ' PyObject_HEAD_INIT(NULL)\n' 9 ' 0, /* ob_size */\n' 10 ' (char *) "%(tp_name)s", /* tp_name */\n' 11 ' %(tp_basicsize)s, /* tp_basicsize */\n' 12 ' 0, /* tp_itemsize */\n' 13 ' /* methods */\n' 14 ' (destructor)%(tp_dealloc)s, /* tp_dealloc */\n' 15 ' (printfunc)0, /* tp_print */\n' 16 ' (getattrfunc)%(tp_getattr)s, /* tp_getattr */\n' 17 ' (setattrfunc)%(tp_setattr)s, /* tp_setattr */\n' 18 ' (cmpfunc)%(tp_compare)s, /* tp_compare */\n' 19 ' (reprfunc)%(tp_repr)s, /* tp_repr */\n' 20 ' (PyNumberMethods*)%(tp_as_number)s, /* tp_as_number */\n' 21 ' (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n' 22 ' (PyMappingMethods*)%(tp_as_mapping)s, /* tp_as_mapping */\n' 23 ' (hashfunc)%(tp_hash)s, /* tp_hash */\n' 24 ' (ternaryfunc)%(tp_call)s, /* tp_call */\n' 25 ' (reprfunc)%(tp_str)s, /* tp_str */\n' 26 ' (getattrofunc)%(tp_getattro)s, /* tp_getattro */\n' 27 ' (setattrofunc)%(tp_setattro)s, /* tp_setattro */\n' 28 ' (PyBufferProcs*)%(tp_as_buffer)s, /* tp_as_buffer */\n' 29 ' %(tp_flags)s, /* tp_flags */\n' 30 ' %(tp_doc)s, /* Documentation string */\n' 31 ' (traverseproc)%(tp_traverse)s, /* tp_traverse */\n' 32 ' (inquiry)%(tp_clear)s, /* tp_clear */\n' 33 ' (richcmpfunc)%(tp_richcompare)s, /* tp_richcompare */\n' 34 ' %(tp_weaklistoffset)s, /* tp_weaklistoffset */\n' 35 ' (getiterfunc)%(tp_iter)s, /* tp_iter */\n' 36 ' (iternextfunc)%(tp_iternext)s, /* tp_iternext */\n' 37 ' (struct PyMethodDef*)%(tp_methods)s, /* tp_methods */\n' 38 ' (struct PyMemberDef*)0, /* tp_members */\n' 39 ' %(tp_getset)s, /* tp_getset */\n' 40 ' NULL, /* tp_base */\n' 41 ' NULL, /* tp_dict */\n' 42 ' (descrgetfunc)%(tp_descr_get)s, /* tp_descr_get */\n' 43 ' (descrsetfunc)%(tp_descr_set)s, /* tp_descr_set */\n' 44 ' %(tp_dictoffset)s, /* tp_dictoffset */\n' 45 ' (initproc)%(tp_init)s, /* tp_init */\n' 46 ' (allocfunc)%(tp_alloc)s, /* tp_alloc */\n' 47 ' (newfunc)%(tp_new)s, /* tp_new */\n' 48 ' (freefunc)%(tp_free)s, /* tp_free */\n' 49 ' (inquiry)%(tp_is_gc)s, /* tp_is_gc */\n' 50 ' NULL, /* tp_bases */\n' 51 ' NULL, /* tp_mro */\n' 52 ' NULL, /* tp_cache */\n' 53 ' NULL, /* tp_subclasses */\n' 54 ' NULL, /* tp_weaklist */\n' 55 ' (destructor) NULL /* tp_del */\n' 56 '};\n' 57 ) 58 59 def __init__(self): 60 self.slots = {} 61 62 def generate(self, code_sink): 63 """ 64 Generates the type structure. All slots are optional except 65 'tp_name', 'tp_basicsize', and the pseudo-slot 'typestruct'. 66 """ 67 68 slots = dict(self.slots) 69 70 slots.setdefault('tp_dealloc', 'NULL') 71 slots.setdefault('tp_getattr', 'NULL') 72 slots.setdefault('tp_setattr', 'NULL') 73 slots.setdefault('tp_compare', 'NULL') 74 slots.setdefault('tp_repr', 'NULL') 75 slots.setdefault('tp_as_number', 'NULL') 76 slots.setdefault('tp_as_sequence', 'NULL') 77 slots.setdefault('tp_as_mapping', 'NULL') 78 slots.setdefault('tp_hash', 'NULL') 79 slots.setdefault('tp_call', 'NULL') 80 slots.setdefault('tp_str', 'NULL') 81 slots.setdefault('tp_getattro', 'NULL') 82 slots.setdefault('tp_setattro', 'NULL') 83 slots.setdefault('tp_as_buffer', 'NULL') 84 slots.setdefault('tp_flags', 'Py_TPFLAGS_DEFAULT') 85 slots.setdefault('tp_doc', 'NULL') 86 slots.setdefault('tp_traverse', 'NULL') 87 slots.setdefault('tp_clear', 'NULL') 88 slots.setdefault('tp_richcompare', 'NULL') 89 slots.setdefault('tp_weaklistoffset', '0') 90 slots.setdefault('tp_iter', 'NULL') 91 slots.setdefault('tp_iternext', 'NULL') 92 slots.setdefault('tp_methods', 'NULL') 93 slots.setdefault('tp_getset', 'NULL') 94 slots.setdefault('tp_descr_get', 'NULL') 95 slots.setdefault('tp_descr_set', 'NULL') 96 slots.setdefault('tp_dictoffset', '0') 97 slots.setdefault('tp_init', 'NULL') 98 slots.setdefault('tp_alloc', 'PyType_GenericAlloc') 99 slots.setdefault('tp_new', 'PyType_GenericNew') 100 slots.setdefault('tp_free', '0') 101 slots.setdefault('tp_is_gc', 'NULL') 102 103 code_sink.writeln(self.TEMPLATE % slots) 104 105 106class PyNumberMethods(object): 107 TEMPLATE = ( 108 'static PyNumberMethods %(variable)s = {\n' 109 ' (binaryfunc) %(nb_add)s,\n' 110 ' (binaryfunc) %(nb_subtract)s,\n' 111 ' (binaryfunc) %(nb_multiply)s,\n' 112 ' (binaryfunc) %(nb_divide)s,\n' 113 ' (binaryfunc) %(nb_remainder)s,\n' 114 ' (binaryfunc) %(nb_divmod)s,\n' 115 ' (ternaryfunc) %(nb_power)s,\n' 116 ' (unaryfunc) %(nb_negative)s,\n' 117 ' (unaryfunc) %(nb_positive)s,\n' 118 ' (unaryfunc) %(nb_absolute)s,\n' 119 ' (inquiry) %(nb_nonzero)s,\n' 120 ' (unaryfunc) %(nb_invert)s,\n' 121 ' (binaryfunc) %(nb_lshift)s,\n' 122 ' (binaryfunc) %(nb_rshift)s,\n' 123 ' (binaryfunc) %(nb_and)s,\n' 124 ' (binaryfunc) %(nb_xor)s,\n' 125 ' (binaryfunc) %(nb_or)s,\n' 126 ' (coercion) %(nb_coerce)s,\n' 127 ' (unaryfunc) %(nb_int)s,\n' 128 ' (unaryfunc) %(nb_long)s,\n' 129 ' (unaryfunc) %(nb_float)s,\n' 130 ' (unaryfunc) %(nb_oct)s,\n' 131 ' (unaryfunc) %(nb_hex)s,\n' 132 ' /* Added in release 2.0 */\n' 133 ' (binaryfunc) %(nb_inplace_add)s,\n' 134 ' (binaryfunc) %(nb_inplace_subtract)s,\n' 135 ' (binaryfunc) %(nb_inplace_multiply)s,\n' 136 ' (binaryfunc) %(nb_inplace_divide)s,\n' 137 ' (binaryfunc) %(nb_inplace_remainder)s,\n' 138 ' (ternaryfunc) %(nb_inplace_power)s,\n' 139 ' (binaryfunc) %(nb_inplace_lshift)s,\n' 140 ' (binaryfunc) %(nb_inplace_rshift)s,\n' 141 ' (binaryfunc) %(nb_inplace_and)s,\n' 142 ' (binaryfunc) %(nb_inplace_xor)s,\n' 143 ' (binaryfunc) %(nb_inplace_or)s,\n' 144 '\n' 145 ' /* Added in release 2.2 */\n' 146 ' /* The following require the Py_TPFLAGS_HAVE_CLASS flag */\n' 147 ' (binaryfunc) %(nb_floor_divide)s,\n' 148 ' (binaryfunc) %(nb_true_divide)s,\n' 149 ' (binaryfunc) %(nb_inplace_floor_divide)s,\n' 150 ' (binaryfunc) %(nb_inplace_true_divide)s,\n' 151 '\n' 152 '#if PY_VERSION_HEX >= 0x020500F0\n' 153 ' /* Added in release 2.5 */\n' 154 ' (unaryfunc) %(nb_index)s,\n' 155 '\n' 156 '#endif\n' 157 '};\n' 158 ) 159 160 def __init__(self): 161 self.slots = {} 162 163 def generate(self, code_sink): 164 """ 165 Generates the structure. All slots are optional except 'variable'. 166 """ 167 168 slots = dict(self.slots) 169 170 slots.setdefault('nb_add', 'NULL') 171 slots.setdefault('nb_subtract', 'NULL') 172 slots.setdefault('nb_multiply', 'NULL') 173 slots.setdefault('nb_divide', 'NULL') 174 slots.setdefault('nb_remainder', 'NULL') 175 slots.setdefault('nb_divmod', 'NULL') 176 slots.setdefault('nb_power', 'NULL') 177 slots.setdefault('nb_negative', 'NULL') 178 slots.setdefault('nb_positive', 'NULL') 179 slots.setdefault('nb_absolute', 'NULL') 180 slots.setdefault('nb_nonzero', 'NULL') 181 slots.setdefault('nb_invert', 'NULL') 182 slots.setdefault('nb_lshift', 'NULL') 183 slots.setdefault('nb_rshift', 'NULL') 184 slots.setdefault('nb_and', 'NULL') 185 slots.setdefault('nb_xor', 'NULL') 186 slots.setdefault('nb_or', 'NULL') 187 slots.setdefault('nb_coerce', 'NULL') 188 slots.setdefault('nb_int', 'NULL') 189 slots.setdefault('nb_long', 'NULL') 190 slots.setdefault('nb_float', 'NULL') 191 slots.setdefault('nb_oct', 'NULL') 192 slots.setdefault('nb_hex', 'NULL') 193 slots.setdefault('nb_inplace_add', 'NULL') 194 slots.setdefault('nb_inplace_subtract', 'NULL') 195 slots.setdefault('nb_inplace_multiply', 'NULL') 196 slots.setdefault('nb_inplace_divide', 'NULL') 197 slots.setdefault('nb_inplace_remainder', 'NULL') 198 slots.setdefault('nb_inplace_power', 'NULL') 199 slots.setdefault('nb_inplace_lshift', 'NULL') 200 slots.setdefault('nb_inplace_rshift', 'NULL') 201 slots.setdefault('nb_inplace_and', 'NULL') 202 slots.setdefault('nb_inplace_xor', 'NULL') 203 slots.setdefault('nb_inplace_or', 'NULL') 204 slots.setdefault('nb_floor_divide', 'NULL') 205 slots.setdefault('nb_true_divide', 'NULL') 206 slots.setdefault('nb_inplace_floor_divide', 'NULL') 207 slots.setdefault('nb_inplace_true_divide', 'NULL') 208 slots.setdefault('nb_index', 'NULL') 209 210 code_sink.writeln(self.TEMPLATE % slots) 211 212class PySequenceMethods(object): 213 TEMPLATE = ''' 214static PySequenceMethods %(variable)s = { 215 (lenfunc) %(sq_length)s, 216 (binaryfunc) %(sq_concat)s, 217 (ssizeargfunc) %(sq_repeat)s, 218 (ssizeargfunc) %(sq_item)s, 219 (ssizessizeargfunc) %(sq_slice)s, 220 (ssizeobjargproc) %(sq_ass_item)s, 221 (ssizessizeobjargproc) %(sq_ass_slice)s, 222 (objobjproc) %(sq_contains)s, 223 /* Added in release 2.0 */ 224 (binaryfunc) %(sq_inplace_concat)s, 225 (ssizeargfunc) %(sq_inplace_repeat)s, 226}; 227 228''' 229 230 FUNCTION_TEMPLATES = { 231 "sq_length" : ''' 232static Py_ssize_t 233%(wrapper_name)s (%(py_struct)s *py_self) 234{ 235 PyObject *py_result; 236 Py_ssize_t result; 237 238 py_result = %(method_name)s(py_self); 239 if (py_result == NULL) { 240 return -1; 241 } 242 result = PyInt_AsSsize_t(py_result); 243 Py_DECREF(py_result); 244 return result; 245} 246 247''', 248 249 # This hacky version is necessary 'cause if we're calling a function rather than a method 250 # or an overloaded wrapper the args parameter gets tacked into the call sequence. 251 "sq_length_ARGS" : ''' 252static Py_ssize_t 253%(wrapper_name)s (%(py_struct)s *py_self) 254{ 255 PyObject *py_result; 256 PyObject *args; 257 Py_ssize_t result; 258 259 args = PyTuple_New (0); 260 py_result = %(method_name)s(py_self, args, NULL); 261 Py_DECREF(args); 262 if (py_result == NULL) { 263 return -1; 264 } 265 result = PyInt_AsSsize_t(py_result); 266 Py_DECREF(py_result); 267 return result; 268} 269 270''', 271 272 "sq_item" : ''' 273static PyObject* 274%(wrapper_name)s (%(py_struct)s *py_self, Py_ssize_t py_i) 275{ 276 PyObject *result; 277 PyObject *args; 278 279 args = Py_BuildValue("(i)", py_i); 280 result = %(method_name)s(py_self, args, NULL); 281 Py_DECREF(args); 282 if (PyErr_ExceptionMatches(PyExc_IndexError) || 283 PyErr_ExceptionMatches(PyExc_StopIteration)) { 284 Py_XDECREF(result); 285 return NULL; 286 } else { 287 return result; 288 } 289} 290 291 292''', 293 294 "sq_ass_item" : ''' 295static int 296%(wrapper_name)s (%(py_struct)s *py_self, Py_ssize_t py_i, PyObject *py_val) 297{ 298 PyObject *result; 299 PyObject *args; 300 301 args = Py_BuildValue("(iO)", py_i, py_val); 302 result = %(method_name)s(py_self, args, NULL); 303 Py_DECREF(args); 304 if (result == NULL) { 305 return -1; 306 } else { 307 Py_DECREF(result); 308 return 0; 309 } 310} 311 312''', 313 } 314 315 def __init__(self): 316 self.slots = {} 317 318 def generate(self, code_sink): 319 """ 320 Generates the structure. All slots are optional except 'variable'. 321 """ 322 323 slots = dict(self.slots) 324 325 slots.setdefault('sq_length', 'NULL') 326 slots.setdefault('sq_concat', 'NULL') 327 slots.setdefault('sq_repeat', 'NULL') 328 slots.setdefault('sq_item', 'NULL') 329 slots.setdefault('sq_slice', 'NULL') 330 slots.setdefault('sq_ass_item', 'NULL') 331 slots.setdefault('sq_ass_slice', 'NULL') 332 slots.setdefault('sq_contains', 'NULL') 333 slots.setdefault('sq_inplace_concat', 'NULL') 334 slots.setdefault('sq_inplace_repeat', 'NULL') 335 336 code_sink.writeln(self.TEMPLATE % slots) 337 338